장고로 개발을 하고나면 runserver로 테스트를 했지만, 직접 배포를 runserver로 하게되면 보안, 안정성, 효율 등 여러 면에서 좋지않다.
- Nginx: 건물 입구에서 손님을 분산시키고 안내하는 리셉션
- Gunicorn: 실제로 음식(웹 페이지)을 만드는 주방 셰프
- 손님(요청)이 많으면 리셉션(Nginx)이 없으면 주방(Gunicorn)이 난리 나요.



이전에 gunicorn을 이용해 서버 가동을 했다면 이제는 웹서버인 Nginx와 연동해 서비스를 꾸려나가볼 것입니다.
우선 Nginx는 트래픽이 많은 웹사이트의 서버(WAS)를 도와주는 고성능 경량 웹 서버입니다.
apache의 단점들을 보완해 나온 것이 Nginx인데, 장점을 이야기해보면 크게 3가지가 있습니다.
7000 명 이상의 동시 접속자 있으면 NGINX를 추천하고 있다.
높은 성능
높은 동시성
낮은 자원 사용
Gunicorn(Green Unicorn)은 Python Web Server Gateway Interface(WSGI) HTTP서버입니다. Python 웹 어플리케이션의 높은 트래픽을 쉽게 처리할 수 있는 가볍고 안정적인 서버입니다.
파이썬 애플리케이션이 웹서버와 통신하기 위한 인터페이스로 웹서버의 요청을 해석을 해서 파이썬애플리케이션에게 전달해줍니다. 대표적으로 gunicorn과 uWSGI가 있습니다.


보통은 WS + CGI + Django
에서 WSGI로 gunicorn이나 uWSGI를 많이 사용하는 것 같은데, gunicorn보다 uWSGI가 효율적인 면에서 좋은 것 같아서 uWSGI를 이용해보려고 한다.
environ 딕셔너리 + start_response 함수
Django는 보통 wsgi.py를 통해 실행되며, 다음과 같은 방식으로 요청 정보를 받음:
def application(environ, start_response):
# environ은 CGI에서 유래된 환경변수 형식의 딕셔너리
...
{
'REQUEST_METHOD': 'GET',
'PATH_INFO': '/home/',
'QUERY_STRING': 'page=2',
'CONTENT_TYPE': 'text/html',
'CONTENT_LENGTH': '123',
'SERVER_NAME': 'localhost',
'SERVER_PORT': '8000',
...
}
✅ 전체 흐름 개요 (소스 기반)
[요청] --> [WSGI 서버 (gunicorn, uwsgi, runserver)]
--> [Django의 wsgi.py의 application(environ, start_response)]
--> [Django의 WSGIHandler 호출]
--> [HttpRequest 객체 생성]
--> [URL 매칭 및 View 실행]
--> [HttpResponse 반환]
--> [start_response로 응답 반환]
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')
application = get_wsgi_application() # 👈 WSGI 인터페이스로 사용할 application 객체
이 application 객체는 WSGI 서버가 요청을 전달하는 WSGI callable입니다.
get_wsgi_application()은 내부적으로 WSGIHandler 인스턴스를 반환합니다.
class WSGIRequest(HttpRequest):
def __init__(self, environ):
self.environ = environ
self.path_info = environ.get('PATH_INFO', '/')
self.method = environ.get('REQUEST_METHOD', 'GET')
environ에서 CGI 스타일의 값들을 추출해 HttpRequest 객체로 래핑
✅ 핵심 요약: 톰캣 vs 유니콘
| 항목 | Apache Tomcat | Gunicorn (Green Unicorn) |
|---|---|---|
| 대상 언어 | Java | Python |
| 실행 대상 | Java Servlet, JSP (Spring 등) | WSGI 기반 Python 앱 (Django, Flask 등) |
| 표준 | Servlet API, Java EE 일부 | WSGI (PEP 3333) |
| 정적 파일 처리 | 가능하지만 비효율적 | 안 함 (보통 Nginx와 연동) |
| 주 사용 환경 | Java 웹 앱 (Spring MVC 등) | Python 웹 앱 (Django, Flask 등) |
| 예시 실행 | tomcat/bin/startup.sh | gunicorn myapp.wsgi:application |
| 멀티 프로세스/스레드 | Java 기반 처리 (스레드 중심) | Python 기반 처리 (워크 프로세스 방식) |
Nginx는 프록시(reverse proxy) 역할로,
정적 파일 처리, 보안, 성능, 부하 분산 등을 담당하고
Gunicorn은 오직 Python 애플리케이션 실행에 집중
Gunicorn은 요청을 받아 처리할 수는 있지만,
정적 파일 처리 없음
연결 제한
오류 처리 미흡
프로덕션에서는 프록시 없이 쓰지 말 것이 권장사항
Nginx는 비동기 이벤트 기반 → 수천 개의 연결을 효율적으로 처리
Gunicorn은 워커 수에 따라 병렬 처리 한계가 있음
[클라이언트 요청]
↓
[Nginx] ← 정적 파일, SSL, 압축, 보안
↓
[Gunicorn] ← Django/Flask WSGI 앱 실행
↓
[애플리케이션 응답]