๐Ÿ Python ๋น„๋™๊ธฐ ํ”„๋กœ๊ทธ๋ž˜๋ฐ: ๋™์‹œ์„ฑ์œผ๋กœ ์„ฑ๋Šฅ ๊ฐœ์„ ํ•˜๊ธฐ ๐Ÿš€

์ฝ˜ํ…์ธ  ๋Œ€ํ‘œ ์ด๋ฏธ์ง€ - ๐Ÿ Python ๋น„๋™๊ธฐ ํ”„๋กœ๊ทธ๋ž˜๋ฐ: ๋™์‹œ์„ฑ์œผ๋กœ ์„ฑ๋Šฅ ๊ฐœ์„ ํ•˜๊ธฐ ๐Ÿš€

 

 

์•ˆ๋…•, ํŒŒ์ด์ฌ ๋งˆ์Šคํ„ฐ๊ฐ€ ๋˜๊ณ  ์‹ถ์€ ์นœ๊ตฌ๋“ค! ์˜ค๋Š˜์€ ์ •๋ง ํฅ๋ฏธ์ง„์ง„ํ•œ ์ฃผ์ œ๋กœ ์ฐพ์•„์™”์–ด. ๋ฐ”๋กœ Python์˜ ๋น„๋™๊ธฐ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์— ๋Œ€ํ•ด ๊นŠ์ด ํŒŒํ—ค์ณ๋ณผ ๊ฑฐ์•ผ. ๐Ÿ˜Ž

ํ˜น์‹œ ๋„ˆํฌ ์ค‘์— ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ์ผ์„ ๋™์‹œ์— ํ•˜๋Š” ๊ฑธ ์ข‹์•„ํ•˜๋Š” ์‚ฌ๋žŒ ์žˆ์–ด? ์˜ˆ๋ฅผ ๋“ค์–ด, ์Œ์•… ๋“ค์œผ๋ฉด์„œ ์ˆ™์ œํ•˜๊ณ , ๋™์‹œ์— ์นœ๊ตฌ๋ž‘ ์นดํ†กํ•˜๋Š” ๊ทธ๋Ÿฐ ๊ฑฐ ๋ง์ด์•ผ. ๊ทธ๋ ‡๋‹ค๋ฉด ๋„ˆํฌ๋Š” ์ด๋ฏธ '๋น„๋™๊ธฐ'์˜ ๊ฐœ๋…์„ ์ผ์ƒ์—์„œ ์‹ค์ฒœํ•˜๊ณ  ์žˆ๋Š” ๊ฑฐ์•ผ! ๐Ÿ‘

ํ”„๋กœ๊ทธ๋ž˜๋ฐ์—์„œ๋„ ์ด๋Ÿฐ ๊ฐœ๋…์ด ์ ์šฉ๋ผ. ํŠนํžˆ Python์—์„œ๋Š” ์ด๊ฑธ '๋น„๋™๊ธฐ ํ”„๋กœ๊ทธ๋ž˜๋ฐ'์ด๋ผ๊ณ  ๋ถˆ๋Ÿฌ. ์˜ค๋Š˜์€ ์ด ๋ฉ‹์ง„ ๊ธฐ์ˆ ์— ๋Œ€ํ•ด ์นœ๊ตฌ์ฒ˜๋Ÿผ ์žฌ๋ฏธ์žˆ๊ฒŒ ์„ค๋ช…ํ•ด์ค„๊ฒŒ. ์ค€๋น„๋๋‹ˆ? ๊ทธ๋Ÿผ ์‹œ์ž‘ํ•ด๋ณด์ž๊ณ ! ๐Ÿš€

๐Ÿ’ก ์•Œ์ญ๋‹ฌ์ญ Tip: ๋น„๋™๊ธฐ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์€ ์ฒ˜์Œ์—๋Š” ์ข€ ์–ด๋ ค์›Œ ๋ณด์ผ ์ˆ˜ ์žˆ์–ด. ํ•˜์ง€๋งŒ ๊ฑฑ์ • ๋งˆ! ์šฐ๋ฆฌ๊ฐ€ ํ•จ๊ป˜ ์ฐจ๊ทผ์ฐจ๊ทผ ์•Œ์•„๊ฐ€๋‹ค ๋ณด๋ฉด, ์–ด๋Š์ƒˆ ๋„Œ ๋น„๋™๊ธฐ์˜ ๋‹ฌ์ธ์ด ๋˜์–ด ์žˆ์„ ๊ฑฐ์•ผ. ๊ทธ๋ฆฌ๊ณ  ์ด๋Ÿฐ ์‹ค๋ ฅ์€ ๋‚˜์ค‘์— ์žฌ๋Šฅ๋„ท ๊ฐ™์€ ํ”Œ๋žซํผ์—์„œ ๋„ค ์žฌ๋Šฅ์„ ๋ฝ๋‚ด๋Š” ๋ฐ ํฐ ๋„์›€์ด ๋  ๊ฑฐ์•ผ! ๐Ÿ˜‰

๐Ÿ”„ ๋น„๋™๊ธฐ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์ด ๋ญ๊ธธ๋ž˜?

์ž, ๋น„๋™๊ธฐ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์ด ๋ญ”์ง€ ํ•œ๋ฒˆ ์•Œ์•„๋ณผ๊นŒ? ์‰ฝ๊ฒŒ ์„ค๋ช…ํ•˜์ž๋ฉด, ๋น„๋™๊ธฐ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์€ ์—ฌ๋Ÿฌ ์ž‘์—…์„ ๋™์‹œ์— ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ๋งˆ๋ฒ• ๊ฐ™์€ ๊ธฐ์ˆ ์ด์•ผ. ๐Ÿ˜ฒ

