
1. 기본/개요
asyncio는 파이썬 표준 라이브러리에 포함된 비동기 I/O 모듈로, 공식 문서에 따르면 코루틴을 사용해 단일 스레드 기반의 동시성(concurrent) 코드를 작성하기 위한 인프라를 제공하며, 소켓과 기타 리소스에 대한 I/O 접근을 멀티플렉싱하고, 네트워크 클라이언트·서버 및 관련된 기본 요소들을 실행하는 데 쓰입니다. Python 3.4 문서를 보면 asyncio 패키지는 최초 도입 당시 표준 라이브러리에 "잠정적(provisional)"으로 포함되었으며, 핵심 개발자들이 필요하다고 판단하면 모듈 제거를 포함한 하위 호환성 깨는 변경이 있을 수 있다고 명시되어 있었습니다. 이후 버전을 거치며 async/await 문법 등이 정식으로 자리 잡아 현재는 표준 라이브러리의 안정적인 일부로 사용되고 있습니다.
asyncio의 핵심 개념은 이벤트 루프(event loop)입니다. 최신 공식 개념 개요 문서는 이벤트 루프를 "오케스트라 지휘자"에 비유하며, 이벤트 루프 자체는 실행해야 할 작업(job)들의 모음을 가지고 있고, 이 작업들을 하나씩 꺼내 실행 권한을 넘겨준다고 설명합니다.
2. 기능/스펙
asyncio 공식 문서는 이 모듈이 제공하는 기능으로, 파이썬 코루틴을 동시에 실행하며 그 실행을 완전히 제어하는 기능, 네트워크 I/O와 IPC(프로세스 간 통신) 수행, 서브프로세스 제어, 큐를 통한 작업 분배, 동시 실행 코드의 동기화 등을 제시합니다. 애플리케이션 개발자 입장에서는 asyncio.run()과 같은 고수준 API를 주로 사용해야 하며, 이벤트 루프 객체나 그 메서드를 직접 참조할 일은 드물다고 공식 문서는 권고합니다.
동작 방식과 관련해 중요한 스펙은, Developing with asyncio 문서에 명시된 대로 이벤트 루프는 하나의 스레드(보통 메인 스레드)에서 실행되며, 해당 스레드 안에서 모든 콜백과 태스크를 실행한다는 점입니다. 그리고 하나의 태스크(Task)가 실행되는 동안에는 같은 스레드에서 다른 태스크가 실행될 수 없으며, 태스크가 await 표현식을 실행하면 그 태스크는 일시 중단되고 이벤트 루프가 다음 태스크를 실행한다고 설명되어 있습니다. 이는 asyncio가 제공하는 것이 진짜 병렬 실행이 아니라 협력적(cooperative) 동시성이라는 점을 보여줍니다.
또한 asyncio 개발 가이드 문서는 CPU 집약적인 계산을 수행하는 블로킹 코드를 이벤트 루프 안에서 직접 호출해서는 안 된다고 명시합니다. 예를 들어 1초가 걸리는 CPU 집약적 계산을 수행하는 함수를 그대로 호출하면 다른 모든 동시 실행 중인 asyncio 태스크와 I/O 작업이 그 1초 동안 지연된다고 설명하며, 이런 경우 다른 스레드나 별도 프로세스에서 실행하도록 executor(예: ThreadPoolExecutor, ProcessPoolExecutor)를 활용해야 한다고 안내합니다.
3. 장단점 (내 생각과 비판 포함)
asyncio의 장점은 스레드나 프로세스를 여러 개 만들지 않고도 대량의 I/O 대기(네트워크 요청, 파일 입출력 등)를 효율적으로 처리할 수 있다는 데 있습니다. 특히 다수의 외부 API를 동시에 호출해야 하는 상황에서는 순차적인 requests 기반 코드보다 훨씬 짧은 시간에 작업을 마칠 잠재력이 있습니다.
다만 개인적으로 asyncio를 다룰 때 가장 아쉬운 부분은 진입장벽입니다. 공식 문서 자체가 이벤트 루프, 코루틴, 태스크, Future라는 여러 층위의 개념을 요구하고, "CPU 바운드 코드를 직접 호출하면 안 된다"처럼 암묵적인 규칙을 지키지 않으면 오히려 전체 애플리케이션이 멈추는 역설적 상황이 발생합니다. 이는 asyncio의 결함이라기보다 협력적 동시성 모델 자체의 본질적 특성이지만, 동기 코드에 익숙한 개발자에게는 상당한 사고 전환이 필요하다는 점에서 비판적으로 짚을 만합니다. 또한 asyncio 생태계에 참여하려면 requests 대신 aiohttp나 httpx처럼 asyncio 호환 라이브러리로 바꿔야 하는 경우가 많아, 기존 동기 코드베이스를 부분적으로만 비동기화하기가 쉽지 않다는 점도 실무에서 자주 부딪히는 제약입니다.
4. 추천대상
수많은 네트워크 요청이나 I/O 대기가 반복되는 애플리케이션, 예를 들어 다수의 API를 동시에 호출하는 서비스, 채팅 서버, 웹소켓 기반 실시간 서비스를 만드는 개발자에게 asyncio는 적합한 선택입니다. 반대로 CPU 연산이 주된 작업(예: 이미지 처리, 수치 계산)이라면 asyncio 단독으로는 이득이 없으며, 멀티프로세싱 쪽이 더 적합합니다. 또한 비동기 프로그래밍 경험이 전혀 없는 입문자라면, 먼저 동기 코드로 로직을 완성한 뒤 asyncio로 전환하는 학습 순서를 권장할 만합니다.
5. FAQ
Q1. asyncio는 언제부터 파이썬 표준 라이브러리에 포함되었나요?
A. Python 3.4 공식 문서에 따르면 asyncio 패키지는 Python 3.4에서 처음 표준 라이브러리에 포함되었으며, 당시에는 잠정적(provisional) 상태였습니다.
Q2. asyncio는 진짜 병렬 처리를 제공하나요?
A. 아닙니다. 공식 문서에 따르면 이벤트 루프는 하나의 스레드에서 실행되고, 한 태스크가 실행되는 동안 같은 스레드의 다른 태스크는 실행될 수 없습니다. 즉 asyncio는 동시성(concurrency)을 제공하는 것이지 병렬성(parallelism)을 제공하는 것이 아닙니다.
Q3. CPU 연산이 많은 함수를 asyncio 코드 안에서 그대로 호출해도 되나요?
A. 권장되지 않습니다. 공식 개발 가이드는 블로킹(CPU 바운드) 코드를 직접 호출하지 말고 executor를 통해 다른 스레드나 프로세스에서 실행하라고 안내합니다.
Q4. asyncio를 시작할 때 권장되는 진입점은 무엇인가요?
A. 공식 문서는 애플리케이션 개발자가 asyncio.run() 같은 고수준 함수를 사용하고, 이벤트 루프 객체를 직접 다루는 일은 최소화할 것을 권장합니다.
6. 출처
Python 공식 문서, asyncio — Asynchronous I/O (docs.python.org/3/library/asyncio.html)
Python 공식 문서, A Conceptual Overview of asyncio (docs.python.org/3/howto/a-conceptual-overview-of-asyncio.html)
Python 공식 문서, Developing with asyncio (docs.python.org/3/library/asyncio-dev.html)
Python 3.4 공식 문서, asyncio 모듈 소개 (docs.python.org/3.4/library/asyncio.html)
Python 공식 문서, Coroutines and tasks (docs.python.org/3/library/asyncio-task.html)