[Python] 코루틴(Coroutine) - 네이티브 코루틴과 제너레이터 기반 코루틴

solved_err.log·2023년 3월 14일
0
post-custom-banner

파이썬을 이용해 비동기 파트를 다루면서 다음 용어에 대해 많이 접하게 되었다.
한 번쯤 들어봤을 코루틴, 제너레이터와 이터레이터에 대해 정리해보았다.


코루틴(Coroutine)

네이티브 코루틴(Native Coroutine)

파이썬에서 여러 작업을 동시에 병렬 처리하기 위해 비동기(Asynchronous) 함수를 사용한다.

async def cr_func():
    print('test')

이렇게 async 키워드로 만든 비동기 함수를 코루틴(Coroutine) 또는 코루틴 함수라고 한다. 그렇다면, 이 코루틴 함수는 언제 어떻게 사용하는 것일까?

async def cr_func():
    print('test')
    
cr_func()


### ----- Result ----- ###
RuntimeWarning: coroutine 'cr_func' was never awaited
### ------------------- ###

cr_func 이라는 이름의 코루틴 함수를 선언하고 호출하자 다음과 같은 에러가 나타났다.
async 키워드로 선언된 코루틴 함수는 일반 함수 호출 방식과는 다르며, 다음과 같이 실행한다.

import asyncio

async def cr_func():  # 코루틴 함수 선언
    print('Coroutine Function!')

loop = asyncio.get_event_loop()       # asyncio 모듈의 event loop 객체 생성
loop.run_until_complete(cr_func())  # cr_func 함수가 완전히 종료될 때까지 대기
loop.close()                          # event loop 종료 


### ----- Result ----- ###
Coroutine Function!
### ------------------- ###

📌 asyncio 모듈의 get_event_loop를 얻어와서 run_until_complete의 인자로 코루틴 함수를 전달하여 실행한다.
run_until_complete 함수는 인자로 받은 함수가 완전히 종료될 때까지 이벤트 루프를 실행하게 된다.
이와 같이, async로 선언된 코루틴을 "네이티브 코루틴" 이라고 한다.

다른 함수에서 이 코루틴 함수를 호출할 때는 어떻게 할까?

import asyncio

async def cr_func():
    print('test')

async def main():
    await cr_func()

loop = asyncio.get_event_loop()
loop.run_until_complete(main())
loop.close()

코루틴 함수 생성 방식은 동일하나, 코루틴 함수를 호출하고자 하는 함수에서 await 키워드를 붙여줘야 한다.
await = 말 그대로 cr_func()함수가 완료되기를 기다린 후 결과를 가져온다는 의미이다.

응답을 받을 때까지 아무것도 하지 않고 기다린다는 것이 아니라 해당 함수가 완료될 때까지 다른 작업을 하면서 완료를 기다린다는 의미이다.

제너레이터 기반 코루틴(Generator-based Coroutine)

일반적으로 사용하는 네이티브 코루틴 외의 또 다른 방식인 제너레이터 기반 코루틴에 대해 정리해보았다.

제너레이터에 대해서 정리한 글

다음은 yield 키워드를 통해 메인 루틴과 서브 루틴간에 값을 이동하며 실행의 지연 및 재개를 보여주는 예제이다.

def cr_gen():
    total = 0
    while True:	# 코루틴을 계속 유지하기 위해 무한 루프 사용
        num = yield total # total 발생 및 num에 값 저장
        total += num

cr = cr_gen()
print(next(cr)) # 처음 yield 까지 실행
print(cr.send(3)) # num에 3 저장 후 다음 yield 까지 실행
print(cr.send(2)) # num에 2 저장 후 다음 yield 까지 실행

""" 실행결과
0
3
5
"""

📌이와 같이 코루틴 바깥에서 보낸 값을 yield 변수(여기서는 num)에 받아 저장한 후, 다음 루틴을 실행한다.
정리하면, 핵심은 "코루틴은 yield에서 함수 중간에 대기한 다음에 메인 루틴을 실행하다가 다시 코루틴을 실행한다"는 것이다.

profile
배우고 기록하는 개발 일기장✍
post-custom-banner

0개의 댓글