์˜ˆ๋ฅผ ๋“ค์–ด๋ณผ๊ฒŒ. ๋„Œ ์ง€๊ธˆ ํ”ผ์ž ๊ฐ€๊ฒŒ์—์„œ ์ผํ•˜๊ณ  ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ด๋ด. ์†๋‹˜์ด ํ”ผ์ž๋ฅผ ์ฃผ๋ฌธํ•˜๋ฉด, ๋„Œ ์˜ค๋ธ์— ํ”ผ์ž๋ฅผ ๋„ฃ๊ณ  15๋ถ„์„ ๊ธฐ๋‹ค๋ ค์•ผ ํ•ด. ๊ทธ๋Ÿฐ๋ฐ ๊ทธ 15๋ถ„ ๋™์•ˆ ๊ฐ€๋งŒํžˆ ์žˆ์„ ๊ฑฐ์•ผ? ์•„๋‹ˆ์ง€! ๋‹ค๋ฅธ ์ผ์„ ํ•  ์ˆ˜ ์žˆ์ž–์•„. ์˜ˆ๋ฅผ ๋“ค์–ด ๋‹ค๋ฅธ ์†๋‹˜์˜ ์ฃผ๋ฌธ์„ ๋ฐ›๊ฑฐ๋‚˜, ํ…Œ์ด๋ธ”์„ ์ •๋ฆฌํ•˜๊ฑฐ๋‚˜, ์Œ๋ฃŒ์ˆ˜๋ฅผ ์ค€๋น„ํ•  ์ˆ˜ ์žˆ์–ด.

์ด๊ฒŒ ๋ฐ”๋กœ ๋น„๋™๊ธฐ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์˜ ํ•ต์‹ฌ์ด์•ผ. ํ•œ ์ž‘์—…์ด ๋๋‚˜๊ธฐ๋ฅผ ๊ธฐ๋‹ค๋ฆฌ๋Š” ๋™์•ˆ ๋‹ค๋ฅธ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฑฐ์ง€. coolํ•˜์ง€ ์•Š์•„? ๐Ÿ˜Ž

๋น„๋™๊ธฐ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๊ฐœ๋…๋„ ๋น„๋™๊ธฐ ํ”„๋กœ๊ทธ๋ž˜๋ฐ Task 1 Task 2 Task 3 Task 4 ๋™์‹œ ์‹คํ–‰ ํšจ์œจ์ ์ธ ์ž์› ํ™œ์šฉ

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

๊ทธ๋Ÿผ ์ด์ œ ๋น„๋™๊ธฐ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์ด ์™œ ์ค‘์š”ํ•œ์ง€ ์•Œ์•„๋ณผ๊นŒ?

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

์ด๋ ‡๊ฒŒ ๋ณด๋‹ˆ๊นŒ ๋น„๋™๊ธฐ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์ด ์–ผ๋งˆ๋‚˜ ๊ฐ•๋ ฅํ•œ์ง€ ์•Œ๊ฒ ์ง€? ๐Ÿ˜ƒ

๐Ÿšจ ์ฃผ์˜์‚ฌํ•ญ: ๋น„๋™๊ธฐ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์ด ํ•ญ์ƒ ์ข‹์€ ๊ฒƒ๋งŒ์€ ์•„๋‹ˆ์•ผ. ๋•Œ๋กœ๋Š” ์ฝ”๋“œ๊ฐ€ ๋ณต์žกํ•ด์งˆ ์ˆ˜ ์žˆ๊ณ , ๋””๋ฒ„๊น…๋„ ์–ด๋ ค์›Œ์งˆ ์ˆ˜ ์žˆ์–ด. ๊ทธ๋ž˜์„œ ์ƒํ™ฉ์— ๋งž๊ฒŒ ์ ์ ˆํžˆ ์‚ฌ์šฉํ•˜๋Š” ๊ฒŒ ์ค‘์š”ํ•ด!

์ž, ์ด์ œ ๋น„๋™๊ธฐ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์˜ ๊ธฐ๋ณธ ๊ฐœ๋…์„ ์•Œ์•˜์œผ๋‹ˆ, ๋‹ค์Œ์œผ๋กœ Python์—์„œ ์–ด๋–ป๊ฒŒ ์ด๊ฑธ ๊ตฌํ˜„ํ•˜๋Š”์ง€ ์•Œ์•„๋ณผ๊นŒ? ์ค€๋น„๋๋‹ˆ? ๊ทธ๋Ÿผ ๊ณ ๊ณ ! ๐Ÿš€

๐Ÿ Python์—์„œ์˜ ๋น„๋™๊ธฐ ํ”„๋กœ๊ทธ๋ž˜๋ฐ

์ž, ์ด์ œ Python์—์„œ ๋น„๋™๊ธฐ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ์–ด๋–ป๊ฒŒ ๊ตฌํ˜„ํ•˜๋Š”์ง€ ์•Œ์•„๋ณผ ์ฐจ๋ก€์•ผ. Python์€ ๋น„๋™๊ธฐ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ์œ„ํ•ด asyncio๋ผ๋Š” ๋ฉ‹์ง„ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ œ๊ณตํ•ด. ์ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” Python 3.4๋ถ€ํ„ฐ ๋„์ž…๋๊ณ , ๊ณ„์†ํ•ด์„œ ๋ฐœ์ „ํ•˜๊ณ  ์žˆ์–ด. ๐Ÿ˜Š

asyncio๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ฝ”๋ฃจํ‹ด(coroutine)์ด๋ผ๋Š” ํŠน๋ณ„ํ•œ ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์–ด. ์ฝ”๋ฃจํ‹ด์€ ์‹คํ–‰ ์ค‘์— ์ผ์‹œ ์ค‘์ง€๋˜๊ณ  ๋‚˜์ค‘์— ๋‹ค์‹œ ์‹œ์ž‘๋  ์ˆ˜ ์žˆ๋Š” ํ•จ์ˆ˜์•ผ. ์ด๊ฒŒ ๋ฐ”๋กœ ๋น„๋™๊ธฐ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์˜ ํ•ต์‹ฌ์ด์ง€!

