개념 잡동사니

코루틴(coroutine)

wikys 2026. 4. 7. 10:08

잘난 척을 위한 한 줄 요약

코루틴은 “작업을 끝까지 한 번에 밀어붙이는 함수”가 아니라, 중간에 잠깐 멈췄다가 다시 이어서 실행할 수 있는 함수 실행 단위이고, 그래서 스레드를 마구 늘리지 않고도 동시성을 다루게 해 준다.

 

코루틴, 비동기 프로그래밍이 왜 갑자기 덜 복잡해 보이기 시작했을까

코루틴이란 무엇일까?

코루틴(coroutine)은 실행 도중 일시 중단(suspend) 했다가, 나중에 이어서 재개(resume) 할 수 있는 계산 단위다. Python asyncio 문서는 async/await로 코루틴을 다루는 방식을 설명하고 있고, Kotlin 공식 문서도 코루틴을 중단 가능한 계산(suspendable computation) 이라고 설명한다. 즉, 코루틴의 핵심은 “동시에 여러 일을 한다”보다 먼저, 중간에 멈출 수 있고 다시 이어갈 수 있다는 데 있다.

 

처음 들으면 “그럼 그냥 함수랑 뭐가 다른데?” 싶다.
보통 함수는 호출되면 끝날 때까지 쭉 실행된다. 반면 코루틴은 네트워크 응답을 기다리거나, 특정 작업이 끝나길 기다리는 순간에 실행 흐름을 잠깐 넘겨주고, 나중에 이어서 돌아올 수 있다. 그래서 코드 모양은 순차적인데, 실제로는 비동기 작업을 훨씬 자연스럽게 표현할 수 있다. Kotlin 문서도 코루틴이 자연스럽고 순차적인 스타일로 비동기 코드를 쓰게 해 준다고 설명한다.

 


왜 코루틴이 중요할까?

코루틴이 중요한 이유는 비동기 프로그래밍이 원래 꽤 지저분했기 때문이다.
예전에는 콜백을 넘기고, 완료되면 다시 콜백을 부르고, 그 안에서 또 다음 작업을 거는 식으로 코드가 꼬이기 쉬웠다. Python asyncio 문서는 async/await가 비동기 코드를 쓰는 기반이라고 설명하고, Kotlin 문서는 코루틴이 스레드보다 가볍고 자원 친화적이라 미세한 단위의 동시성에 더 적합하다고 설명한다.

 

즉, 코루틴은 단순히 멋진 문법이 아니라 “기다리는 동안 멍하니 막히지 말고, 다른 일을 하자”를 훨씬 읽기 좋은 코드로 바꿔 준다. 그래서 웹 서버, 네트워크 클라이언트, UI 앱, 데이터 파이프라인처럼 기다림이 많은 프로그램에서 특히 빛난다. Python asyncio는 고성능 네트워크 서버, DB 라이브러리, 분산 작업 큐의 기반으로 쓰인다고 문서에서 설명한다.

 


스레드와는 뭐가 다를까?

이건 제일 많이 헷갈리는 포인트다.

 

스레드는 운영체제가 관리하는 실행 단위다

스레드는 운영체제 수준에서 스케줄링되는 실행 단위다. 여러 스레드를 만들면 동시에 여러 일을 진행할 수 있지만, 생성 비용과 문맥 전환 비용이 있고 공유 자원 동기화도 까다롭다. Kotlin 공식 문서는 코루틴을 lightweight alternative to threads 라고 설명한다.

 

코루틴은 더 가벼운 협력형 실행 단위에 가깝다

코루틴은 보통 런타임이나 프레임워크가 관리한다. 스레드처럼 아무 때나 강제로 끊기는 느낌보다, 중단 가능한 지점에서 스스로 실행을 양보하는 구조에 가깝다. 그래서 코루틴은 적은 자원으로도 훨씬 많이 만들 수 있고, 기다리는 작업이 많을 때 특히 효율적이다. Kotlin은 코루틴이 system resources를 막지 않고 suspend할 수 있다고 설명한다.

 

아주 거칠게 말하면 이렇게 기억하면 된다.

  • 스레드: 무거운 작업자
  • 코루틴: 가벼운 작업 예약 단위

다만 이것도 완전히 따로 노는 건 아니다. 많은 코루틴은 결국 어떤 스레드 위에서 실행된다. Kotlin 문서도 코루틴 컨텍스트와 디스패처가 어떤 스레드/스레드풀에서 실행될지를 결정한다고 설명한다.

 


코루틴은 실제로 어떻게 움직일까?

코루틴을 이해하는 데 가장 좋은 감각은 “작업을 분할해서 넘긴다”는 느낌이다.

예를 들어 파일을 읽고, 네트워크를 기다리고, 결과를 저장하는 코드가 있다고 하자.
일반 함수라면 네트워크 응답이 올 때까지 흐름이 막힐 수 있다. 그런데 코루틴은 await나 suspend 같은 지점에서 “여기서는 기다려야 하니까, 일단 다른 작업부터 돌려”라고 런타임에 넘길 수 있다. Python 문서는 await 가능한 객체와 태스크를 통해 이런 흐름을 설명하고, Kotlin 문서는 suspending functions를 통해 이런 패턴을 다룬다.

 

여기서 중요한 건, 코루틴이 “마법처럼 병렬 처리”를 한다기보다 기다리는 시간에 CPU를 낭비하지 않게 만드는 구조라는 점이다.
즉, 계산이 엄청 무거운 작업을 무조건 빠르게 만드는 기술이라기보다, 입출력 대기와 동시성 제어를 효율적으로 만들기 위한 모델에 더 가깝다. Python asyncio의 이벤트 루프 문서도 이벤트 루프가 비동기 태스크와 콜백, 네트워크 I/O를 실행하는 핵심이라고 설명한다.

 


