[Python] anyio - ํ•œ ์ธต ๋” ๊ฐ•ํ™”๋œ ๋น„๋™๊ธฐ ํŒจ๋Ÿฌ๋‹ค์ž„

๋ฐ˜์‘ํ˜•

์–ด๋Š๋ง ์‹ค๋ฌด์—์„œ Python ๋ฐฑ์—”๋“œ ์—”์ง€๋‹ˆ์–ด๋กœ ๋ณด๋‚ธ์ง€ 1๋…„์ด ์กฐ๊ธˆ ๋„˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋งŽ์€ ๊ณ ๋ฏผ๊ณผ ๊ณ ๋‚œ, ๊ทธ๋ฆฌ๊ณ  ์ด ์ž๋ฆฌ์— ์˜ค๊ธฐ๊นŒ์ง€ ์ˆ˜๋งŽ์€ ๋ฐ˜์„ฑ๊ณผ ๋…ธ๋ ฅ์œผ๋กœ ํŒŒ์ด์ฌ ๋ฐฑ์—”๋“œ ์—”์ง€๋‹ˆ์–ด๋กœ์จ์˜ ์ž๋ฆฌ๋ฅผ ์žก์•˜๋˜ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. 

 

์˜ค๋Š˜ ์ด์•ผ๊ธฐ๋ฅผ ์œ„ํ•ด ๋‹จ๋„์ง์ž…์ ์œผ๋กœ ๋ง์”€๋“œ๋ฆฌ์ž๋ฉด Python์€ Java์˜ Spring๊ณผ ๋‹ฌ๋ฆฌ ๋™๊ธฐ ์ฒ˜๋ฆฌ๋ณด๋‹ค๋Š” ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ๊ฐ€ ๋” ๋‚˜์€ ๋น›์˜ ์„ฑ๋Šฅ์„ ๋ณด์ธ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ํŒŒ์ด์ฌ์˜ ๋น„๋™๊ธฐ ํŒจ๋Ÿฌ๋‹ค์ž„์€ ๊ทธ ์—ญ์‚ฌ๊ฐ€ ๋งค์šฐ ๋ณต์žกํ•˜๋‹ค๊ณ  ํ•  ์ˆ˜ ์žˆ์„ ์ •๋„๋กœ ์ˆ˜๋งŽ์€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์žˆ๊ณ  ๊ทธ ๋งˆ์ €๋„ ์“ฐ๊ธฐ ์–ด๋ ค์šด ๋ถ€๋ถ„์— ์†ํ•ฉ๋‹ˆ๋‹ค.

 

 

Coroutine๊ณผ asyncio

Python์˜ ๋™์‹œ์„ฑ ์ฒ˜๋ฆฌ๋Š” Thread, Process์™€ ๊ฐ™์ด ๋™๊ธฐ์ ์ธ ๋ฐฉ๋ฒ•์œผ๋กœ ์ˆ˜ํ–‰๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ Process๋ฅผ ์ด์šฉํ•œ ๋™์‹œ์„ฑ ์ฒ˜๋ฆฌ๋Š” Context switching๊ณผ ๊ฐ™์€ ๋ณ‘๋ชฉ์„ ์œ ๋ฐœํ–ˆ๊ณ , ๊ทธ๋ฅผ ๋Œ€์ฒดํ•ด ๋‚˜์˜จ ๊ฒƒ์ด ๋ฐ”๋กœ Thread ์ด์ง€๋งŒ ๊ณต๊ต๋กญ๊ฒŒ๋„ Python์˜ ๋ฉ€ํ‹ฐ ์Šค๋ ˆ๋”ฉ์€ GIL๋กœ ์ธํ•œ ์ž์› ์ ์œ  ์ด์Šˆ ์†”๋ฃจ์…˜ ๋•Œ๋ฌธ์— ํ†ต์ƒ์ ์ธ ๋ฉ€ํ‹ฐ ์Šค๋ ˆ๋“œ ๋ฐฉ์‹ ๋™์‹œ์„ฑ ์ฒ˜๋ฆฌ๋ณด๋‹ค ๋Š๋ฆฐ ์„ฑ๋Šฅ์„ ๋ณด์ž…๋‹ˆ๋‹ค.

 

๊ทธ๋ž˜์„œ ๋‚˜ํƒ€๋‚œ ๊ฒƒ์ด ๋ฐ”๋กœ Coroutine์ž…๋‹ˆ๋‹ค. Coroutine์€ ํƒˆ์ถœ ์ง€์ (return ์ง€์ )์ด ์ž์œ ๋กœ์šด ํ•จ์ˆ˜๋ฅผ ์ผ์ปซ๋Š” ๋ง๋กœ ์šฐ๋ฆฌ๊ฐ€ ํ†ต์ƒ ๊ตฌํ˜„ํ•˜๋Š” ํ•จ์ˆ˜๋Š” return ์ง€์ ์ด ์ •ํ•ด์ ธ ์žˆ์–ด, ๊ทธ ์ง€์ ์„ ๋น ์ ธ ๋‚˜๊ฐ€์•ผ๋งŒ ๋‹ค์Œ ์ž‘์—…์„ ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐ˜๋ฉด Coroutine์€ ๊ทธ ์ง€์ ์ด ์–ด๋Š ์‹œ์ ์—์„œ๋“ ์ง€ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค.

 

