Daphne는 ASGI 서버, Gunicorn은 기본적으로 WSGI 서버고, 이 차이가 WebSocket 동작 여부를 결정해.
요약
- Gunicorn (WSGI)
→ HTTP 요청/응답(동기, 단발성)만 처리
→ WebSocket 프로토콜 자체를 이해하지 못함 - Daphne (ASGI)
→ HTTP + WebSocket + lifespan 등 지속 연결 프로토콜 처리
→ WebSocket 네이티브 지원
핵심 차이: WSGI vs ASGI
1️⃣ WSGI (Gunicorn의 기본 세계관)
WSGI는 애초에 이렇게 정의돼 있어:
Request → Application → Response → Connection 종료
특징:
- 요청당 하나의 response
- connection을 오래 붙잡고 상태를 유지하는 개념이 없음
- HTTP Upgrade (WebSocket handshake) 이후의 프레임 통신 모델이 없음
그래서:
- WebSocket handshake 이후
send/receive루프를 돌려야 하는데
→ WSGI 인터페이스에는 그 자리가 아예 없음
👉 Gunicorn은 “정상적으로 설계된 WSGI 서버”라서 WebSocket이 안 되는 게 맞음
2️⃣ ASGI (Daphne의 세계관)
ASGI는 처음부터 이렇게 정의됨:
Client ↔ Server ↔ Application
(long-lived connection)
인터페이스 자체가 이벤트 기반이야:
async def application(scope, receive, send):
...
scope: protocol 정보 (http,websocket)receive: 클라이언트 이벤트 수신send: 서버 → 클라이언트 이벤트 전송
WebSocket은 이렇게 들어와:
scope["type"] == "websocket"
그리고 이벤트는:
{"type": "websocket.connect"}
{"type": "websocket.receive"}
{"type": "websocket.disconnect"}
👉 프로토콜 레벨에서 WebSocket이 1급 시민
“근데 Gunicorn도 WebSocket 된다고 들었는데?”
맞아. 하지만 조건부야.
Gunicorn + ASGI Worker
Gunicorn 자체는 그냥 Process Manager야.
여기에 ASGI worker를 붙이면 이야기가 달라져.
대표 조합:
gunicorn -k uvicorn.workers.UvicornWorkergunicorn -k daphne.server.DaphneWorker(거의 안 씀)
이 경우 구조는:
Client
↓
Gunicorn (master/worker 관리)
↓
Uvicorn/Daphne (ASGI server)
↓
ASGI App
👉 WebSocket이 되는 이유는 Gunicorn 때문이 아니라
👉 Uvicorn/Daphne가 ASGI 서버이기 때문
Daphne vs Uvicorn (ASGI 서버 간 차이)
| 항목 | Daphne | Uvicorn |
|---|---|---|
| 출신 | Django Channels | Starlette/FastAPI |
| 이벤트 루프 | Twisted | asyncio / uvloop |
| HTTP 성능 | 보통 | 매우 좋음 |
| WebSocket 안정성 | 매우 성숙 | 성숙 |
| Django 친화성 | ★★★★★ | ★★★ |
| 운영 난이도 | 약간 높음 | 낮음 |
Django + Channels 기준에선:
- 공식 레퍼런스: Daphne
- 실무 트렌드: Uvicorn 점점 증가
왜 “WebSocket이 동작하는 게 다르게 느껴질까?”
운영 관점에서 체감 차이는 여기서 나와:
1️⃣ 연결 유지 모델
- Daphne: connection당 event loop 관리가 명확
- Gunicorn(WSGI): connection 유지 개념 자체 없음 → 바로 끊김
2️⃣ Reverse Proxy 영향
Nginx에서:
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
ASGI 서버는 이걸 이해
WSGI 서버는 무시
그래서:
- Gunicorn만 쓰면 → handshake 이후 바로 종료
- Daphne/Uvicorn → 정상 연결 유지
실무 권장 아키텍처
Django + WebSocket
[Nginx]
↓
[Daphne or Uvicorn]
↓
[Django ASGI + Channels]
Django + HTTP only
[Nginx]
↓
[Gunicorn (WSGI)]
↓
[Django WSGI]
혼합 (요즘 제일 흔함)
HTTP → Gunicorn (WSGI)
WS → Uvicorn/Daphne (ASGI)
또는
전부 ASGI (Uvicorn)
결론
- WebSocket 동작 차이는 구현 문제 ❌
- 프로토콜 철학(WSGI vs ASGI)의 차이 ⭕
- Gunicorn은 WebSocket을 “못하는 게 아니라”
→ 하도록 설계되지 않았음 - Daphne는 WebSocket을 위해 태어남