์ž, ๊ทธ๋Ÿผ ๊ฐ„๋‹จํ•œ ์˜ˆ์ œ๋ฅผ ํ†ตํ•ด asyncio๋ฅผ ์‚ฌ์šฉํ•ด๋ณด์ž.


import asyncio

async def say_hello(name):
    print(f"Hello, {name}!")
    await asyncio.sleep(1)
    print(f"Goodbye, {name}!")

async def main():
    await asyncio.gather(
        say_hello("Alice"),
        say_hello("Bob"),
        say_hello("Charlie")
    )

asyncio.run(main())

์ด ์ฝ”๋“œ๊ฐ€ ์–ด๋–ป๊ฒŒ ๋™์ž‘ํ•˜๋Š”์ง€ ์„ค๋ช…ํ•ด์ค„๊ฒŒ:

  1. async def๋กœ ์ฝ”๋ฃจํ‹ด ํ•จ์ˆ˜๋ฅผ ์ •์˜ํ•ด.
  2. await ํ‚ค์›Œ๋“œ๋Š” ๋น„๋™๊ธฐ ์ž‘์—…์ด ์™„๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฌ๋ผ๋Š” ์˜๋ฏธ์•ผ.
  3. asyncio.gather()๋Š” ์—ฌ๋Ÿฌ ์ฝ”๋ฃจํ‹ด์„ ๋™์‹œ์— ์‹คํ–‰ํ•ด.
  4. asyncio.run()์€ ๋น„๋™๊ธฐ ํ”„๋กœ๊ทธ๋žจ์˜ ์ง„์ž…์ ์ด์•ผ.

์ด ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜๋ฉด, "Hello" ๋ฉ”์‹œ์ง€๊ฐ€ ๊ฑฐ์˜ ๋™์‹œ์— ์ถœ๋ ฅ๋˜๊ณ , 1์ดˆ ํ›„์— "Goodbye" ๋ฉ”์‹œ์ง€๊ฐ€ ์ถœ๋ ฅ๋ผ. ๋ฉ‹์ง€์ง€ ์•Š์•„? ๐Ÿ˜Ž

asyncio ๋™์ž‘ ์›๋ฆฌ asyncio Event Loop Alice Bob Charlie Concurrent Execution

์œ„ ๊ทธ๋ฆผ์€ asyncio์˜ ์ด๋ฒคํŠธ ๋ฃจํ”„๊ฐ€ ์–ด๋–ป๊ฒŒ ๋™์ž‘ํ•˜๋Š”์ง€๋ฅผ ๋ณด์—ฌ์ค˜. Alice, Bob, Charlie๋ผ๋Š” ์„ธ ๊ฐœ์˜ ํƒœ์Šคํฌ๊ฐ€ ๋™์‹œ์— ์‹คํ–‰๋˜๊ณ  ์žˆ์–ด. ์ด๋ฒคํŠธ ๋ฃจํ”„๋Š” ์ด ํƒœ์Šคํฌ๋“ค์„ ๋ฒˆ๊ฐˆ์•„๊ฐ€๋ฉฐ ์‹คํ–‰ํ•˜๋ฉด์„œ, ํšจ์œจ์ ์œผ๋กœ ๋ฆฌ์†Œ์Šค๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์ง€. ๐Ÿ˜Š

๐Ÿ’ก Pro Tip: asyncio๋ฅผ ๋งˆ์Šคํ„ฐํ•˜๋ฉด, ๋„คํŠธ์›Œํฌ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์ด๋‚˜ ์›น ์Šคํฌ๋ž˜ํ•‘ ๊ฐ™์€ I/O ๋ฐ”์šด๋“œ ์ž‘์—…์—์„œ ์—„์ฒญ๋‚œ ์„ฑ๋Šฅ ํ–ฅ์ƒ์„ ๊ฒฝํ—˜ํ•  ์ˆ˜ ์žˆ์–ด. ์ด๋Ÿฐ ์‹ค๋ ฅ์€ ์žฌ๋Šฅ๋„ท์—์„œ ๋„ค ๊ฐ€์น˜๋ฅผ ํ•œ์ธต ๋” ๋†’์—ฌ์ค„ ๊ฑฐ์•ผ!

์ž, ์ด์ œ ๊ธฐ๋ณธ์ ์ธ asyncio ์‚ฌ์šฉ๋ฒ•์„ ์•Œ์•˜์œผ๋‹ˆ, ์ข€ ๋” ๋ณต์žกํ•œ ์˜ˆ์ œ๋ฅผ ์‚ดํŽด๋ณผ๊นŒ? ๐Ÿค”


import asyncio
import random

async def fetch_data(url):
    print(f"Fetching data from {url}")
    await asyncio.sleep(random.uniform(0.5, 2.0))  # ์‹ค์ œ ๋„คํŠธ์›Œํฌ ์š”์ฒญ์„ ์‹œ๋ฎฌ๋ ˆ์ด์…˜
    print(f"Finished fetching data from {url}")
    return f"Data from {url}"

async def process_data(data):
    print(f"Processing {data}")
    await asyncio.sleep(0.5)  # ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ๋ฅผ ์‹œ๋ฎฌ๋ ˆ์ด์…˜
    print(f"Finished processing {data}")
    return f"Processed {data}"

async def main():
    urls = ['http://example.com', 'http://example.org', 'http://example.net']
    
    # ๋ฐ์ดํ„ฐ ๊ฐ€์ ธ์˜ค๊ธฐ
    fetch_tasks = [fetch_data(url) for url in urls]
    fetched_data = await asyncio.gather(*fetch_tasks)
    
    # ๊ฐ€์ ธ์˜จ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌํ•˜๊ธฐ
    process_tasks = [process_data(data) for data in fetched_data]
    processed_data = await asyncio.gather(*process_tasks)
    
    for result in processed_data:
        print(result)

asyncio.run(main())

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