ํ•˜์ง€๋งŒ Python์˜ Coroutine์€ ์‚ฌ์šฉํ•˜๊ธฐ ๊ฐ„๋‹จํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. (์–ด์ฉŒ๋ฉด Javascript์˜ Promise ๋ณด๋‹ค๋„ ๋” ๋ณต์žกํ• ์ง€๋„..) ์ด ์ฝ”๋ฃจํ‹ด์ด ๊ฐ„๋‹จํ•ด์ง€๊ธฐ๊นŒ์ง€ Python ์ง„์˜์—์„œ๋Š” 3๊ฐ€์ง€ ์ฝ”๋ฃจํ‹ด ๊ตฌํ˜„ ๋ฐฉ๋ฒ•์ด ์กด์žฌํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

 

(์•„๋ž˜์˜ ํ•ญ๋ชฉ๋“ค์„ ํด๋ฆญํ•˜๋ฉด ์ž์„ธํ•œ ์ฝ”๋“œ๋ฅผ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.)

 

  • ๋”๋ณด๊ธฐ

    Python์˜ Generator๋Š” ๊ฐ’์„ ์ƒ์„ฑํ•˜๋Š” ํ•จ์ˆ˜๋กœ yield ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค. ํ•จ์ˆ˜๊ฐ€ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•œ ํ›„ ์Šค์ฝ”ํ”„๋ฅผ ์†Œ๋ฉธํ•œ ๋‹ค์Œ, ๋‹ค์‹œ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ์ฒ˜์Œ๋ถ€ํ„ฐ ๋‹ค์‹œ ์‹œ์ž‘ํ•˜๋Š” ๊ธฐ๋Šฅ์ธ๋ฐ, ์ด ๊ธฐ๋Šฅ์„ ์ผ์‹œ ์ค‘์ง€๋กœ ์‚ฌ์šฉํ•˜๋ฉฐ ์ฝ”๋ฃจํ‹ด์„ ๊ตฌํ˜„ํ•œ ๋ฐฉ๋ฒ•์ด ๋ฐ”๋กœ Generator based corutine ์ž…๋‹ˆ๋‹ค.

    ํ•˜์ง€๋งŒ ์ด๋Ÿฌํ•œ syntax๋Š” ์ด ๋ฌธ๋ฒ•์ด ํ•จ์ˆ˜์ธ์ง€, ์ œ๋„ค๋ ˆ์ดํ„ฐ์ธ์ง€, ํ˜น์€ ์ฝ”๋ฃจํ‹ด์ธ์ง€๋ฅผ ๊ตฌ๋ถ„ํ•˜๊ธฐ ์–ด๋ ต๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค. ์œ„์˜ ์ฝ”๋“œ๋Š” ์ฝ”๋ฃจํ‹ด์ด๋ฉฐ ํ•จ์ˆ˜ ์ปจํ…์ŠคํŠธ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ฌ ๋•Œ yield๋ฅผ ํ†ตํ•ด ์ผ์‹œ์ค‘์ง€ํ•˜๊ณ  ๊ทธ ๊ฐ’์„ ๊ฐ€์ ธ์˜ค๋Š” ๋ชจ์Šต์ž…๋‹ˆ๋‹ค.

    ์ด๋ฅผ ์šฐ๋ฆฌ๋Š” ์ œ๋„ค๋ ˆ์ดํ„ฐ ๊ธฐ๋ฐ˜ ์ฝ”๋ฃจํ‹ด์ด๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

  • ๋”๋ณด๊ธฐ

    asyncio์˜ ๋ชจ๋“ˆ์„ ์ด์šฉํ•˜์—ฌ ์ฝ”๋ฃจํ‹ด์„ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•์ธ๋ฐ, ์‚ฌ์‹ค์ƒ ์ œ๋„ค๋ ˆ์ดํ„ฐ ๊ธฐ๋ฐ˜ ์ฝ”๋ฃจํ‹ด๊ณผ ๋‹ค๋ฅธ์ ์€ asyncio ๋ชจ๋“ˆ ์œ„์—์„œ ๋™์ž‘์‹œํ‚จ ๋‹ค๋Š” ๊ฒƒ์˜ ์ฐจ์ด์ž…๋‹ˆ๋‹ค.

    ์ œ๋„ค๋ ˆ์ดํ„ฐ ๊ธฐ๋ฐ˜์˜ ์ฝ”๋ฃจํ‹ด์ด ํŒŒ์ด์ฌ์˜ ์Šค์ฝ”ํ”„์— ์˜ํ•ด ๋™์ž‘๋˜๋Š” ๊ฒƒ์ด๋ผ๋ฉด asyncio๋Š” ์ด๋ฒคํŠธ ๋ฃจํ”„์— ํ•ด๋‹นํ•˜๋ฉฐ ํ๋ฅผ ์ด์šฉํ•ด ํƒœ์Šคํฌ๋ฅผ ์ ์žฌํ•˜๊ณ  ์ผ์‹œ ์ค‘์ง€๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ์ƒํƒœ๋ฅผ ์ €์žฅํ•œ ๋‹ค์Œ ๊ทธ ์ƒํƒœ์— ๋”ฐ๋ผ ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰์‹œ์ผœ์ฃผ๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค. 

    ์œ„ ์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด yield from ํ‚ค์›Œ๋“œ๊ฐ€ ๋ณด์ด๋Š”๋ฐ, yield from์€ yield ๋ฐ˜๋ณต๋ฌธ์„ ๊ฐ„๋‹จํ•˜๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•œ syntax๋กœ ๋ณธ๋ž˜๋Š” for x in asyncio.sleep(random.randint(0, 5)): yield x ์ฝ”๋“œ๋ฅผ ์ค„์ธ ๊ฒƒ์ž…๋‹ˆ๋‹ค. 

    ์ด์ฒ˜๋Ÿผ asyncio ๋ชจ๋“ˆ์„ ์ด์šฉํ•ด ๋น„๋™๊ธฐ๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ asyncio ๋ชจ๋“ˆ ๊ธฐ๋ฐ˜ ์ฝ”๋ฃจํ‹ด์ด๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

  • ๋”๋ณด๊ธฐ

    ๋„ค์ดํ‹ฐ๋ธŒ ์ฝ”๋ฃจํ‹ด์€ Python 3.5์—์„œ ๋“ฑ์žฅํ•œ ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ ๋งค์ปค๋‹ˆ์ฆ˜์œผ๋กœ async-await ํ‚ค์›Œ๋“œ๊ฐ€ ์—ฌ๊ธฐ์— ํ•ด๋‹นํ•ฉ๋‹ˆ๋‹ค.

    ํ•จ์ˆ˜์˜ ์„ ์–ธ์€ def๊ฐ€ ์•„๋‹Œ async def๋ฅผ ์ด์šฉํ•˜๊ณ  ์žˆ์œผ๋ฉฐ ๊ฐ’์˜ ๋ฐ˜ํ™˜ ์—ญ์‹œ yield๋‚˜ yield from์ด ์•„๋‹Œ await๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋Š” ๋ชจ์Šต์ž…๋‹ˆ๋‹ค. ์ง€๊ธˆ ๋Œ€๋ถ€๋ถ„์˜ ํŒŒ์ด์ฌ ๊ฐœ๋ฐœ์ž ๋ถ„๋“ค์ด ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ์‹์ผ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

 

๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ ๋งค์ปค๋‹ˆ์ฆ˜์— ๋Œ€ํ•ด์„œ๋Š” ๋‹น์‹œ Javascript ์ง„์˜์—์„œ๋„ ํ™”๋‘๊ฐ€ ๋˜์—ˆ๋˜ ๊ฒƒ์ด์—ˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ด๋Ÿฐ ๋‹ค์–‘ํ•œ ๋งค์ปค๋‹ˆ์ฆ˜๋“ค์€ ์˜คํžˆ๋ ค ๋ ˆ๊ฑฐ์‹œ ์ฒ˜๋ฆฌ๋ฅผ ์–ด๋ ต๊ฒŒ ํ•˜๋Š” ๋ถ€๋ถ„์ด ์žˆ๊ณ , ์ด๋ฒคํŠธ ๋ฃจํ”„ ๋ชจ๋“ˆ์— ๋Œ€ํ•œ ์‚ฌ์šฉ๋ฒ•์„ ์•Œ์•„์•ผํ•˜๋Š” ๋“ฑ ํŒŒ์ด์ฌ์œผ๋กœ ๋น„๋™๊ธฐ๋ฅผ ๊ฐœ๋ฐœํ•˜๋Š” ๋ฐ ์žˆ์–ด์„œ ๋†’์€ ๋Ÿฌ๋‹ ์ปค๋ธŒ๋ฅผ ๋ณด์ด๊ฒŒ ํ–ˆ์Šต๋‹ˆ๋‹ค.

 

์ด์™€ ๋น„์Šทํ•˜๊ฒŒ Javascript V8์˜ ๊ฒฝ์šฐ๋„ ์‹ฑ๊ธ€ ์Šค๋ ˆ๋“œ์˜ ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ๋ฅผ ์ด์šฉํ•˜์ง€๋งŒ ์ด๋Ÿฌํ•œ ์ด๋ฒคํŠธ ๋ฃจํ”„์— ๋Œ€ํ•ด์„œ๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ ์‹ ๊ฒฝ์“ฐ์ง€ ์•Š์•„๋„ ๋˜์–ด ์‚ฌ์‹ค์ƒ ๊ฐœ๋ฐœ์ž๊ฐ€ ์‰ฝ๊ฐœ ์„œ๋ฒ„ ๊ฐœ๋ฐœ์— ์ง‘์ค‘ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ฃผ๋Š” ์ ๊ณผ ๋‹ค์†Œ ์ฐจ์ด๋ฅผ ๋ณด์ž…๋‹ˆ๋‹ค.

 

 

 

