FastAPI가 기반으로 하고 있는 Starlette(ASGI 프레임워크)와 uvicorn(ASGI 서버)이 이 모델을 채택한 데에는 네 가지 핵심적인 이유가 있다.
1. 현대 웹의 핵심: I/O Bound 작업의 압도적 비중
현대 웹 서비스에서 CPU가 연산을 수행하는 시간보다 **'기다리는 시간'**이 훨씬 많다.
- 데이터베이스 쿼리 결과 기다리기
- 외부 API 호출 응답 기다리기
- 파일 업로드/다운로드 기다리기
이러한 I/O Bound 상황에서 전통적인 멀티스레드 모델은 각 요청마다 스레드를 할당한다. 요청이 1만 개(C10k 문제)가 들어오면 스레드도 1만 개가 필요하며, 이는 엄청난 메모리 낭비와 컨텍스트 스위칭(Context Switching) 비용을 초래한다.
이벤트 루프는 이 '기다리는 시간'에 CPU를 놀리지 않고 다른 요청을 처리하게 함으로써, 적은 자원으로도 수만 개의 동시 접속을 처리할 수 있게 한다.
2. Python의 기술적 제약: GIL (Global Interpreter Lock)
Python에는 GIL이라는 제약이 있다. 한 프로세스 내에서 여러 스레드가 있더라도, 실제로 Python 바이트코드를 실행할 수 있는 스레드는 한 번에 하나뿐이다.
즉, Python에서 멀티스레드를 써도 CPU 연산 자체는 병렬로 처리되지 않는다. 오히려 스레드 간의 제어권을 주고받는 오버헤드만 발생할 수 있다.
이벤트 루프 모델은 GIL의 제약 하에서 '병렬성(Parallelism)' 대신 **'동시성(Concurrency)'**을 극대화하여 효율을 뽑아내는 가장 영리한 방법이다.
3. 리소스 효율성 (Memory & Overhead)
- 스레드(Thread): 생성 시 보통 수 MB의 스택 메모리를 점유한다. 수천 개의 스레드는 시스템 메모리를 금방 고갈시킨다.
- 코루틴(Coroutine): async 함수는 스레드가 아닌 객체로 관리되며, 점유 메모리가 수 KB 수준이다.
이 덕분에 FastAPI는 매우 가벼우며, 낮은 사양의 컨테이너 환경(Docker/Kubernetes)에서도 높은 성능을 낼 수 있다.
4. 개발의 단순성과 안전성
멀티스레드 환경에서는 여러 스레드가 동일한 자원에 접근할 때 **경쟁 상태(Race Condition)**나 데드락(Deadlock) 문제가 발생하기 쉽다. 이를 막기 위해 Lock이나 Semaphore 같은 복잡한 도구가 필요하다.
이벤트 루프 모델은 단일 스레드에서 실행되므로, await 포인트가 아닌 이상 코드가 중간에 끊기지 않는다는 것이 보장된다. 이는 공유 자원 관리의 난이도를 획기적으로 낮춰준다.
요약: 이 모델의 트레이드오프
FastAPI는 **"웹 서버의 본질은 빠른 응답과 높은 동시성"**이라는 점에 집중했다.
| 장점 (득) | 단점 (실) |
|---|---|
| 수만 개의 동시 연결 처리 가능 (High Concurrency) | 단일 요청 내 무거운 CPU 연산 시 전체 서버 마비 |
| 메모리 점유율이 매우 낮음 | 멀티코어 CPU를 100% 활용하려면 여러 프로세스를 띄워야 함 |
| 코드 구조가 직관적이고 관리가 쉬움 | 비동기를 지원하지 않는 라이브러리 사용 시 효율 급감 |
결론적으로, FastAPI는 Node.js나 Go가 증명한 현대적 네트워크 처리 방식을 Python 생태계에 가장 효율적으로 이식하기 위해 이 모델을 선택한 것이다.