์ด๋Ÿฐ ๋ฐฉ์‹์œผ๋กœ ํ”„๋กœ๊ทธ๋ž˜๋ฐํ•˜๋ฉด, ๋„คํŠธ์›Œํฌ ์ง€์—ฐ ์‹œ๊ฐ„์„ ํšจ์œจ์ ์œผ๋กœ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์–ด. ํ•œ URL์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ธฐ๋‹ค๋ฆฌ๋Š” ๋™์•ˆ ๋‹ค๋ฅธ URL์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์œผ๋‹ˆ๊นŒ. ๐Ÿ‘

๐Ÿšจ ์ฃผ์˜์‚ฌํ•ญ: ๋น„๋™๊ธฐ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ํ•  ๋•Œ๋Š” ํ•ญ์ƒ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ์— ์‹ ๊ฒฝ ์จ์•ผ ํ•ด. ๋„คํŠธ์›Œํฌ ์˜ค๋ฅ˜๋‚˜ ํƒ€์ž„์•„์›ƒ ๊ฐ™์€ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๊ฑฐ๋“ . try-except ๊ตฌ๋ฌธ์„ ์ ์ ˆํžˆ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ์žŠ์ง€ ๋งˆ!

์ž, ์ด์ œ ๋น„๋™๊ธฐ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์˜ ๊ธฐ๋ณธ์„ ์•Œ๊ฒŒ ๋์–ด. ๊ทผ๋ฐ ์—ฌ๊ธฐ์„œ ๋์ด ์•„๋‹ˆ์•ผ. ๋น„๋™๊ธฐ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์—๋Š” ๋” ๋งŽ์€ ๊ฐœ๋…๊ณผ ํ…Œํฌ๋‹‰์ด ์žˆ์–ด. ๋‹ค์Œ ์„น์…˜์—์„œ ๋” ๊นŠ์ด ํŒŒ๊ณ ๋“ค์–ด๋ณผ๊นŒ? ์ค€๋น„๋๋‹ˆ? Let's go! ๐Ÿš€

๐Ÿง  ๋น„๋™๊ธฐ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์˜ ๊ณ ๊ธ‰ ๊ฐœ๋…

์ž, ์ด์ œ ๋น„๋™๊ธฐ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์˜ ๋” ๊นŠ์€ ๋ถ€๋ถ„์œผ๋กœ ๋“ค์–ด๊ฐ€๋ณผ ๊ฑฐ์•ผ. ์ค€๋น„๋๋‹ˆ? ์‹ฌํ˜ธํก ํ•œ ๋ฒˆ ํ•˜๊ณ ... ์‹œ์ž‘ํ•ด๋ณผ๊นŒ? ๐Ÿ˜Š

1. ํƒœ์Šคํฌ(Task)

ํƒœ์Šคํฌ๋Š” ์ฝ”๋ฃจํ‹ด์„ ๊ฐ์‹ธ๋Š” ๊ฐ์ฒด์•ผ. ์ฝ”๋ฃจํ‹ด์˜ ์‹คํ–‰์„ ์ถ”์ ํ•˜๊ณ  ๊ด€๋ฆฌํ•˜๋Š” ์—ญํ• ์„ ํ•ด. ํƒœ์Šคํฌ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ฝ”๋ฃจํ‹ด์˜ ์ƒํƒœ๋ฅผ ํ™•์ธํ•˜๊ฑฐ๋‚˜, ์ทจ์†Œํ•  ์ˆ˜ ์žˆ์–ด.


import asyncio

async def my_coroutine():
    print("Coroutine started")
    await asyncio.sleep(1)
    print("Coroutine finished")

async def main():
    task = asyncio.create_task(my_coroutine())
    print(f"Task created: {task}")
    await task
    print(f"Task completed: {task}")

asyncio.run(main())

์ด ์˜ˆ์ œ์—์„œ asyncio.create_task()๋ฅผ ์‚ฌ์šฉํ•ด ์ฝ”๋ฃจํ‹ด์„ ํƒœ์Šคํฌ๋กœ ๋งŒ๋“ค์—ˆ์–ด. ํƒœ์Šคํฌ๋Š” ์ƒ์„ฑ๋˜์ž๋งˆ์ž ์‹คํ–‰์„ ์‹œ์ž‘ํ•˜์ง€๋งŒ, await๋ฅผ ์‚ฌ์šฉํ•ด ์™„๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆด ์ˆ˜ ์žˆ์–ด.

2. ํ“จ์ฒ˜(Future)

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


import asyncio

async def set_after(fut, delay, value):
    await asyncio.sleep(delay)
    fut.set_result(value)

async def main():
    loop = asyncio.get_running_loop()
    fut = loop.create_future()
    
    loop.create_task(set_after(fut, 1, '... World'))
    
    print('Hello ...')
    print(await fut)

asyncio.run(main())

์ด ์˜ˆ์ œ์—์„œ๋Š” ํ“จ์ฒ˜๋ฅผ ๋งŒ๋“ค๊ณ , ๋‚˜์ค‘์— ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ์„ค์ •ํ•ด. ๋ฉ”์ธ ์ฝ”๋ฃจํ‹ด์€ ํ“จ์ฒ˜๊ฐ€ ์™„๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ ธ๋‹ค๊ฐ€ ๊ฒฐ๊ณผ๋ฅผ ์ถœ๋ ฅํ•ด.

3. ์ด๋ฒคํŠธ ๋ฃจํ”„(Event Loop)

์ด๋ฒคํŠธ ๋ฃจํ”„๋Š” ๋น„๋™๊ธฐ ํ”„๋กœ๊ทธ๋žจ์˜ ํ•ต์‹ฌ์ด์•ผ. ๋ชจ๋“  ๋น„๋™๊ธฐ ์ž‘์—…์„ ๊ด€๋ฆฌํ•˜๊ณ  ์‹คํ–‰ํ•˜๋Š” ์—ญํ• ์„ ํ•ด. Python์˜ asyncio๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ๋‹จ์ผ ์Šค๋ ˆ๋“œ ์ด๋ฒคํŠธ ๋ฃจํ”„๋ฅผ ์‚ฌ์šฉํ•ด.