asyncio์˜ ๋ณต์žก์„ฑ

asyncio๋Š” ์–ผํ• ์ด ๊ธ€๋กœ๋งŒ ๋ณด๋ฉด ๋‹จ์ˆœํ•œ ์ด๋ฒคํŠธ ๋ฃจํ”„์ฒ˜๋Ÿผ ๋ณด์ด์ง€๋งŒ ๊ทธ ๋‚ด๋ถ€์—์„œ๋Š” ๋ฌด์ˆ˜ํžˆ ๋งŽ์€ ๊ธฐ๋Šฅ๋“ค์„ ํฌํ•จํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋ถ„๋ช… asyncio๋Š” ๋ชจ๋“ˆ ์ž์ฒด๋Š” ํ›Œ๋ฅญํ–ˆ์ง€๋งŒ ์žฅ๋ฒฝ ๋†’์€ ์ ‘๊ทผ์„ฑ์€ ๊ฐœ๋ฐœ์ž๋“ค์—๊ฒŒ ์˜คํžˆ๋ ค ๊ฑฐ๋ฆฌ๊ฐ๋งŒ ์ฃผ๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

 

์ € ๋˜ํ•œ asyncio ๋ชจ๋“ˆ์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์ง€๋งŒ asyncio๋Š” ๋‹จ์ˆœํ•œ ์ด๋ฒคํŠธ ๋ฃจํ”„๊ฐ€ ์•„๋‹ˆ์—ˆ์Šต๋‹ˆ๋‹ค. ์‹ค์ œ๋กœ ์ œ๊ฐ€ ์ƒ๊ฐํ•˜๋Š” ์ด๋ฒคํŠธ ๋ฃจํ”„, ์—ฌ๋Ÿฌ๋ถ„๋“ค์ด ์ƒ๊ฐํ•˜๋Š” ์ด๋ฒคํŠธ ๋ฃจํ”„๋Š” ๊ฐ ๋‹จ์ผ ์Šค๋ ˆ๋“œ ๋‹น ํ•˜๋‚˜์˜ ์ด๋ฒคํŠธ ๋ฃจํ”„๋ฅผ ๊ฐ€์ง€๋Š” ๊ฒƒ์œผ๋กœ ์ƒ๊ฐํ•˜์‹ค ๊ฒ๋‹ˆ๋‹ค.

 

 

ํ•˜์ง€๋งŒ Python์˜ asyncio๋Š” ์ด์™€ ๊ฐ™์ด ๋™์ž‘ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋ฉ”์ธ ์Šค๋ ˆ๋“œ์—์„œ get_event_loop ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•ด ์ด๋ฒคํŠธ ๋ฃจํ”„๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ, ์ด๋ฅผ ๋‹ค๋ฅธ ์„œ๋ธŒ ์Šค๋ ˆ๋“œ๋ฅผ ๋งŒ๋“ค๊ณ  ์ƒ์„ฑํ•˜๋ฉด ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

 

๋งŒ์•ฝ ์„œ๋ธŒ ์Šค๋ ˆ๋“œ์—์„œ ์ด๋ฒคํŠธ ๋ฃจํ”„๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด set_event_loop ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ๋ฉ”์ธ ์Šค๋ ˆ๋“œ์—์„œ ์ƒ์„ฑํ•œ ์ด๋ฒคํŠธ ๋ฃจํ”„๋ฅผ ๋ฐ”์ธ๋”ฉํ•˜์—ฌ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ๋ฉ”์ธ ์Šค๋ ˆ๋“œ์™€ ์„œ๋ธŒ ์Šค๋ ˆ๋“œ๊ฐ€ ๊ฐ™์€ ์ด๋ฒคํŠธ ๋ฃจํ”„๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

 

์„œ๋ธŒ ์Šค๋ ˆ๋“œ์—์„œ ๋…๋ฆฝ๋œ ๋‹ค๋ฅธ ์ด๋ฒคํŠธ ๋ฃจํ”„๋ฅผ ์‚ฌ์šฉํ•˜๊ณ ์ž ํ•˜๋Š” ๊ฒฝ์šฐ new_event_loop ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿฐ๋ฐ, ๋ฌธ์ œ์ ์€ ์ด๋Ÿฐ ๊ฒฝ์šฐ ์„œ๋ธŒ ์Šค๋ ˆ๋“œ์—์„œ get_event_loop๋ฅผ ํ˜ธ์ถœํ–ˆ์„ ๋•Œ ์œ„์—์„œ ์ƒ์„ฑํ•œ ์ƒˆ๋กœ์šด ์ด๋ฒคํŠธ ๋ฃจํ”„๊ฐ€ ๋ฐ˜ํ™˜๋˜์–ด์•ผ ํ•˜์ง€๋งŒ ๊ทธ๋ ‡์ง€ ์•Š๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

 

์ด๋Ÿฌํ•œ ๋ฌธ์ œ๋Š” ์˜คํžˆ๋ ค asyncio๋ฅผ ์ดํ•ดํ•˜๊ธฐ ์–ด๋ ต๋‹ค๋Š” ํ”ผ๋“œ๋ฐฑ์œผ๋กœ ๋‚จ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

 

 

 

 

