[Rust] lifetime: async์ ์ฝ๋ฐฑ
2025.02.03 ์์ฑ
2025.02.23 ์์
Rust์ ๋ผ์ดํํ์ ์์คํ
์ด ์ด๋ ต๊ณ ๋ํดํ๋ค๊ณ ํ์ง๋ง, ์ฌ์ค ์ผ๋ฐ์ ์ธ ๊ฒฝ์ฐ์์๋ ๊ทธ๋ ๊ฒ ๋ฒฝ์ ๋๋๋งํ ๊ฒฝ์ฐ๊ฐ ๋ง์ง๋ ์๋ค.
๋จ์ํ๊ฒ ํจ์์ ์ฐธ์กฐ๋ฅผ ๋๊ธฐ๊ฑฐ๋ ํ๋ ๊ฒฝ์ฐ๋ ๋ฌธ์ ๊ฐ ๋ ๊ฒฝ์ฐ๊ฐ ์ ์๋ค.
ํ์ง๋ง ์ฐธ์กฐ์ async๊ฐ ๋ถ๊ณ ์ฝ๋ฐฑ๋ ์ฎ์ธ๋ค๋ฉด ๋จธ๋ฆฌ๊ฐ ์ํ์ง๊ธฐ ์์ํ๋ค.
๋ฌธ์ ์๋ ๊ฒฝ์ฐ
async๊ฐ ์๋๋ผ๋ฉด ๋ท๋ฉด์์์ ์ฝ๋ ์์ฑ์ด ๊ฑฐ์ ์ผ์ด๋์ง ์๊ธฐ๋ ํ๊ณ , ๋์ฒด๋ก๋ ๋ณ ๋ฌธ์ ๊ฐ ์๋ค.
์ฝ๋ฐฑํจ์๋ฅผ ๋ฐ์์ ์คํํ๋ retry ํจ์๋ฅผ ๋ง๋ ๋ค๊ณ ํ๋ฉด, ์ด๋ฐ ์์ผ๋ก ํ ์ ์์ ๊ฒ์ด๋ค.

์ ๋์ํ๋ค.
๊ทธ๋ฌ๋ฉด ์ฝ๋ฐฑ์ ๊ฐ๋ณ ์ฐธ์กฐ ๊ฐ์ ๊ฐ์ ํ๋ผ๋ฏธํฐ๋ก ๋๊ธฐ๋ฉด ์ด๋จ๊น? ์ฐธ์กฐ๋ผ์ ๋ฌธ์ ๊ฐ ์๊ธธ๊น?

๋๊ธฐ ์ฝ๋์์๋ ๋ณ๋ค๋ฅธ ๋ฌธ์ ๊ฐ ์๋ค.
๋ฌธ์ : async callback๊ณผ ์ฐธ์กฐ ์ ๋ฌ
๋ฌธ์ ๊ฐ ์๊ธฐ๋๊ฑด ๋ณดํต async๋ฅผ ์ธ๋๋ถํฐ๋ค.
ํ์ง๋ง ์ฝ๋ฐฑ์ด ํ๋ผ๋ฏธํฐ๋ฅผ ๋ฐ์ง ์๋๋ค๋ฉด ์ด ๋ํ ๋ฌธ์ ๋ ์๋ค.


๋ฌธ์ ๊ฐ ์๊ธฐ๋๊ฑด, async ์ฝ๋ฐฑ์ด ์ฐธ์กฐ ํ๋ผ๋ฏธํฐ๋ฅผ ๋ฐ์๋๋ถํฐ๋ค
async ์์ฒด๊ฐ ๋ฌธ์ ๋ผ๊ธฐ๋ณด๋จ, async๊ฐ trait์ผ๋ก ํ์ฅ๋๋ ๊ณผ์ ์์ ๋ฏธ๋ฌํ ๋ญ์๊ธฐ๋ค์ด ์๊ธฐ๋ ๊ฒ์ด๋ค.

์ด๋ฐ ์์ผ๋ก ์ง๋ฉด