์ด๋ฒคํŠธ ๋ฃจํ”„ ๋™์ž‘ ์›๋ฆฌ Event Loop Task 1 Task 2 Task 3 Tasks are executed in a round-robin fashion

์œ„ ๊ทธ๋ฆผ์€ ์ด๋ฒคํŠธ ๋ฃจํ”„์˜ ๋™์ž‘ ์›๋ฆฌ๋ฅผ ๋ณด์—ฌ์ค˜. ์ด๋ฒคํŠธ ๋ฃจํ”„๋Š” ๊ณ„์†ํ•ด์„œ ๋Œ๋ฉด์„œ ์‹คํ–‰ ๊ฐ€๋Šฅํ•œ ํƒœ์Šคํฌ๋ฅผ ์ฐพ์•„ ์‹คํ–‰ํ•ด. ํƒœ์Šคํฌ๊ฐ€ I/O ์ž‘์—… ๊ฐ™์€ ๊ฑธ ๋งŒ๋‚˜๋ฉด ์ž ์‹œ ์ค‘๋‹จํ•˜๊ณ  ๋‹ค๋ฅธ ํƒœ์Šคํฌ๋กœ ๋„˜์–ด๊ฐ€. ์ด๋ ‡๊ฒŒ ํ•ด์„œ ํšจ์œจ์ ์œผ๋กœ ๋ฆฌ์†Œ์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฑฐ์ง€. ๐Ÿ˜Š

4. ๋™์‹œ์„ฑ๊ณผ ๋ณ‘๋ ฌ์„ฑ

๋งŽ์€ ์‚ฌ๋žŒ๋“ค์ด ๋™์‹œ์„ฑ(Concurrency)๊ณผ ๋ณ‘๋ ฌ์„ฑ(Parallelism)์„ ํ˜ผ๋™ํ•ด. ํ•˜์ง€๋งŒ ์ด ๋‘˜์€ ๋‹ค๋ฅธ ๊ฐœ๋…์ด์•ผ.

  • ๋™์‹œ์„ฑ: ์—ฌ๋Ÿฌ ์ž‘์—…์„ ๋ฒˆ๊ฐˆ์•„๊ฐ€๋ฉฐ ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ. ํ•œ ๋ฒˆ์— ํ•˜๋‚˜์˜ ์ž‘์—…๋งŒ ์ง„ํ–‰ํ•˜์ง€๋งŒ, ๋น ๋ฅด๊ฒŒ ์ „ํ™˜ํ•ด์„œ ๋งˆ์น˜ ๋™์‹œ์— ์‹คํ–‰๋˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ด๊ฒŒ ํ•ด.
  • ๋ณ‘๋ ฌ์„ฑ: ์‹ค์ œ๋กœ ์—ฌ๋Ÿฌ ์ž‘์—…์„ ๋™์‹œ์— ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ. ์ด๊ฑด ๋ฉ€ํ‹ฐ์ฝ”์–ด ํ”„๋กœ์„ธ์„œ์—์„œ ๊ฐ€๋Šฅํ•ด.

asyncio๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ๋™์‹œ์„ฑ์„ ์ œ๊ณตํ•ด. ํ•˜์ง€๋งŒ Python์˜ ๋ฉ€ํ‹ฐํ”„๋กœ์„ธ์‹ฑ๊ณผ ๊ฒฐํ•ฉํ•˜๋ฉด ๋ณ‘๋ ฌ์„ฑ๋„ ๋‹ฌ์„ฑํ•  ์ˆ˜ ์žˆ์–ด.

5. ๋น„๋™๊ธฐ ์ปจํ…์ŠคํŠธ ๋งค๋‹ˆ์ €

Python์˜ with ๋ฌธ์ฒ˜๋Ÿผ, asyncio๋„ ๋น„๋™๊ธฐ ์ปจํ…์ŠคํŠธ ๋งค๋‹ˆ์ €๋ฅผ ์ œ๊ณตํ•ด. ์ด๋ฅผ ํ†ตํ•ด ๋ฆฌ์†Œ์Šค์˜ ํš๋“๊ณผ ํ•ด์ œ๋ฅผ ๋น„๋™๊ธฐ์ ์œผ๋กœ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์–ด.


import asyncio

class AsyncContextManager:
    async def __aenter__(self):
        print("Entering the context")
        await asyncio.sleep(1)
        return self

    async def __aexit__(self, exc_type, exc, tb):
        print("Exiting the context")
        await asyncio.sleep(1)

async def main():
    async with AsyncContextManager() as manager:
        print("Inside the context")

asyncio.run(main())

์ด ์˜ˆ์ œ์—์„œ AsyncContextManager๋Š” ๋น„๋™๊ธฐ ์ปจํ…์ŠคํŠธ ๋งค๋‹ˆ์ €์•ผ. __aenter__์™€ __aexit__ ๋ฉ”์„œ๋“œ๋ฅผ ๋น„๋™๊ธฐ์ ์œผ๋กœ ์ •์˜ํ•ด์„œ ๋ฆฌ์†Œ์Šค์˜ ํš๋“๊ณผ ํ•ด์ œ๋ฅผ ๋น„๋™๊ธฐ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์–ด.

๐Ÿ’ก Pro Tip: ๋น„๋™๊ธฐ ์ปจํ…์ŠคํŠธ ๋งค๋‹ˆ์ €๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ์ด๋‚˜ ๋„คํŠธ์›Œํฌ ์†Œ์ผ“ ๊ฐ™์€ ๋ฆฌ์†Œ์Šค๋ฅผ ๊ด€๋ฆฌํ•  ๋•Œ ํŠนํžˆ ์œ ์šฉํ•ด. ์žฌ๋Šฅ๋„ท์—์„œ ๋ฐฑ์—”๋“œ ๊ฐœ๋ฐœ์„ ํ•  ๋•Œ ์ด๋Ÿฐ ๊ธฐ์ˆ ์„ ์‚ฌ์šฉํ•˜๋ฉด ํšจ์œจ์ ์ธ ๋ฆฌ์†Œ์Šค ๊ด€๋ฆฌ๊ฐ€ ๊ฐ€๋Šฅํ•  ๊ฑฐ์•ผ!