anyio

asyncio๊ฐ€ ํŒŒ์ด์ฌ ๋น„๋™๊ธฐ์— ๊ฑฐ์˜ ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ ๊ฒŒ์žฌ๋œ ๊ฒƒ์€ ๋งž์ง€๋งŒ ์—ฌ์ „ํžˆ ํŒŒ์ด์ฌ์—์„œ ๋น„๋™๊ธฐ๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋Š” ๋‹ค์–‘ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค. ๊ทธ ์ค‘์—์„œ anyio๋Š” ํ˜„์žฌ FastAPI(์ •ํ™•ํžˆ๋Š” ์˜ค๋ฆฌ์ง€๋„ ํ”„๋ ˆ์ž„์›Œํฌ์ธ Starlette)์—์„œ ์‚ฌ์šฉ ์ค‘์ธ ๋น„๋™๊ธฐ ๋ชจ๋“ˆ์— ํ•ด๋‹นํ•ฉ๋‹ˆ๋‹ค.

 

anyio๋Š” ์ƒˆ๋กœ์ด ๊ฐœ์ฒ™๋œ ๋น„๋™๊ธฐ ๋ชจ๋“ˆ์ด ์•„๋‹Œ asyncio ํ˜น์€ trio ์œ„์—์„œ ๋™์ž‘ํ•˜๋Š” ๊ทธ๋“ค์˜ ๊ตฌํ˜„์ฒด์— ํ•ด๋‹นํ•ฉ๋‹ˆ๋‹ค. asyncio๋Š” ๊ทธ ๊ธฐ๋Šฅ์ด ํ›Œ๋ฅญํ–ˆ์ง€๋งŒ ์‚ฌ์šฉ์ด ์–ด๋ ค์›Œ ๋Š˜ ๋ถ€์ •์ ์ธ ํ”ผ๋“œ๋ฐฑ์„ ๋ฐ›์•˜๊ณ , trio ์—ญ์‹œ ๊ฐ„๋‹จํ•œ ์‚ฌ์šฉ์„ฑ์œผ๋กœ ๋‚ด์„ธ์› ์ง€๋งŒ ๊ธฐ๋Šฅ์ด ๋ถ€์‹คํ•ด ์ฐจ๊ฐ€์šด ์‹œ์„ ์„ ๋ฐ›์•˜๋˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ž…๋‹ˆ๋‹ค.

 

anyio์˜ ํŠน์ง•์€ trio๊ฐ€ ๊ฐ€์ง„ async-await์˜ ์•„์ฃผ ๊ฐ„๋‹จ๋ช…๋ฃŒํ•œ ๊ฐœ๋…์„ asyncio์— ์ ‘๋ชฉ ์‹œํ‚จ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ž…๋‹ˆ๋‹ค. ์ œ๋„ค๋ ˆ์ดํ„ฐ ์ฝ”๋ฃจํ‹ด์ด๋‚˜ ๋ชจ๋“ˆํ™” ์ฝ”๋ฃจํ‹ด๊ณผ ๊ฐ™์€ ๊ตฌ์กฐํ™”๋œ ๋™์‹œ์„ฑ ๊ฐœ๋…์ด ์—†์–ด ์‚ฌ์šฉ์ด ํŽธ๋ฆฌํ•˜๊ณ  ๊ฐœ๋ฐœ์— ๋”์šฑ ์ง‘์ค‘ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค.

 

๋จผ์ € ์„ค์น˜๋ถ€ํ„ฐ ์ฐจ๊ทผ์ฐจ๊ทผ ํ•ด๋ณด๊ณ  ๋ฌด์—‡์ด ๋‹ค๋ฅธ์ง€๋ฅผ ์•Œ์•„๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

 

 

 

Installation

anyio๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” Python 3.6.2 ๋ฒ„์ „ ์ด์ƒ์„ ์‚ฌ์šฉํ•ด์•ผ ํ•˜์ง€๋งŒ ๋ชจ๋“  ๊ธฐ๋Šฅ์„ ์•ˆ์ „ํ•˜๊ฒŒ ๋™์ž‘ํ•˜๊ธธ ์›ํ•œ๋‹ค๋ฉด Python 3.7 ๋ฒ„์ „ ์ด์ƒ ์‚ฌ์šฉ์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค.

$ pip install anyio
$ pip install anyio[trio]

asyncio๊ฐ€ ์•„๋‹Œ trio๋ฅผ ๋ฐฑ์—”๋“œ๋กœ ์‚ฌ์šฉํ•˜๊ณ ์ž ํ•˜๋Š” ๊ฒฝ์šฐ extra ์˜ต์…˜์— trio๋ฅผ ๋„ฃ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

 

 

Create Task

๊ฐ„๋‹จํ•œ ํƒœ์Šคํฌ๋ฅผ ํ•˜๋‚˜ ๋งŒ๋“ค์–ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

 

 

