Uvicorn - Python ASGI 서버
TL;DR
- Uvicorn - Python ASGI 서버의 핵심 개념과 사용 범위를 한눈에 정리
- 등장 배경과 필요한 이유를 짚고 실무 적용 포인트를 연결
- 주요 특징과 체크리스트를 빠르게 확인
1. 개념
┌─────────────────────────────────────────────────────────────┐ │ │ │ Uvicorn = 초고속 ASGI 웹 서버 │ │ │ │ 이름 유래: UV (Unicorn의 변형) + ASGI │ │ 탄생: 2017년 (Tom Christie 개발) │ │ 특징: 비동기, 빠름, 가벼움 │ │ │ │ 핵심 역할: │ │ ┌─────────────────────────────────────────────────────┐ │ │ │ │ │ │ │ 인터넷 ───────► Uvicorn ───────► FastAPI/Starlette │ │ │ │ (HTTP 요청) (ASGI 서버) (Python 앱) │ │ │ │ │ │ │ └─────────────────────────────────────────────────────┘ │ │ │ │ 비유: │ │ ├── FastAPI = 요리사 (요청을 처리하는 로직) │ │ └── Uvicorn = 식당 입구 (요청을 받아서 요리사에게 전달) │ │ │ └─────────────────────────────────────────────────────────────┘
2. 배경
Uvicorn - Python ASGI 서버이(가) 등장한 배경과 기존 한계를 정리한다.
3. 이유
이 주제를 이해하고 적용해야 하는 이유를 정리한다.
4. 특징
- Nginx 설정 예시
- 관련 키워드
5. 상세 내용
작성일: 2026-01-29 카테고리: Backend / Server / ASGI 포함 내용: Uvicorn, ASGI, WSGI, uvloop, httptools, Gunicorn, 프로덕션 배포
1. Uvicorn이란?
┌─────────────────────────────────────────────────────────────┐
│ │
│ Uvicorn = 초고속 ASGI 웹 서버 │
│ │
│ 이름 유래: UV (Unicorn의 변형) + ASGI │
│ 탄생: 2017년 (Tom Christie 개발) │
│ 특징: 비동기, 빠름, 가벼움 │
│ │
│ 핵심 역할: │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ 인터넷 ───────► Uvicorn ───────► FastAPI/Starlette │ │
│ │ (HTTP 요청) (ASGI 서버) (Python 앱) │ │
│ │ │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 비유: │
│ ├── FastAPI = 요리사 (요청을 처리하는 로직) │
│ └── Uvicorn = 식당 입구 (요청을 받아서 요리사에게 전달) │
│ │
└─────────────────────────────────────────────────────────────┘
2. WSGI vs ASGI 역사 (배경)
┌─────────────────────────────────────────────────────────────┐
│ │
│ 2003년: WSGI (Web Server Gateway Interface) 탄생 │
│ ├── PEP 333 (Python 표준) │
│ ├── 동기(Synchronous) 방식 │
│ ├── 요청 하나 = 스레드 하나 │
│ └── 구현체: Gunicorn, uWSGI │
│ │
│ WSGI의 한계: │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ def wsgi_app(environ, start_response): │ │
│ │ # 동기적으로만 실행 가능 │ │
│ │ # WebSocket? ❌ 불가능 │ │
│ │ # async/await? ❌ 불가능 │ │
│ │ # HTTP/2? ❌ 제한적 │ │
│ │ return [b"Hello World"] │ │
│ │ │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ ───────────────────────────────────────────────────────── │
│ │
│ 2016년: ASGI (Asynchronous Server Gateway Interface) 탄생 │
│ ├── Django Channels 프로젝트에서 시작 │
│ ├── 비동기(Asynchronous) 방식 │
│ ├── WebSocket, HTTP/2 지원 │
│ └── async/await 네이티브 지원 │
│ │
│ ASGI의 장점: │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ async def asgi_app(scope, receive, send): │ │
│ │ # 비동기적으로 실행 가능 │ │
│ │ # WebSocket? ✓ 가능 │ │
│ │ # async/await? ✓ 네이티브 │ │
│ │ # HTTP/2? ✓ 가능 │ │
│ │ await send({"type": "http.response.body", ...})│ │
│ │ │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 2017년: Uvicorn 등장 │
│ ├── 최초의 순수 Python ASGI 서버 │
│ ├── uvloop 기반 (libuv 바인딩) │
│ └── FastAPI, Starlette와 함께 성장 │
│ │
└─────────────────────────────────────────────────────────────┘
3. 왜 Uvicorn인가?
┌─────────────────────────────────────────────────────────────┐
│ │
│ ASGI 서버 비교: │
│ │
│ ┌────────────┬─────────────────────────────────────────┐ │
│ │ 서버 │ 특징 │ │
│ ├────────────┼─────────────────────────────────────────┤ │
│ │ Uvicorn │ 가볍고 빠름, 개발용 기본 선택 │ │
│ │ │ uvloop 사용 시 매우 빠름 │ │
│ ├────────────┼─────────────────────────────────────────┤ │
│ │ Hypercorn │ HTTP/2, HTTP/3(QUIC) 지원 │ │
│ │ │ 더 많은 프로토콜 지원 │ │
│ ├────────────┼─────────────────────────────────────────┤ │
│ │ Daphne │ Django Channels 공식 서버 │ │
│ │ │ Django 프로젝트에서 주로 사용 │ │
│ └────────────┴─────────────────────────────────────────┘ │
│ │
│ Uvicorn이 인기 있는 이유: │
│ ├── FastAPI 공식 권장 서버 │
│ ├── 설정이 간단 │
│ ├── 성능이 뛰어남 (uvloop 사용 시) │
│ └── 활발한 개발/유지보수 │
│ │
└─────────────────────────────────────────────────────────────┘
4. 기본 사용법
# main.py
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def root():
return {"message": "Hello World"}
# 실행 방법 1: CLI
# uvicorn main:app --reload
# 실행 방법 2: 코드에서 직접
if __name__ == "__main__":
import uvicorn
uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True)
# CLI 옵션들
uvicorn main:app \
--host 0.0.0.0 \ # 바인딩 주소 (기본: 127.0.0.1)
--port 8000 \ # 포트 (기본: 8000)
--reload \ # 코드 변경 시 자동 재시작 (개발용)
--workers 4 \ # 워커 프로세스 수 (프로덕션)
--loop uvloop \ # 이벤트 루프 (uvloop이 더 빠름)
--http httptools \ # HTTP 파서 (httptools이 더 빠름)
--log-level info # 로그 레벨
5. 아키텍처
┌─────────────────────────────────────────────────────────────┐
│ │
│ Uvicorn 아키텍처 │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Internet │ │
│ │ │ │ │
│ │ ▼ │ │
│ │ ┌─────────────────────────────────────────────┐ │ │
│ │ │ Uvicorn Server │ │ │
│ │ │ │ │ │
│ │ │ ┌─────────────────────────────────────┐ │ │ │
│ │ │ │ Event Loop (uvloop) │ │ │ │
│ │ │ │ │ │ │ │
│ │ │ │ ┌───────────┐ ┌───────────┐ │ │ │ │
│ │ │ │ │ HTTP │ │ WebSocket │ │ │ │ │
│ │ │ │ │ Protocol │ │ Protocol │ │ │ │ │
│ │ │ │ └─────┬─────┘ └─────┬─────┘ │ │ │ │
│ │ │ │ │ │ │ │ │ │
│ │ │ │ └──────┬───────┘ │ │ │ │
│ │ │ │ │ │ │ │ │
│ │ │ │ ▼ │ │ │ │
│ │ │ │ ┌─────────────────────────────┐ │ │ │ │
│ │ │ │ │ ASGI Interface │ │ │ │ │
│ │ │ │ │ scope, receive, send │ │ │ │ │
│ │ │ │ └──────────────┬──────────────┘ │ │ │ │
│ │ │ │ │ │ │ │ │
│ │ │ └─────────────────┼──────────────────┘ │ │ │
│ │ │ │ │ │ │
│ │ └────────────────────┼──────────────────────┘ │ │
│ │ │ │ │
│ │ ▼ │ │
│ │ ┌─────────────────────────────────────────────┐ │ │
│ │ │ ASGI Application │ │ │
│ │ │ (FastAPI, Starlette, Django Channels) │ │ │
│ │ └─────────────────────────────────────────────┘ │ │
│ │ │ │
│ └────────────────────────────────────────────────────┘ │
│ │
│ 핵심 컴포넌트: │
│ ├── uvloop: libuv 기반 초고속 이벤트 루프 │
│ ├── httptools: 초고속 HTTP 파서 (Node.js에서 사용) │
│ └── ASGI Interface: 앱과 서버 간의 표준 인터페이스 │
│ │
└─────────────────────────────────────────────────────────────┘
6. uvloop과 httptools
┌─────────────────────────────────────────────────────────────┐
│ │
│ uvloop (선택적, 권장): │
│ │
│ - libuv 기반 이벤트 루프 (Node.js가 사용하는 것) │
│ - 기본 asyncio 대비 2~4배 빠름 │
│ - Cython으로 작성되어 C 수준 성능 │
│ │
│ 설치: pip install uvloop │
│ 사용: uvicorn main:app --loop uvloop │
│ │
│ ───────────────────────────────────────────────────────── │
│ │
│ httptools (선택적, 권장): │
│ │
│ - Node.js의 HTTP 파서를 Python으로 포팅 │
│ - 기본 파서 대비 훨씬 빠름 │
│ - Cython 기반 │
│ │
│ 설치: pip install httptools │
│ 사용: uvicorn main:app --http httptools │
│ │
│ ───────────────────────────────────────────────────────── │
│ │
│ 권장 설치 (둘 다 포함): │
│ │
│ pip install uvicorn[standard] │
│ │
│ 포함되는 것: │
│ ├── uvloop (Linux/macOS) │
│ ├── httptools │
│ ├── watchfiles (--reload용) │
│ └── websockets (WebSocket용) │
│ │
└─────────────────────────────────────────────────────────────┘
7. 개발 vs 프로덕션 설정
┌─────────────────────────────────────────────────────────────┐
│ │
│ 개발 환경: │
│ │
│ uvicorn main:app --reload │
│ │
│ ├── --reload: 코드 변경 감지 및 자동 재시작 │
│ ├── 단일 워커 (디버깅 용이) │
│ └── localhost만 바인딩 (보안) │
│ │
│ ───────────────────────────────────────────────────────── │
│ │
│ 프로덕션 환경 (방법 1: Uvicorn 직접): │
│ │
│ uvicorn main:app \ │
│ --host 0.0.0.0 \ │
│ --port 8000 \ │
│ --workers 4 \ │
│ --loop uvloop \ │
│ --http httptools │
│ │
│ ⚠️ --workers 사용 시 --reload 사용 불가 │
│ │
│ ───────────────────────────────────────────────────────── │
│ │
│ 프로덕션 환경 (방법 2: Gunicorn + Uvicorn Workers): │
│ │
│ gunicorn main:app \ │
│ -w 4 \ │
│ -k uvicorn.workers.UvicornWorker \ │
│ --bind 0.0.0.0:8000 │
│ │
│ 장점: │
│ ├── Gunicorn의 프로세스 관리 기능 활용 │
│ ├── 워커 재시작, 그레이스풀 셧다운 │
│ └── 프로덕션 검증된 프로세스 매니저 │
│ │
└─────────────────────────────────────────────────────────────┘
8. Worker 개수 설정
┌─────────────────────────────────────────────────────────────┐
│ │
│ 워커 수 계산 공식: │
│ │
│ workers = (CPU 코어 수 × 2) + 1 │
│ │
│ 예시: │
│ ├── 4코어 서버: (4 × 2) + 1 = 9 워커 │
│ ├── 8코어 서버: (8 × 2) + 1 = 17 워커 │
│ └── 하지만 보통 4~8개로 시작하고 조정 │
│ │
│ ───────────────────────────────────────────────────────── │
│ │
│ 고려 사항: │
│ │
│ I/O 바운드 작업 (DB, API 호출 등): │
│ └── 워커 수 늘려도 효과 좋음 │
│ │
│ CPU 바운드 작업 (계산, 이미지 처리 등): │
│ └── 코어 수 = 워커 수가 적절 │
│ │
│ 메모리 제한: │
│ └── 워커당 ~100MB+ 사용, 총 메모리 고려 │
│ │
│ ⚠️ 비동기 앱에서는 워커가 적어도 동시 처리 많음 │
│ └── async/await가 I/O 대기 중 다른 요청 처리 │
│ │
└─────────────────────────────────────────────────────────────┘
9. Nginx와 함께 사용 (프로덕션)
┌─────────────────────────────────────────────────────────────┐
│ │
│ 일반적인 프로덕션 아키텍처: │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────────────┐ │
│ │ Client │────►│ Nginx │────►│ Uvicorn/Gunicorn│ │
│ │ │ │ (Reverse │ │ + FastAPI │ │
│ │ │ │ Proxy) │ │ │ │
│ └──────────┘ └──────────┘ └──────────────────┘ │
│ │
│ Nginx 역할: │
│ ├── SSL/TLS 종료 (HTTPS 처리) │
│ ├── 정적 파일 서빙 │
│ ├── 로드 밸런싱 │
│ ├── 요청 버퍼링 │
│ └── DDoS 방어 │
│ │
└─────────────────────────────────────────────────────────────┘
Nginx 설정 예시
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# WebSocket 지원
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
# 정적 파일 (Nginx가 직접 서빙)
location /static {
alias /app/static;
}
}
10. Docker에서 사용
# Dockerfile
FROM python:3.12-slim
WORKDIR /app
# 의존성 설치
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# 소스 복사
COPY . .
# uvicorn[standard] 설치 (uvloop, httptools 포함)
RUN pip install uvicorn[standard]
# 포트 노출
EXPOSE 8000
# 프로덕션 실행
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000", "--workers", "4"]
# docker-compose.yml
version: '3.8'
services:
web:
build: .
ports:
- "8000:8000"
environment:
- DATABASE_URL=postgresql://user:pass@db/mydb
depends_on:
- db
# Gunicorn + Uvicorn Worker 사용 시
command: >
gunicorn main:app
-w 4
-k uvicorn.workers.UvicornWorker
--bind 0.0.0.0:8000
db:
image: postgres:15
environment:
- POSTGRES_USER=user
- POSTGRES_PASSWORD=pass
- POSTGRES_DB=mydb
11. 성능 비교
┌─────────────────────────────────────────────────────────────┐
│ │
│ 벤치마크 (요청/초, 단순 JSON 응답): │
│ │
│ ┌─────────────────────────┬───────────────────────────┐ │
│ │ 서버 구성 │ 요청/초 (RPS) │ │
│ ├─────────────────────────┼───────────────────────────┤ │
│ │ Uvicorn (기본) │ ~30,000 │ │
│ │ Uvicorn (uvloop) │ ~50,000+ │ │
│ │ Gunicorn + WSGI │ ~10,000 │ │
│ │ Flask (dev server) │ ~1,000 │ │
│ └─────────────────────────┴───────────────────────────┘ │
│ │
│ ⚠️ 실제 성능은 앱 로직, DB, 네트워크 등에 따라 다름 │
│ │
│ Uvicorn이 빠른 이유: │
│ ├── uvloop: C로 작성된 이벤트 루프 │
│ ├── httptools: C로 작성된 HTTP 파서 │
│ ├── 비동기: I/O 대기 중 다른 요청 처리 │
│ └── 경량: 최소한의 오버헤드 │
│ │
└─────────────────────────────────────────────────────────────┘
12. 로깅 설정
import uvicorn
from uvicorn.config import LOGGING_CONFIG
# 기본 로깅 설정 커스터마이징
LOGGING_CONFIG["formatters"]["default"]["fmt"] = \
"%(asctime)s - %(levelname)s - %(message)s"
LOGGING_CONFIG["formatters"]["access"]["fmt"] = \
'%(asctime)s - %(client_addr)s - "%(request_line)s" %(status_code)s'
if __name__ == "__main__":
uvicorn.run(
"main:app",
host="0.0.0.0",
port=8000,
log_level="info",
access_log=True, # 접근 로그 활성화
)
# CLI에서 로그 레벨 설정
uvicorn main:app --log-level debug # debug, info, warning, error, critical
uvicorn main:app --access-log # 접근 로그 활성화
uvicorn main:app --no-access-log # 접근 로그 비활성화
13. SSL/HTTPS 설정
# 개발용 자체 서명 인증서 생성
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes
# Uvicorn에서 HTTPS 사용
uvicorn main:app \
--host 0.0.0.0 \
--port 443 \
--ssl-keyfile key.pem \
--ssl-certfile cert.pem
# 코드에서 SSL 설정
import uvicorn
if __name__ == "__main__":
uvicorn.run(
"main:app",
host="0.0.0.0",
port=443,
ssl_keyfile="key.pem",
ssl_certfile="cert.pem",
)
⚠️ 프로덕션에서는 Nginx에서 SSL 처리를 권장 (Let’s Encrypt 등)
14. 정리
┌─────────────────────────────────────────────────────────────┐
│ │
│ Uvicorn 핵심 요약: │
│ │
│ 1. ASGI 서버 = 비동기 Python 앱을 실행하는 서버 │
│ │
│ 2. FastAPI/Starlette의 공식 권장 서버 │
│ │
│ 3. 성능을 위해 uvicorn[standard] 설치 │
│ └── uvloop + httptools 포함 │
│ │
│ 4. 개발: uvicorn main:app --reload │
│ │
│ 5. 프로덕션: │
│ ├── Uvicorn: --workers N --loop uvloop │
│ └── 또는 Gunicorn + UvicornWorker │
│ │
│ 6. 앞단에 Nginx 두면 더 좋음 │
│ └── SSL, 정적 파일, 로드밸런싱 │
│ │
│ 7. 워커 수: (CPU × 2) + 1 또는 4~8개로 시작 │
│ │
│ ───────────────────────────────────────────────────────── │
│ │
│ 비유: │
│ ├── WSGI (Gunicorn) = 단일 창구 은행 (한 명씩 처리) │
│ └── ASGI (Uvicorn) = 번호표 은행 (대기하며 다른 일 처리) │
│ │
└─────────────────────────────────────────────────────────────┘
관련 키워드
Uvicorn, ASGI, WSGI, uvloop, httptools, Gunicorn, FastAPI, Starlette, Worker, 비동기, 이벤트 루프, Nginx, 리버스 프록시