6. ๋น„๋™๊ธฐ ์ดํ„ฐ๋ ˆ์ดํ„ฐ์™€ ์ œ๋„ˆ๋ ˆ์ดํ„ฐ

Python์˜ ์ดํ„ฐ๋ ˆ์ดํ„ฐ์™€ ์ œ๋„ˆ๋ ˆ์ดํ„ฐ ๊ฐœ๋…์„ ๋น„๋™๊ธฐ ์„ธ๊ณ„๋กœ ํ™•์žฅํ•œ ๊ฑฐ์•ผ. ๋น„๋™๊ธฐ ์ดํ„ฐ๋ ˆ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋Œ€๋Ÿ‰์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋น„๋™๊ธฐ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์–ด.


import asyncio

class AsyncRange:
    def __init__(self, start, stop):
        self.start = start
        self.stop = stop

    def __aiter__(self):
        return self

    async def __anext__(self):
        if self.start >= self.stop:
            raise StopAsyncIteration
        await asyncio.sleep(0.1)  # ๊ฐ ํ•ญ๋ชฉ ์‚ฌ์ด์— ์•ฝ๊ฐ„์˜ ์ง€์—ฐ์„ ์ถ”๊ฐ€
        self.start += 1
        return self.start - 1

async def main():
    async for i in AsyncRange(0, 5):
        print(i)

asyncio.run(main())

์ด ์˜ˆ์ œ์—์„œ AsyncRange๋Š” ๋น„๋™๊ธฐ ์ดํ„ฐ๋ ˆ์ดํ„ฐ์•ผ. __aiter__์™€ __anext__ ๋ฉ”์„œ๋“œ๋ฅผ ๊ตฌํ˜„ ํ•ด์„œ ๋น„๋™๊ธฐ์ ์œผ๋กœ ๊ฐ’์„ ์ƒ์„ฑํ•˜๊ณ  ์žˆ์–ด. ์ด๋Ÿฐ ๋ฐฉ์‹์œผ๋กœ ๋Œ€๋Ÿ‰์˜ ๋ฐ์ดํ„ฐ๋ฅผ ํšจ์œจ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์ง€.

7. ๋น„๋™๊ธฐ ์ปดํ”„๋ฆฌํ—จ์…˜๊ณผ ์ œ๋„ˆ๋ ˆ์ดํ„ฐ ํ‘œํ˜„์‹

Python์˜ ๋ฆฌ์ŠคํŠธ ์ปดํ”„๋ฆฌํ—จ์…˜๊ณผ ์ œ๋„ˆ๋ ˆ์ดํ„ฐ ํ‘œํ˜„์‹์— ์ต์ˆ™ํ•˜์ง€? asyncio๋Š” ์ด๋Ÿฐ ํŽธ๋ฆฌํ•œ ๋ฌธ๋ฒ•์„ ๋น„๋™๊ธฐ ์„ธ๊ณ„๋กœ ๊ฐ€์ ธ์™”์–ด.


import asyncio

async def fetch_data(url):
    await asyncio.sleep(1)  # ๋„คํŠธ์›Œํฌ ์š”์ฒญ์„ ์‹œ๋ฎฌ๋ ˆ์ด์…˜
    return f"Data from {url}"

async def main():
    urls = ['http://example.com', 'http://example.org', 'http://example.net']
    
    # ๋น„๋™๊ธฐ ์ปดํ”„๋ฆฌํ—จ์…˜
    results = [await fetch_data(url) for url in urls]
    print(results)
    
    # ๋น„๋™๊ธฐ ์ œ๋„ˆ๋ ˆ์ดํ„ฐ ํ‘œํ˜„์‹
    async for result in (fetch_data(url) for url in urls):
        print(result)

asyncio.run(main())

์ด ์˜ˆ์ œ์—์„œ ๋น„๋™๊ธฐ ์ปดํ”„๋ฆฌํ—จ์…˜๊ณผ ์ œ๋„ˆ๋ ˆ์ดํ„ฐ ํ‘œํ˜„์‹์„ ์‚ฌ์šฉํ•ด ์—ฌ๋Ÿฌ URL์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๊ณ  ์žˆ์–ด. ์ด๋Ÿฐ ๋ฐฉ์‹์œผ๋กœ ์ฝ”๋“œ๋ฅผ ๊ฐ„๊ฒฐํ•˜๊ฒŒ ์œ ์ง€ํ•˜๋ฉด์„œ๋„ ๋น„๋™๊ธฐ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์ง€.

8. ๋™์‹œ์„ฑ ์ œ์–ด

์—ฌ๋Ÿฌ ์ฝ”๋ฃจํ‹ด์ด ๋™์‹œ์— ์‹คํ–‰๋  ๋•Œ, ๋•Œ๋กœ๋Š” ์ด๋“ค ์‚ฌ์ด์˜ ์‹คํ–‰ ์ˆœ์„œ๋‚˜ ๋™์‹œ ์ ‘๊ทผ์„ ์ œ์–ดํ•ด์•ผ ํ•  ํ•„์š”๊ฐ€ ์žˆ์–ด. asyncio๋Š” ์ด๋ฅผ ์œ„ํ•œ ์—ฌ๋Ÿฌ ๋„๊ตฌ๋ฅผ ์ œ๊ณตํ•ด.

  • Lock: ํ•œ ๋ฒˆ์— ํ•˜๋‚˜์˜ ์ฝ”๋ฃจํ‹ด๋งŒ ํŠน์ • ์ฝ”๋“œ ๋ธ”๋ก์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด.
  • Semaphore: ๋™์‹œ์— ์‹คํ–‰๋  ์ˆ˜ ์žˆ๋Š” ์ฝ”๋ฃจํ‹ด์˜ ์ˆ˜๋ฅผ ์ œํ•œํ•ด.
  • Event: ํ•œ ์ฝ”๋ฃจํ‹ด์ด ๋‹ค๋ฅธ ์ฝ”๋ฃจํ‹ด์—๊ฒŒ ํŠน์ • ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Œ์„ ์•Œ๋ฆด ์ˆ˜ ์žˆ๊ฒŒ ํ•ด.
  • Condition: ๋ณต์žกํ•œ ๋™๊ธฐํ™” ์‹œ๋‚˜๋ฆฌ์˜ค๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด.