anyio์—์„œ ์ž‘์—…์„ ์ˆœ์ฐจ์ ์œผ๋กœ ์ƒ์„ฑํ•ด ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ๊ฐ€ ๋˜๋Š”์ง€๋ฅผ ๋ณด๊ธฐ ์œ„ํ•ด์„œ create_task_group์„ ์ด์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด task_group์€ ํŒŒ์ด์ฌ์˜ ๋น„๋™๊ธฐ ์ปจํ…์ŠคํŠธ ๊ด€๋ฆฌ์ž๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๊ณ , ํ•จ์ˆ˜์— ์ธ์ž๋ฅผ ๋„ฃ์œผ๋ ค๋ฉด task_group์˜ start_soon ๋ฉ”์„œ๋“œ๋ฅผ ์ด์šฉํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

 

๊ทธ๋Ÿฌ๋ฉด ์ˆœ์ฐจ์ ์œผ๋กœ Task 0 ~ 5 running์ด ์‹คํ–‰๋˜์—ˆ๋‹ค๊ฐ€ 1์ดˆ ๋’ค finished๊ฐ€ ๋‚˜ํƒ€๋‚˜๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

 

 

Handling Exception

๋™์‹œ์„ฑ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ํ•˜๋‹ค๋ณด๋ฉด ๋™์‹œ ๋‹ค๋ฐœ์ ์œผ๋กœ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜๋„ ์žˆ๋Š”๋ฐ, ์ด๋Ÿฐ ๋‹ค๋ฐœ์  ์˜ค๋ฅ˜๋ฅผ anyio์—์„œ๋Š” ํ•œ ๋ฒˆ ์˜ค๋ฅ˜ ๋ฐœ์ƒ์œผ๋กœ ๋๋‚˜๋Š” ๊ฒƒ์ด ์•„๋‹Œ ๋ชจ๋“  ์˜ค๋ฅ˜๋ฅผ ๋‚ด๋ฑ‰์–ด ์ค˜์•ผํ•œ๋‹ค. ์ฆ‰, ๋™์‹œ ๋‹ค๋ฐœ์ ์ธ ์˜ค๋ฅ˜๋Š” ๊ทธ ์—ญ์ถ”์ ์„ ๋ชจ๋‘ ํฌํ•จํ•ด์•ผ ํ•œ๋‹ค๋ผ๋Š” ๋งˆ์ธ๋“œ๋ฅผ ๊ฐ€์ง€๊ณ  ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค.

 

anyio๋Š” ๋ฐ”๋กœ ์œ„์˜ task_group๊ณผ ๋น„์Šทํ•œ ExceptionGroup์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

 

 

์ฝ”๋“œ ๊ตฌํ˜„๋Œ€๋กœ running ๊นŒ์ง€๋Š” ๋ชจ๋‘ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ ๋‹ค์Œ์— ๋‚˜์˜ค๋Š” ๊ฒƒ์ด ๋ฐ”๋กœ ExceptionGroup์ธ๋ฐ, ๊ทธ ๋ฐ‘์œผ๋กœ ์–ด๋–ค ์˜ค๋ฅ˜๊ฐ€ ๋‚˜ํƒ€๋‚ฌ๋Š”์ง€๋ฅผ ์•Œ๋ ค์ค๋‹ˆ๋‹ค.

 

๊ตฌํ˜„๋Œ€๋กœ ๋ช‡ ๋ฒˆ์งธ ๋ผ์ธ์—์„œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ๋Š”์ง€๋ฅผ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค. 

 

์—ฌ๊ธฐ์„œ ์ฃผ์˜ํ•ด์•ผํ•  ์ ์€ ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ์ด๊ธฐ ๋•Œ๋ฌธ์— ์˜ค๋ฅ˜ ๋ฐœ์ƒ์˜ ์ˆœ์„œ๋Š” ๋ณด์žฅ๋˜์ง€ ์•Š๋Š”๋‹ค๋Š” ์ ์ž…๋‹ˆ๋‹ค. ํ™”๋ฉด์—์„œ๋Š” running์ด ๋ชจ๋‘ print ๋˜๊ณ  ๋‚œ ๋‹ค์Œ Exception์ด ํ•ธ๋“ค๋ง ๋˜์—ˆ์ง€๋งŒ ๋•Œ๋กœ๋Š” ๋ชจ๋‘ finished ๋œ ๋‹ค์Œ์— Error๊ฐ€ ํ•ธ๋“ค๋ง ๋˜๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค.

 

 

 

Synchronization primitives

๋ชจ๋“  ๋™์‹œ์„ฑ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ anyio์—๋„ Lock(๋ฝ), Semaphore(์„ธ๋งˆํฌ์–ด), Event(์ด๋ฒคํŠธ) ๋“ฑ ์ž‘์—…์„ ์กฐ์ •ํ•˜๊ธฐ ์œ„ํ•œ ๋ชจ๋“  ๋™๊ธฐํ™” ์š”์†Œ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. 

 

  • Event (์ด๋ฒคํŠธ)
  • Semaphore (์„ธ๋งˆํฌ์–ด)
  • Lock (๋ฝ)
  • Condition (์ปจ๋””์…˜)
  • Capacity Limiter (์šฉ๋Ÿ‰ ๋ฆฌ๋ฏธํ„ฐ)

