asyncio๋ฅผ ๊ณต๋ถํ๋ ค๋ค๊ฐ ์ ๋ชจ๋ฅด๋ ๋ถ๋ถ์ด ๋ง์์ ๊ทธ๋ฅ ๋ชจ๋ฅด๋ ๋ถ๋ถ๋ถํฐ ๊ณต๋ถํ๊ณ ๋์ด๊ฐ๊ณ ์ ํ๋ค.
1. ์ฝ๋ฃจํด(coroutine) ์ด๋?
- cooperative routine์ ์๋ฏธํ๋๋ฐ, ์๋ก ํ๋ ฅํ๋ ๋ฃจํด์ด๋ผ๋ ๋ป์ด๋ค.
- ์ฐ์ ๋ฃจํด์ด๋ผ๋ ๊ฐ๋ ๋ถํฐ ์ดํด๋ณธ๋ค.
def add(a, b):
c = a + b # add ํจ์๊ฐ ๋๋๋ฉด ๋ณ์์ ๊ณ์ฐ์์ ์ฌ๋ผ์ง
print(c)
print('add ํจ์')
def calc():
add(1, 2) # add ํจ์๊ฐ ๋๋๋ฉด ๋ค์ calc ํจ์๋ก ๋์์ด
print('calc ํจ์')
calc()
์ด ์ฝ๋์์ calcํจ์์์ add๋ฅผ ๋ถ๋ ๊ณ , addํจ์๊ฐ ๋๋๋ฉด calc๋ก ๋ค์ ๋์์จ๋ค. ์ด๋, calc๊ฐ ๋ฉ์ธ ๋ฃจํด์ด๊ณ , add๋ ์๋ธ๋ฃจํด์ด ๋๋ ๊ฑฐ๋ค.
- ์ด๋ฐ์์ ํ๋ก์ฐ๋ฅผ ๊ฐ์ง๊ณ ์๋ค.
- ์ฝ๋ฃจํด์ ํ๋ก์ฐ
- ์ด์ฒ๋ผ ์ฝ๋ฃจํด์ ํจ์๊ฐ ์ข ๋ฃ๋์ง ์์ ์ํ์์ ๋ฉ์ธ ๋ฃจํด์ ์ฝ๋๋ฅผ ์คํํ๊ณ , ๋ค์ ๋์์ ์ฝ๋ฃจํด์ ์ฝ๋๋ฅผ ์คํํ๋ค. ํจ์์ ์ฝ๋๋ฅผ ์คํํ๋ ์ง์ ์ ์ง์ ์ (entry point)๋ผ๊ณ ํ๋๋ฐ, ์ฝ๋ฃจํด์ ์ง์ ์ ์ด ์ฌ๋ฌ๊ฐ๋ค. ์ด๋ฐ ์ ์์ ์ฝ๋ฃจํด์ ์ผ๋ฐ ๋ฃจํด์ ๋นํด ๋ฉ์ธ๋ฃจํด๊ณผ ์ข ์๊ด๊ณ๊ฐ ์๋, ๋๋ฑ๊ด๊ณ์ด๋ฉฐ, ๊ทธ๋์ ํ๋ ฅํ๋ ๋ฃจํด์ด๋ค.
- ์ด๋ ๊ฒ ๊ณ์ ํํ๋๋ ๊ฑธ ๋ณดํต loop๋ฅผ ํตํด ๊ตฌํ์ ํ๊ณ , close()๋ฅผ ํตํด ๋ฉ์ถ๋ค.
(1) Asymmertric coroutine (generator based coroutine)
- Python์ generator๋ฅผ ์ด์ฉํ ์ฝ๋ฃจํด์ ๋งํ๋ค.
- generator ํจ์ ์์ yield๋ฅผ ์ด์ฉํด ์คํ์ด ์ผ์์ ์ง๋์ด์๋ generator์๊ฒ ๊ฐ์ ์ ๋ฌํ๋ ์์ผ๋ก ๊ตฌํํ ์ ์๋ค.
def inner():
yield 'INNER'
yield 'GENERATOR'
yield 'YEAH!'
def outer():
yield 'Get ready for ...'
yield from inner()
gen = outer()
print(next(gen))
Get ready for ...
print(next(gen), next(gen), next(gen))
INNER GENERATOR YEAH!
- ์ ์ฝ๋๋ outer() ์ ๋๋ ์ดํฐ ์์ inner()๋ผ๋ ๋ค๋ฅธ ์ ๋๋ ์ดํฐ๋ฅผ ์์ฑํ์ฌ yieldํ๋ ์์ผ๋ก ์ฝ๋ฃจํด์ ๋ง๋ค์๋ค.
- ์ด๋ ๊ฒ ๊ตฌํํ ์ ๋๋ ์ดํฐ๋ค์ ํญ์ ์์ ์ caller์๊ฒ ์คํ ์์๋ฅผ ๋๊ฒจ์ฃผ๊ฒ ๋๋ค.
(2) Symmetric coroutine (Natice Coroutine)
- ๋ฌด์กฐ๊ฑด caller์๋ง ์ํธ์์ฉํ๋ ๊ธฐ์กด ์ฝ๋ฃจํด์์ ๊ฐ๊ฐ์ ์ฝ๋ฃจํด๋ค์ด ์๋ก์๊ฒ ์คํ ์์๋ฅผ ๋๊ฒจ์ฃผ๋ ๊ฒ์ฒ๋ผ ๋ณด์ด๊ฒ ํ๋ ์ฝ๋ฃจํด์ด๋ค.
import asyncio
async def echo_twice(msg):
print(msg)
await asyncio.sleep(1)
print(msg)
loop = asyncio.get_event_loop()
asyncio.ensure_future(echo_twice('Hello'))
asyncio.ensure_future(echo_twice('There'))
loop.run_forever()
Hello
There
# ์ฃผ์ถค...
Hello
There
- asnyc๋ฅผ ํตํด echo_twice()๋ฅผ ์ฝ๋ฃจํด ํจ์๋ก ์ ์ํ๋ค. asyncio.ensure_future()๋ฅผ ํตํด ์คํํ ์ฝ๋ฃจํด์ ์์ฑํ๋ค.
- asyncio.get_event_loop()๋ก ๋ฐ์ event loop์ run_forever๋ฅผ ์คํํจ์ผ๋ก์จ ๋๊ฐ์ ์ฝ๋ฃจํด๋ค์ ์คํํ๋ค.
- await๊ฐ yield from์ ๊ฐ๋ ์ผ๋ก, asyncio.sleep(1)์ ํตํด 1์ด๋ค์ ์ฒซ๋ฒ์งธ ์ฝ๋ฃจํด์ ์คํ์ด ์๋ฃ๋๊ณ , ๋ค์ event loop์๊ฒ๋ก ํต์ ๊ถ์ด ๋์ด๊ฐ๊ณ , ๋ค๋ฅธ ์ฝ๋ฃจํด์ด ์คํ๋๋ค.
- event loop๋ single thread์ด๋ฏ๋ก ํ๋ฒ์ ์คํ๋๋ ์ฝ๋ฃจํด์ ํ๋์ด๋ค. ๊ทธ๋์ ๋ณ๋ ฌ์ ์ผ๋ก ์คํ๋๋ ๊ฒ์ ์๋๋ค. ์ด๋ถ๋ถ์ thread์ ๊ฐ๋ ์ด ํ์ํ๋ฏ๋ก ๋ค์ ํฌ์คํ ์์ ์ข ๋ ์์ธํ ๋ค๋ฃจ๋๋ก ํ๋ค.
- ์ด๋ฏธ์ง์์ councurrency์ ํด๋น๋๋ ๋ฐฉ์์ผ๋ก ์ฝ๋ฃจํด๋ค์ด ๋์ํ๋ค.
2. Task๋?
- ์ฐ์ Task์ ์ฝ๋ฃจํด์ ๊ด๊ณ ์ดํด๋ฅผ ์ํด ์ฌ์ง์ ๋จผ์ ๋ณด๋๋ก ํ๋ค.
- ๋์ถฉ ๋ณด๋ฉด task ์์ ์ฝ๋ฃจํด์ด ์๋ค๋ ๊ฑธ ์ ์ ์๋ค.
- ๊ฐ์ฒด๊ฐ await ํํ์์ ์ฌ์ฉ๋ ์ ์์ ๋ ์ด์จ์ดํฐ๋ธ ๊ฐ์ฒด๋ผ๊ณ ๋งํ๋๋ฐ, ์ด ๊ฐ์ฒด์๋ ์ธ๊ฐ์ง ์ ํ์ด ์๋ค. ์ฝ๋ฃจํด, ํ์คํฌ ๋ฐ ํจ์ฒ
- ํ์คํฌ๋ ์ฝ๋ฃจํด์ ๋์์ ์์ฝํ๋ ๋ฐ ์ฌ์ฉ๋๋ค.