์ฌ์ฉํ ๋ lifetime ๊ด๋ จ ์ค๋ฅ๊ฐ ๋์ถ๋๊ธฐ ์์ํ๋ค.
์ด๋ฌํ ์ค๋ฅ ๋ฉ์ธ์ง๋ ๊ด๋ จํด์ ์๋๊ฒ ์๋ค๋ฉด ์ง๊ด์ ์ผ๋ก ๋ฐ์๋ค์ด๊ธฐ ์ด๋ ต๋ค.
์ ๊ธฐ์ ๋ฌธ์ ๊ฐ ๋๊ฑด ํด๋ก์ ์ธ๋ฐ, ํ๋์ฉ ๊น๋ณด์.
|context: &mut Context| async {
println!("Hello, world!");
context.do_something();
Ok(())
}
์ผ๋จ ํด๋ก์ ์ ํ๋ผ๋ฏธํฐ ํ์
์ด (context: &'1 mut Context)๋ก ํด์๋๋ค.
๊ทธ๋ฆฌ๊ณ ํด๋ก์ ์ ๋ฐํ ํ์
(์ฌ๊ธฐ์๋ async block)์ด ๋ผ์ดํํ์ '2๋ก ์์๋๋ค.
ํ์ ์๊ทธ๋์ฒ๋ก ํํํ๋ฉด ์ด๋ ๊ฒ ํ๋ฆฐ๋ค๊ณ ๋ณด๋ฉด ๋๋ค.
(context: &'1 mut Context) ->
(impl Fn(&mut Context) -> impl '2 + Future<Output = anyhow::Result<()>>)
์ด๊ฒ๋ ์ด์ง๋ฝ๊ธด ํ๋ค.
์๋ฌดํผ ์ฌ๊ธฐ์ rust๊ฐ ๋งํ๋๊ฑด, '1 ์ฐธ์กฐ๊ฐ '2๋ณด๋ค ์ค๋ ์ด์์๋ค๋ ๋ณด์ฅ์ด ์๋ค๋ ๊ฒ์ด๋ค.
์ฌ์ค ๋ก์ง์์ผ๋ก๋ ๋ณ๋ค๋ฅธ ๋ฌธ์ ๊ฐ ์๊ธด ํ๋ฐ, parameter์ return Future ์ฌ์ด์ ์ด ๋ฏธ๋ฌํ ๊ฐ๊ทน์ rust ์ปดํ์ผ๋ฌ๊ฐ ์๋ฒฝํ ์ถ์ ์ ํ์ง๋ ๋ชปํด์ ์๊ธฐ๋ ๋ฌธ์ ๋ค.
์ด๋ค ์์ผ๋ก๋ผ๋ ์ด ๋ถ์ ๊ตํฉ์ ํด๊ฒฐํด์ผ ์ปดํ์ผ์ด ๋ ๊ฒ์ด๋ค. ์ฌ๊ธฐ์ 2๊ฐ์ง ์ ๋์ ๋ฐฉ๋ฒ์ด ์์๋๋ฐ, 1.85๋ถํฐ ๊น๋ํ ๋ฐฉ๋ฒ์ด ์๊ฒผ๋ค.
Best - async ํด๋ก์ ์ AsyncFn ํธ๋ ์ (since 1.85)
๋ง์ฝ ์ด๊ฑธ ๋ณด๋ ๋น์ ์ด 1.85 ๋ฒ์ ์ด์์ ์ด๋ค๋ฉด, async ํด๋ก์ ๋ฅผ ์ฌ์ฉํ๋๊ฒ ๊ฐ์ฅ ๊น๋ํ ํด๊ฒฐ์ฑ
์ด๋ค.
Fn ๋์ AsyncFn ๊ฐ์ async ํจ์์ฉ ํธ๋ ์์ผ๋ก ํจ์ ํ์
์ ์ ์ํ๊ณ

ํด๋ก์ ๋ฅผ ๋๊ธธ ๋๋ async ํด๋ก์ ๋ฅผ ๋๊ธฐ๋ ๊ฒ์ด๋ค.

๊ทธ๋ผ ์์ฃผ ๊น๋ํ๊ฒ ๋์ํ๋ค.

Legacy - ํด๊ฒฐ์ฑ 1: Pin Box
๊ฐ์ฅ ์ผ๋ฐ์ ์ธ ํด๊ฒฐ์ฑ
์, ํด๋ก์ ๊ฐ ๋ฐํํ๋ Future ๊ฐ ์์ฒด๋ฅผ Box๋ก ๋ฌถ๊ณ Pin์ผ๋ก ๊ณ ์ ํ๋ ๊ฒ์ด๋ค.
ํ์ฌ๋ก์๋ ํด๋ก์ ๋ฅผ ๋ฐ์์ ๋์ํ ์ ์๊ฒ ํ๋ ค๋ฉด ์ด ๋ฐฉ๋ฒ์ ์ ํํด์ผ ํ๋ค.
Future๋ฅผ generic์ผ๋ก ๋ฐํํ์ง ์๊ณ , Box์ ๊ฐ์ธ๊ณ Pin์ผ๋ก ๊ณ ์ ํด์ ๋ฐํํ ๋ก ํ๋ค.
๊ทธ๋ฆฌ๊ณ ํด๋ก์ ๋ฅผ ๋ฃ์ ๋๋ ๊ทธ ๋ฐํ๊ฐ์ด Pin<Box
๋ณดํต ์ด๋ ๊ฒ async ๋ธ๋ญ์ pin์ผ๋ก ๊ฑธ๋ฉด ๋๋ค.
๊ทธ๋ฌ๋ฉด ์ ๋์ํ ๊ฒ์ด๋ค.
์ฐธ๊ณ ๋ก futures crate์ ์๋ BoxFuture๊ฐ ์ด Pin<Box
Legacy - ํด๊ฒฐ์ฑ 2: callback ์ ์ฉ trait ์ ์
๊ตณ์ด ํด๋ก์ ๋ง๊ณ ํจ์๋ก ๋ฐ์๋ ๋๊ณ , Box ์์ด ์ฒ๋ฆฌํ๊ณ ์ถ๋ค๋ฉด ์กฐ๊ธ ์ฐํ์ ์ธ ๋ฐฉ๋ฒ์ด ์๋ค.
๊ฒฐ๊ตญ parameter์ return Future ์ฌ์ด์ lifetime์ ์ด๋ป๊ฒ ์ ์ฎ๊ณ ์ฐ๊ฒฐํด์ฃผ๊ธฐ๋ง ํ๋ฉด ๋๋ ๊ฑด๋ฐ, ๊ทธ๊ฒ ์๋ผ์ ์ด ๋๋ฆฌ๊ฐ ๋ฒ์ด์ง ๊ฒ์ด๋ค.
๊ทธ๊ฑธ ํํํ๋ ค๋ฉด ํ์ฌ๋ก์๋ trait์ ํ๋ ๋ฐ์ผ ํ๋ค. HRTB๋ ์จ์ผ ํ๋ค.
์ด๋ฐ ์์ผ๋ก ์ ์ํด์ฃผ๊ณ
๊ทธ๊ฑธ ์ฝ๋ฐฑ ํ์
์ผ๋ก ๋ฐ์ผ๋ฉด ๋๋ค.

๊ทธ๋ผ ์ ๋์ํ ๊ฒ์ด๋ค.
๋ค๋ง ์ด๊ฑด ํด๋ก์ ๋ฅผ ์ฐ์ง ๋ชปํ๋ค๋๊ฒ ๋จ์ ์ด๋ค.
์ฐธ์กฐ
https://users.rust-lang.org/t/lifetime-bounds-to-use-for-future-that-isnt-supposed-to-outlive-calling-scope/89277/2
https://users.rust-lang.org/t/asynchronous-wrapper-function-taking-a-reference/89940/2