์—ฌ๊ธฐ์„œ ์šฐ๋ฆฌ๋Š” ๋‹ค์†Œ ์ƒ์†Œํ•œ Event์™€ Capacity Limiter ๋‘ ๊ฐ€์ง€๋งŒ์„ ์˜ˆ์‹œ๋กœ ๋‹ค๋ค„๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

 

์œ„ ์ฝ”๋“œ๋Š” 10๊ฐœ์˜ Task๊ฐ€ event๋ผ๋Š” ์ž์› ํ•œ ๊ฐœ์— ๋Œ€ํ•œ ๋™์‹œ ์ ‘๊ทผ ์ œํ•œ ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค. Event๋Š” ์žฌ์‚ฌ์šฉ๋˜์ง€ ๋ชปํ•˜๊ณ  ํ•œ ๋ฒˆ ์‚ฌ์šฉํ•œ ๋’ค์—” ๋ฒ„๋ ค์ง€๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๋งŒ์•ฝ ํ•ด๋‹น ์ด๋ฒคํŠธ๋ฅผ ์žฌ์‚ฌ์šฉํ•˜๊ณ ์ž ํ•œ๋‹ค๋ฉด ๋˜‘๊ฐ™์€ ์ด๋ฒคํŠธ ์ธ์Šคํ„ด์Šค๋ฅผ ํ•œ ๊ฐœ ๋” ๋งŒ๋“ค์–ด ์‹คํ–‰ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

Capacity Limiter์˜ ์ •ํ™•ํ•œ ํ•ด์„์€ ์–ด๋–ป๊ฒŒ ๋˜๋Š”์ง€ ๋ชจ๋ฅด๊ฒ ์ง€๋งŒ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ์„ธ๋งˆํฌ์–ด์™€ ๋น„์Šทํ•ฉ๋‹ˆ๋‹ค. ํ‘œํ˜„ํ•œ๋‹ค๋ฉด ์—ฌ๋Ÿฌ๊ฐœ์˜ ์„ธ๋งˆํฌ์–ด๋ฅผ ํ•˜๋‚˜์˜ ๊ฐ์ฒด๋กœ ์‚ฌ์šฉํ•œ๋‹ค๋Š” ๊ฒƒ์ด ๋งž์„ ์ˆ˜๋„ ์žˆ์„ ๊ฒƒ ๊ฐ™๋„ค์š”.

 

๋ฆฌ๋ฏธํ„ฐ๋ฅผ 2๊ฐœ๋กœ ์ฃผ๊ณ  10๊ฐœ์˜ Task๋ฅผ ์‹คํ–‰์‹œํ‚ต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ์ตœ์ดˆ๋กœ ๋ฐ›์€ 2๊ฐœ์˜ Task๊ฐ€ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

 

๊ทธ๋Ÿฐ ๋’ค์—๋Š” ํ์— ์Œ“์ธ๋Œ€๋กœ ๋งˆ์ง€๋ง‰์— ๋“ค์–ด๊ฐ„ Task๊ฐ€ ๊ทธ ๋‹ค์Œ ์ž์›์„ ํ™•๋ณดํ•˜๊ณ  ์ˆœ์ฐจ์ ์œผ๋กœ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. 

 

anyIO์— ๋Œ€ํ•ด ๋” ์•Œ์•„๋ณด๊ณ  ์‹ถ๋‹ค๋ฉด ์•„๋ž˜์˜ ๋งํฌ๋ฅผ ์ฐธ๊ณ ํ•ด๋ณด์„ธ์š”.

 

https://anyio.readthedocs.io/en/stable/index.html

 

AnyIO — AnyIO 3.4.0 documentation

© Copyright 2018, Alex Grönholm. Revision 5376d62a.

anyio.readthedocs.io

 

 

๋งˆ์น˜๋ฉฐ..

์ด๋ฒˆ ํฌ์ŠคํŠธ์—์„œ๋Š” Python์œผ๋กœ 1๋…„ ๋™์•ˆ ๋ฐฑ์—”๋“œ ์—”์ง€๋‹ˆ์–ด๋งํ•˜๋ฉด์„œ ์–ป์€ ๋น„๋™๊ธฐ ์ง€์‹, ๊ทธ๋ฆฌ๊ณ  ๊ทธ์— ๋Œ€ํ•œ ๊ฐ„๋‹จํ•œ ํ›„๊ธฐ๋ฅผ ํฌํ•จํ•˜์—ฌ ํ˜„ Python์˜ ํ˜„ํ™ฉ์— ๋Œ€ํ•ด ์ ์–ด๋ณด๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

 