import asyncio

async def worker(semaphore, name):
    async with semaphore:
        print(f"{name} is working")
        await asyncio.sleep(1)
    print(f"{name} is done")

async def main():
    semaphore = asyncio.Semaphore(2)  # ์ตœ๋Œ€ 2๊ฐœ์˜ ์ž‘์—…๋งŒ ๋™์‹œ ์‹คํ–‰
    workers = [asyncio.create_task(worker(semaphore, f"Worker {i}")) for i in range(5)]
    await asyncio.gather(*workers)

asyncio.run(main())

์ด ์˜ˆ์ œ์—์„œ๋Š” ์„ธ๋งˆํฌ์–ด๋ฅผ ์‚ฌ์šฉํ•ด ๋™์‹œ์— ์‹คํ–‰๋˜๋Š” ์ž‘์—…์˜ ์ˆ˜๋ฅผ 2๊ฐœ๋กœ ์ œํ•œํ•˜๊ณ  ์žˆ์–ด. ์ด๋Ÿฐ ๋ฐฉ์‹์œผ๋กœ ๋ฆฌ์†Œ์Šค ์‚ฌ์šฉ์„ ์ œ์–ดํ•˜๊ณ  ๊ณผ๋ถ€ํ•˜๋ฅผ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ์ง€.

๋™์‹œ์„ฑ ์ œ์–ด ๊ฐœ๋…๋„ Concurrency Control Lock Semaphore Event Coordinating Asynchronous Tasks

์œ„ ๊ทธ๋ฆผ์€ ๋™์‹œ์„ฑ ์ œ์–ด์˜ ์ฃผ์š” ๊ฐœ๋…๋“ค์„ ๋ณด์—ฌ์ค˜. Lock, Semaphore, Event ๋“ฑ์˜ ๋„๊ตฌ๋“ค์ด ์–ด๋–ป๊ฒŒ ๋น„๋™๊ธฐ ํƒœ์Šคํฌ๋“ค์„ ์กฐ์œจํ•˜๋Š”์ง€ ๋ณผ ์ˆ˜ ์žˆ์–ด. ์ด๋Ÿฐ ๋„๊ตฌ๋“ค์„ ์ ์ ˆํžˆ ์‚ฌ์šฉํ•˜๋ฉด ๋ณต์žกํ•œ ๋น„๋™๊ธฐ ์‹œ์Šคํ…œ๋„ ์•ˆ์ •์ ์œผ๋กœ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์ง€. ๐Ÿ˜Š

๐Ÿšจ ์ฃผ์˜์‚ฌํ•ญ: ๋™์‹œ์„ฑ ์ œ์–ด ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ๋Š” ๋ฐ๋“œ๋ฝ(deadlock)์— ์ฃผ์˜ํ•ด์•ผ ํ•ด. ์—ฌ๋Ÿฌ ๊ฐœ์˜ ๋ฝ์„ ์‚ฌ์šฉํ•  ๋•Œ ํŠนํžˆ ์กฐ์‹ฌํ•ด์•ผ ํ•˜์ง€. ํ•ญ์ƒ ๋™์ผํ•œ ์ˆœ์„œ๋กœ ๋ฝ์„ ํš๋“ํ•˜๊ณ  ํ•ด์ œํ•˜๋Š” ๊ฒƒ์ด ์ข‹์•„.

9. ๋น„๋™๊ธฐ ์ŠคํŠธ๋ฆผ

๋Œ€๋Ÿ‰์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•  ๋•Œ, ๋ชจ๋“  ๋ฐ์ดํ„ฐ๋ฅผ ๋ฉ”๋ชจ๋ฆฌ์— ํ•œ ๋ฒˆ์— ๋กœ๋“œํ•˜๋Š” ๊ฒƒ์€ ๋น„ํšจ์œจ์ ์ผ ์ˆ˜ ์žˆ์–ด. ๋น„๋™๊ธฐ ์ŠคํŠธ๋ฆผ์„ ์‚ฌ์šฉํ•˜๋ฉด ๋ฐ์ดํ„ฐ๋ฅผ ์ฒญํฌ(chunk) ๋‹จ์œ„๋กœ ๋น„๋™๊ธฐ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์–ด.


import asyncio

async def data_source():
    for i in range(10):
        await asyncio.sleep(0.5)  # ๋ฐ์ดํ„ฐ ์ƒ์„ฑ ์‹œ๊ฐ„์„ ์‹œ๋ฎฌ๋ ˆ์ด์…˜
        yield f"data {i}"

async def process_stream():
    async for data in data_source():
        print(f"Processing {data}")
        await asyncio.sleep(0.1)  # ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„์„ ์‹œ๋ฎฌ๋ ˆ์ด์…˜

asyncio.run(process_stream())

