PEP 342에서 코루틴을 아래와 같이 설명하고 있습니다.
코루틴은 시뮬레이션, 게임, 비동기 I/O, 이벤트 기반 프로그래밍, 그리고 협력적 멀티태스킹과 같은 다양한 알고리즘을 표현하는 자연스러운 방법입니다.
위의 설명 만으로는 코루틴이 무엇인지 전혀 감이 오지 않습니다
이번엔 위키피디아를 찾아봅시다
코루틴은 프로그램의 실행을 일시 중지하고 나중에 재개할 수 있는 프로그램 구성 요소로, 협력적 멀티태스킹을 위해 서브루틴을 일반화한 개념입니다. 코루틴은 협력 작업, 예외 처리, 이벤트 루프, 이터레이터, 무한 리스트 및 파이프와 같은 프로그램 구성 요소를 구현하는 데 적합합니다. 코루틴은 "실행을 일시 중지할 수 있는 함수"로 설명되기도 합니다.
서브루틴은 뭘까요? 다시 위키피디아를 찾아보면
서브루틴은 코루틴의 특별한 경우입니다. 서브루틴이 호출되면 실행은 항상 시작 지점에서 시작되며, 서브루틴이 종료되면 해당 호출은 완전히 종료됩니다. 서브루틴의 인스턴스는 한 번만 반환되며, 호출 사이에 상태를 유지하지 않습니다. 반면, 코루틴은 다른 코루틴을 호출하여 그 지점으로 돌아올 수 있고, 코루틴의 관점에서 보면 종료되는 것이 아니라 다른 코루틴을 호출하는 것입니다. 따라서 코루틴 인스턴스는 상태를 유지하며, 호출 사이마다 상태가 달라집니다. 또한, 주어진 코루틴의 여러 인스턴스가 동시에 존재할 수 있습니다.
위의 내용을 바탕으로
정리해봅시다
coroutine(코루틴)
subroutine
앞서 이야기했던 generator가 coroutine의 개념을 구현한것 같아 보이지 않나요?
하지만 앞서 이야기 했던 generator에는 한계가 존재했습니다.
PEP 342의 motivation에서는 앞서 이야기 했던 generator의 한계점을 명시하고 있습니다.
파이썬의 제너레이터 함수는 거의 코루틴에 가깝지만, 몇 가지 제한이 있습니다. 제너레이터는 실행을 일시 중지하고 값을 반환할 수는 있지만, 중단된 지점에서 재개할 때 값을 전달하거나 예외를 처리할 수 있는 기능은 없습니다. 또한, try/finally 블록의 try 부분에서 실행을 일시 중지할 수 없기 때문에, 중단된 코루틴이 스스로를 정리(clean up)하는 데 어려움이 있습니다.
추가적으로 설명하자면 try/finally 블록에서 try 부분이 실행되는 동안에는 코드가 반드시 완료될 때까지 중단 없이 실행되어야 합니다. 파이썬의 제너레이터에서는 try 블록 안에서 yield를 호출해 실행을 일시 중지할 수 있지만, 만약 그 시점에서 제너레이터가 종료되거나 예외가 발생하면, finally 블록이 실행되지 않을 수 있습니다. 이것이 문제가 되는 이유는 finally 블록이 주로 자원을 정리(clean up)하거나 상태를 복구하는 데 사용되기 때문입니다.
계속해서 봅시다
또한, 제너레이터는 다른 함수가 실행 중일 때 제어권을 반환할 수 없습니다. 그러려면 그 함수들 역시 제너레이터로 작성되어야 하며, 외부 제너레이터는 내부 제너레이터가 반환하는 값을 바탕으로 제어권을 반환하도록 작성되어야 합니다. 이 때문에 비동기 통신과 같은 상대적으로 간단한 사용 사례조차도 구현이 복잡해지며, 함수 호출마다 많은 반복적 코드(boilerplate code)가 필요합니다.
비동기 방식에서는 제어권이 여러 함수 사이를 빠르게 전환해야 하며, 각 함수가 대기 상태에 있을 때 다른 함수가 실행되어야 합니다.
그런데, 제너레이터를 사용하여 이를 구현하려면 모든 함수가 제너레이터로 작성되어야 하고, 모든 함수 호출이 yield와 함께 이루어져야 합니다. 결과적으로 제어 흐름을 일일이 수동으로 관리해야 하고, 많은 반복적인 코드(boilerplate code)가 필요하게 된다는 의미 입니다.
PEP 342에서는 위의 한계점을 보완하기 위해 몇 가지 새로운 메서드와 문법 개선을 제안했습니다. 이를 통해 generator를 coroutine으로 더 쉽게 사용할 수 있게 되었습니다.
PEP 342 – Coroutines via Enhanced Generators
: https://peps.python.org/pep-0342/
위키피디아 coroutine: https://en.wikipedia.org/wiki/Coroutine