์•„๋งˆ Java๋‚˜ Javascript๋ฅผ ์ด์šฉํ•˜๊ณ  ๊ณ„์‹  ๋ฐฑ์—”๋“œ ์—”์ง€๋‹ˆ์–ด ๋ถ„๋“ค์ด ์ด ๊ธ€์„ ๋ณด์‹ ๋‹ค๋ฉด "๋‚ด๊ฐ€ ์•Œ๊ณ  ์žˆ๋Š” Python์ด ์ด๋ ‡๊ฒŒ ์–ด๋ ค์šด ๊ฑฐ์˜€๋‚˜..?"๋ผ๋Š” ๋ง์”€์ด๋‚˜ ์ƒ๊ฐ์„ ํ•˜์‹ค์ง€๋„ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๊ณผ๊ฑฐ์— ๋น„ํ•˜๋ฉด ๋งŽ์ด ์‰ฌ์›Œ์ง€๊ณ  ์žˆ๋‹ค๋Š” ๊ฒƒ์€ ๋งž๊ณ , ๋‹ค๋ฅธ ์–ธ์–ด ์ƒํƒœ๊ณ„์— ๋น„ํ•˜๋ฉด ๋งŽ์ด ๋ถ€์กฑํ•˜๋‹ค๋Š” ๊ฒƒ๋„ ๋ถ€์ •ํ•˜๊ธฐ๋Š” ์–ด๋ ต์Šต๋‹ˆ๋‹ค.

 

์ด๋ฒˆ์— ๋‚˜์˜จ anyio๋Š” asyncio์—์„œ ๊ฐ€์ง€๊ณ  ์žˆ์—ˆ๋˜ ๋งŽ์€ ๋ถˆํŽธํ•จ ๊ทธ๋ฆฌ๊ณ  ๋™์‹œ์„ฑ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ์œ„ํ•œ ๋งค์ปค๋‹ˆ์ฆ˜์„ ๋”์šฑ ๊ฐ„๋‹จํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜๊ณ  ์—ฌํƒœ๊นŒ์ง€์˜ ๋น„๋™๊ธฐ ํŒจ๋Ÿฌ๋‹ค์ž„์— ์žˆ์–ด ๋ถˆํŽธํ•œ ์ ๋“ค์„ ํ•œ๋Œ€๋ชจ์•„ ๊ฐœ์„ ํ–ˆ๋‹ค๋Š” ์ ์„ ๊ฐ€์žฅ ํฐ ์ฃผ์š”์ ์œผ๋กœ ๋ฝ‘๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

 

๊ทธ๋‚˜๋งˆ ๋‹คํ–‰์ธ ๊ฒƒ์€ anyio๋ผ๋Š” ์ด๋Ÿฐ ์ข‹์€ ํŒจ๋Ÿฌ๋‹ค์ž„์ด ๊ธฐ์กด์˜ asyncio์˜ค ํ˜ธํ™˜๋œ๋‹ค๋Š” ๊ฒƒ์€ ๋‹คํ–‰์ธ ์ผ์ž…๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ด๋ฏธ asyncio ๊ธฐ๋ฐ˜์œผ๋กœ ๊ฐœ๋ฐœ๋œ SQLAlchemy 1.4๋‚˜ aiohttp์™€ ๊ฐ™์€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋“ค์ด ์ด๋“ค๋กœ ๋ฆฌํŒฉํ„ฐ๋งํ•ด ๋ฐ”๊ฟ”๋‚˜๊ฐ€๋Š” ๊ฒƒ์€ ๊ทธ๋งŒํผ ๋งŽ์€ ์‹œ๊ฐ„์ด ์†Œ๋ชจ๋˜๋ฉฐ ์•„์ง๊นŒ์ง€๋„ ํŒŒ์ด์ฌ ๋‚ด ๋น„๋™๊ธฐ ํŒจ๋Ÿฌ๋‹ค์ž„์€ ํ†ตํ•ฉ๋˜์ง€ ๋ชปํ•˜๊ณ  ๋ถ„์‚ฐ๋˜์—ˆ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

 

ํŒŒ์ด์ฌ์ด ๊ทธ๋งŒํผ ์ž์œ ๋กœ์šด ์–ธ์–ด์ธ ๊ฒƒ์€ ๋ณด์žฅ๋ฐ›์„ ์ˆ˜ ์žˆ์ง€๋งŒ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ฐœ๋ฐœํ•˜๋Š” ํ•œ ์—”์ง€๋‹ˆ์–ด๋กœ์จ ์ด๋Ÿฌํ•œ ๋ชจ์Šต์€ ์˜คํžˆ๋ ค ๊นŠ์€ ๋ ˆ๊ฑฐ์‹œ๋ฅผ ๋”์šฑ ์œ ๋ฐœํ•˜๊ณ  ๊ด€๋ฆฌํ•˜๊ธฐ ์–ด๋ ค์šด ํ”„๋กœ๋•ํŠธ๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐ ์›์ธ์ด ๋˜๋Š” ์–ธ์–ด๊ฐ€ ๋˜์ง€ ์•Š์•„ ์šฐ๋ ค์Šค๋Ÿฝ์Šต๋‹ˆ๋‹ค.

 

 

 

 

์ฐธ๊ณ : AnyIO ๊ณต์‹ ๋ฌธ์„œ (https://anyio.readthedocs.io/en/stable/index.html)

๋ฐ˜์‘ํ˜•
TAGS.

Tistory Comments