언어마다 코루틴이 완전히 같을까?

같은 이름을 쓰지만, 느낌은 조금씩 다르다.

 

Python에서는 async/await와 이벤트 루프 중심이다

Python에서는 async def로 코루틴 함수를 만들고, await로 다른 어웨이터블을 기다린다. 그냥 코루틴 함수를 호출하는 것만으로는 바로 실행되지 않고, 이벤트 루프에서 실행되도록 예약하거나 await 해야 한다고 문서가 분명히 설명한다.

 

Kotlin에서는 suspend, launch, async, 디스패처가 핵심이다

Kotlin에서는 suspend 함수와 kotlinx.coroutines 라이브러리를 중심으로 코루틴을 쓴다. launch, async, flow, channel 같은 고수준 도구가 잘 발달해 있어서, 안드로이드나 서버 개발에서 코루틴이 널리 쓰인다. 공식 문서도 kotlinx.coroutines를 코루틴을 위한 풍부한 라이브러리라고 설명한다.

 

JavaScript는 보통 제너레이터와 async/await를 구분해서 봐야 한다

JavaScript의 yield는 제너레이터를 멈췄다가 재개하는 데 쓰인다. 문법적으로는 코루틴 느낌이 나지만, 일반적으로 현대 JS 비동기 코드는 async/await와 Promise 쪽이 중심이다. MDN은 yield가 generator function 실행을 일시 정지한다고 설명한다.

즉, 코루틴은 공통 철학은 비슷하지만 언어마다 구현 방식과 실무 패턴은 꽤 다를 수 있다는 걸 알아두면 좋다.

 


코루틴이 특히 잘 맞는 상황은?

네트워크 요청이 많은 프로그램

웹 크롤러, API 서버, 채팅 서버, DB 연동 코드처럼
입출력 대기가 많은 프로그램은 코루틴과 궁합이 좋다. Python asyncio와 Kotlin 튜토리얼 모두 네트워크 요청을 막지 않고 처리하는 예제를 중심으로 설명한다.

 

UI 앱처럼 “멈추면 안 되는” 환경

안드로이드 같은 환경에서는 메인 스레드를 막지 않으면서 백그라운드 작업을 처리해야 한다. Kotlin 코루틴이 크게 퍼진 이유 중 하나도 이런 UI/비동기 조합을 더 읽기 좋게 만들었기 때문이다. Kotlin 공식 문서는 디스패처와 컨텍스트를 통해 실행 스레드를 제어하는 방식을 설명한다.

 

비동기 데이터 흐름 처리

Kotlin Flow처럼 비동기 스트림을 다루는 구조는 코루틴 기반으로 설계돼 있다. 공식 문서는 Flow를 비동기 데이터 스트림으로 설명하며, 기본적으로 sequential하게 동작한다고 밝힌다.

 


코루틴을 배울 때 자주 하는 오해

1. 코루틴 = 무조건 병렬 처리, 는 아니다

코루틴은 동시성을 쉽게 표현해 주지만, 자동으로 CPU 병렬 처리를 보장하는 건 아니다. 어떤 스레드나 디스패처에서 돌리는지에 따라 실제 병렬성은 달라진다. Kotlin 문서는 코루틴이 concurrently run 할 수 있고 potentially in parallel 하다고 설명한다. 즉, 병렬은 가능하지만 자동 보장은 아니다.

 

2. await는 그냥 느린 함수 호출이 아니다

await는 “시간 오래 걸리는 함수 부르기”가 아니라, 이 지점에서 잠깐 멈추고 다른 일 하도록 넘길 수 있는 지점이라는 의미가 더 중요하다. Python의 asyncio 개념 문서도 await 뒤에서 무슨 일이 벌어지는지 이해하는 게 중요하다고 설명한다.

 

3. 코루틴을 많이 만들면 아무 문제도 없다, 도 아니다

코루틴은 스레드보다 가볍지만 공짜는 아니다. 취소, 예외 전파, 공유 자원 접근, 이벤트 루프 블로킹 같은 문제는 여전히 중요하다. Python의 개발 가이드 문서도 비동기 프로그래밍에서 흔한 실수와 함정을 따로 설명한다.

 


결국 핵심은 이것이다

코루틴은 중간에 멈췄다가 다시 이어갈 수 있는 실행 단위이고, 비동기 코드와 동시성 코드를 훨씬 읽기 좋은 순차 스타일로 만들게 해 준다. Python에서는 asyncio와 이벤트 루프, Kotlin에서는 suspend와 kotlinx.coroutines가 대표적인 실전 형태다. 그리고 진짜 포인트는 “더 빨라진다”보다 기다림이 많은 프로그램을 덜 복잡하고 덜 무겁게 만든다는 데 있다.

 

아주 짧게 정리하면 이렇게 기억하면 된다.

스레드가 작업자를 늘리는 방식이라면, 코루틴은 기다리는 시간을 잘게 나눠서 흐름을 똑똑하게 이어 붙이는 방식이다.

 


참고 자료

 

A Conceptual Overview of asyncio

This HOWTO article seeks to help you build a sturdy mental model of how asyncio fundamentally works, helping you understand the how and why behind the recommended patterns. You might be curious abo...

docs.python.org

 

Coroutine context and dispatchers | Kotlin

 

kotlinlang.org

 

yield - JavaScript | MDN

 

developer.mozilla.org

 


참고 영상

 

- YouTube

 

www.youtube.com

 

- YouTube

 

www.youtube.com

 

- YouTube

 

www.youtube.com

 

- YouTube

 

www.youtube.com

 

반응형