[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