ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Python] 서브루틴과 코루틴 — 흐름을 누가 쥐고 있는가
    IT 2026. 1. 23. 11:12

    프로그램을 작성할 때 우리는 끊임없이 함수를 호출합니다. 너무 자연스럽게 쓰다 보니, 보통은 이런 질문을 하지 않습니다.

    “함수를 호출하면, 흐름은 누가 가지고 있을까?”

    서브루틴과 코루틴의 차이는 문법의 차이가 아니라, 바로 이 제어 흐름(control flow) 에 대한 관점 차이에서 시작됩니다. 이 글에서는 두 개념을 비동기 문법이나 구현 세부가 아니라, 프로그램이 어떻게 실행을 이어가는가라는 큰 그림에서 풀어보려 합니다.


    우리가 익숙한 함수는 서브루틴이다

    우리가 일반적으로 사용하는 함수는 모두 서브루틴(subroutine) 입니다.

    def add(a, b):
        return a + b
    
    result = add(1, 2)

    이 코드에서 흐름은 명확합니다.

    1. add를 호출하면
    2. 호출한 쪽의 실행은 멈추고
    3. 함수가 끝날 때까지 기다린 뒤
    4. 결과를 받아 다시 이어서 실행합니다

    즉, 흐름의 주도권은 항상 호출자에게 있습니다. 서브루틴은 이름 그대로 “하위 작업”입니다.


    서브루틴의 한계

    서브루틴 구조는 단순하고 이해하기 쉽지만, 한 가지 제약이 있습니다.

    • 한 번 호출되면
    • 끝날 때까지
    • 중간에 흐름을 돌려줄 수 없다

    이 구조는 계산에는 잘 맞지만, 다음과 같은 상황에서는 답답해집니다.

    • 중간 결과를 여러 번 내놓고 싶을 때
    • 상태를 유지한 채로 여러 번 재개하고 싶을 때
    • 협력적으로 작업을 나누고 싶을 때

    이 지점에서 코루틴이 등장합니다.


    코루틴은 흐름을 주고받는다

    코루틴(coroutine)은 이름 그대로 함께 실행되는 루틴입니다.

    핵심 차이는 이것입니다.

    코루틴은 실행을 멈췄다가, 다시 이어서 실행할 수 있다

    즉, 코루틴은 실행 상태를 기억한 채로 흐름을 호출자에게 양보(yield) 할 수 있습니다.


    파이썬에서 코루틴을 가장 단순하게 보면

    파이썬에서 코루틴의 가장 직관적인 형태는 yield를 사용하는 함수입니다.

    def counter():
        yield 1
        yield 2
        yield 3

    이 함수는 한 번에 끝까지 실행되지 않습니다.

    c = counter()
    next(c) # 1
    next(c) # 2
    next(c) # 3

    여기서 중요한 점은 counter자기 상태를 기억하고 있다는 것입니다. 이것이 서브루틴과의 결정적인 차이입니다.


    흐름의 방향이 바뀐다

    서브루틴에서는 항상 이렇게 흐름이 움직입니다.

    caller → callee → caller

    하지만 코루틴에서는 흐름이 이렇게 오갑니다.

    caller ⇄ coroutine

    호출자와 코루틴은 상하 관계가 아니라, 협력 관계에 가깝습니다.


    왜 코루틴이 필요해졌을까

    코루틴은 단순한 트릭이 아니라, 현실적인 문제에서 등장했습니다.

    • I/O 대기
    • 이벤트 처리
    • 비동기 작업

    이런 작업들은 “끝날 때까지 기다리는 서브루틴”보다, 잠깐 실행하고 양보하는 구조가 훨씬 효율적입니다.


    async / await는 코루틴의 진화형이다

    파이썬의 async / await 문법은 완전히 새로운 개념이 아닙니다. 기존의 코루틴 개념을 언어 차원에서 안전하게 정리한 형태에 가깝습니다.

    async def fetch():
        await something()

    여기서도 핵심은 같습니다.

    • 실행을 멈추고
    • 다른 작업에게 흐름을 넘기고
    • 다시 돌아와 이어서 실행

    서브루틴 vs 코루틴 한 문장 정리

    • 서브루틴 → 호출되면 끝까지 실행한다
    • 코루틴 → 실행하다가 흐름을 돌려준다

    차이는 작아 보이지만, 이 차이가 프로그램 구조를 완전히 바꿉니다.


    마무리하며

    코루틴과 서브루틴의 차이는 비동기냐 아니냐의 문제가 아닙니다.

    그보다는 이렇게 정리할 수 있습니다.

    “누가 실행 흐름을 쥐고 있는가?”

    이 질문에 대한 답이 달라지는 순간, 함수는 더 이상 단순한 호출 대상이 아니라, 협력하는 실행 단위가 됩니다. 그리고 그 지점이 바로 코루틴의 출발점입니다.

Designed by Tistory.