์ด ์˜ˆ์ œ์—์„œ data_source ํ•จ์ˆ˜๋Š” ๋น„๋™๊ธฐ ์ œ๋„ˆ๋ ˆ์ดํ„ฐ๋กœ, ๋ฐ์ดํ„ฐ๋ฅผ ์ŠคํŠธ๋ฆผ ํ˜•ํƒœ๋กœ ์ƒ์„ฑํ•ด. process_stream ํ•จ์ˆ˜๋Š” ์ด ์ŠคํŠธ๋ฆผ์„ ๋น„๋™๊ธฐ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๊ณ  ์žˆ์–ด. ์ด๋Ÿฐ ๋ฐฉ์‹์œผ๋กœ ๋Œ€์šฉ๋Ÿ‰ ๋ฐ์ดํ„ฐ๋ฅผ ํšจ์œจ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์ง€.

10. ๋น„๋™๊ธฐ ํ…Œ์ŠคํŒ…

๋น„๋™๊ธฐ ์ฝ”๋“œ๋ฅผ ํ…Œ์ŠคํŠธํ•˜๋Š” ๊ฒƒ์€ ๋™๊ธฐ ์ฝ”๋“œ๋ฅผ ํ…Œ์ŠคํŠธํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ์กฐ๊ธˆ ๋” ๋ณต์žกํ•  ์ˆ˜ ์žˆ์–ด. ํ•˜์ง€๋งŒ Python์˜ unittest ๋ชจ๋“ˆ๊ณผ asyncio๋ฅผ ๊ฒฐํ•ฉํ•˜๋ฉด ํšจ๊ณผ์ ์œผ๋กœ ๋น„๋™๊ธฐ ์ฝ”๋“œ๋ฅผ ํ…Œ์ŠคํŠธํ•  ์ˆ˜ ์žˆ์–ด.


import asyncio
import unittest

async def async_sum(a, b):
    await asyncio.sleep(0.1)  # ๋น„๋™๊ธฐ ์ž‘์—…์„ ์‹œ๋ฎฌ๋ ˆ์ด์…˜
    return a + b

class TestAsyncSum(unittest.TestCase):
    def test_async_sum(self):
        result = asyncio.run(async_sum(1, 2))
        self.assertEqual(result, 3)

    async def async_test_sum(self):
        result = await async_sum(1, 2)
        self.assertEqual(result, 3)

    def test_async_sum_with_loop(self):
        async def run_test():
            return await self.async_test_sum()
        asyncio.run(run_test())

if __name__ == '__main__':
    unittest.main()

์ด ์˜ˆ์ œ์—์„œ๋Š” ์„ธ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์œผ๋กœ ๋น„๋™๊ธฐ ํ•จ์ˆ˜๋ฅผ ํ…Œ์ŠคํŠธํ•˜๊ณ  ์žˆ์–ด. asyncio.run()์„ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•, ๋น„๋™๊ธฐ ํ…Œ์ŠคํŠธ ๋ฉ”์„œ๋“œ๋ฅผ ์ •์˜ํ•˜๋Š” ๋ฐฉ๋ฒ•, ๊ทธ๋ฆฌ๊ณ  ์ด๋ฒคํŠธ ๋ฃจํ”„ ๋‚ด์—์„œ ๋น„๋™๊ธฐ ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ณด์—ฌ์ฃผ๊ณ  ์žˆ์ง€.

๐Ÿ’ก Pro Tip: ๋น„๋™๊ธฐ ์ฝ”๋“œ๋ฅผ ํ…Œ์ŠคํŠธํ•  ๋•Œ๋Š” mock ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•ด ์™ธ๋ถ€ ์˜์กด์„ฑ(์˜ˆ: ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค, ๋„คํŠธ์›Œํฌ ์š”์ฒญ)์„ ๋Œ€์ฒดํ•˜๋Š” ๊ฒƒ์ด ์ข‹์•„. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ํ…Œ์ŠคํŠธ ์‹คํ–‰ ์‹œ๊ฐ„์„ ์ค„์ด๊ณ  ๋” ์•ˆ์ •์ ์ธ ํ…Œ์ŠคํŠธ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์–ด. ์žฌ๋Šฅ๋„ท์—์„œ ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ํ•  ๋•Œ ์ด๋Ÿฐ ํ…Œ์ŠคํŒ… ๊ธฐ๋ฒ•์„ ์ ์šฉํ•˜๋ฉด ์ฝ”๋“œ์˜ ํ’ˆ์งˆ์„ ํฌ๊ฒŒ ๋†’์ผ ์ˆ˜ ์žˆ์„ ๊ฑฐ์•ผ!

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

๋น„๋™๊ธฐ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์€ ์ฒ˜์Œ์—๋Š” ์กฐ๊ธˆ ์–ด๋ ต๊ฒŒ ๋Š๊ปด์งˆ ์ˆ˜ ์žˆ์–ด. ํ•˜์ง€๋งŒ ๊ณ„์† ์—ฐ์Šตํ•˜๊ณ  ์‹ค์ œ ํ”„๋กœ์ ํŠธ์— ์ ์šฉํ•ด ๋ณด๋ฉด, ์ ์  ๋” ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋  ๊ฑฐ์•ผ. ๊ทธ๋ฆฌ๊ณ  ๊ทธ ๊ณผ์ •์—์„œ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์˜ ์ƒˆ๋กœ์šด ์ฐจ์›์„ ๊ฒฝํ—˜ํ•˜๊ฒŒ ๋  ๊ฑฐ๋ผ๊ณ  ํ™•์‹ ํ•ด!

์—ฌ๊ธฐ๊นŒ์ง€ Python์˜ ๋น„๋™๊ธฐ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์— ๋Œ€ํ•œ ๊นŠ์ด ์žˆ๋Š” ์„ค๋ช…์ด์—ˆ์–ด. ์ด ์ง€์‹์„ ๋ฐ”ํƒ•์œผ๋กœ ๋” ํšจ์œจ์ ์ด๊ณ  ๊ฐ•๋ ฅํ•œ ํ”„๋กœ๊ทธ๋žจ์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๊ธฐ๋ฅผ ๋ฐ”๋ผ! ํ™”์ดํŒ…! ๐Ÿš€๐Ÿ