* Django의 기본 서버가 아닌 웹서버 연동 : NGINX + Django
🕸 웹 브라우저 요청과 웹 서버/애플리케이션 서버 구조 정리
(Django / Flask / FastAPI 배포 이해 문서)
1. 웹 브라우저의 요청 형태는 크게 두 가지로 나뉜다
: 웹 브라우저가 웹서버에 정보를 요청하는 페이지 형태는 크게 두 가지로 나뉜다. 이 때 웹 서버(NGINX, Apache)는 웹 브라우저의 정적 요청과 동적 요청을 처리(또는 전달)하는 서버이다.
- 정적 페이지 요청 (Static Request) : 웹 브라우저로 js, css, image file 과 같은 파일 자체를 요청하는 것.
특징: 웹 서버가 파일을 그대로 응답(서빙)한다. 빠르고 단순하며, 웹 서버가 가장 잘 처리한다.
- 동적 페이지 요청 (Dynamic Request)
요청 시점, 사용자, 파라미터, DB 결과에 따라 응답이 달라질 수 있는 요청.
주의(중요): /index.html 처럼 확장자가 html이라고 해서 동적/정적이 결정되지는 않는다.
- index.html도 그냥 파일이면 “정적”
- 같은 URL이라도 서버에서 템플릿 렌더링/DB 조회로 만들면 “동적”
즉, 동적/정적의 기준은 “응답이 파일 그대로냐 vs 애플리케이션 실행 결과냐” 이다.
2. 동적 페이지 요청은 왜 더 복잡한가?
: 동적 페이지 요청이 들어오면 웹 서버는 요청 처리를 위한 애플리케이션으로 파이썬 프로그램을 호출해야 한다. 예를 들어 검색 요청이 있는 경우 검색 내용을 조회하여 반환하는 파이썬 로직(ORM/SQL, 템플릿 렌더링, 인증/세션 처리 등)을 수행해야 한다.
그런데 NGINX/Apache 같은 웹 서버는 파이썬 코드를 직접 실행하는 역할이 아니다. 그래서 웹 서버가 “파이썬 앱 실행 담당 서버(앱 서버)”에게 요청을 넘겨주는 구조가 필요하다.
3. WSGI / ASGI: 웹 서버와 파이썬 앱을 연결하는 표준
: 여기서 등장하는 것이 “파이썬 앱을 실행하는 서버 + 표준 인터페이스”이다.
1) WSGI (Web Server Gateway Interface)
- 전통적인 파이썬 웹 표준 인터페이스
- 주로 동기 방식 기반
- WSGI 애플리케이션: Django, Flask
- WSGI 서버(앱 실행기): Gunicorn, uWSGI
정리: “웹 서버(NGINX/Apache)가 WSGI 서버를 통해 Django/Flask를 호출한다.”
2) ASGI (Asynchronous Server Gateway Interface)
- 비동기까지 포함한 현대 표준 인터페이스
- FastAPI(대표), Starlette 같은 비동기 프레임워크에 적합
- ASGI 서버: Uvicorn, Hypercorn
- (실무에서) Gunicorn + UvicornWorker 조합도 많이 씀
정리: “FastAPI는 WSGI가 아니라 ASGI로 실행하는 게 표준적이다.”
4. 대표적인 운영(실서비스) 배포 구조
- 웹 서버(NGINX/Apache)는 앞단에서 정적 파일 처리 + 프록시(Reverse Proxy),
- 앱 서버(Gunicorn/Uvicorn)는 파이썬 앱 실행
A) Django 실서비스 구조(표준) : NGINX + Gunicorn + Django
Browser → NGINX(정적 + Reverse Proxy) → Gunicorn(WSGI) → Django
B) Apache + Django : Apache가 mod_wsgi로 Django를 붙이거나, Apache를 Reverse Proxy로 두고 Gunicorn으로 넘길 수도 있음(구성 선택)
참고: Apache + Django: https://opentutorials.org/module/3923/25079
5. 샘플/참고 자료
😎 샘플 프로젝트 구경하기
[AWS] 웹 어플리케이션 배포하기 (EC2) : https://cherishvert.tistory.com/107
Django + NginX 후 AWS로 서비스 : https://wikidocs.net/75558
우분투와 NGINX Reverse Proxy : https://velog.io/@gudcks0305/우분투에서-Nginx로-Reverse-Proxy-설정하기
🕸 프레임워크별 적용 방법 (Django → Flask → FastAPI) ---
아래는 “운영 배포” 기준으로, 가장 흔한 정답 구조만 뽑아서 정리함. (세부 설정 파일은 별도 문서로 확장하면 됨)
1) Django 적용 (WSGI)
구조 : NGINX → Gunicorn(WSGI) → Django
적용 흐름(핵심 단계)
- Django 앱 준비 (ALLOWED_HOSTS, DEBUG=False, DB/ENV 설정)
- 정적 파일 수집: collectstatic
- Gunicorn으로 Django 실행(서비스화 권장: systemd)
- NGINX가 /static/은 파일로 직접 서빙. 나머지는 Gunicorn으로 프록시
2) Flask 적용 (WSGI)
구조 : NGINX → Gunicorn(WSGI) → Flask
적용 흐름(핵심 단계)
- Flask 앱 준비 (app 객체, 환경변수, SECRET_KEY 등)
- Gunicorn으로 app:app 형태로 실행(서비스화)
- NGINX가 정적 파일 경로는 직접 서빙(선택). API/동적 요청은 Gunicorn으로 프록시
3) FastAPI 적용 (ASGI)
구조 : NGINX → Uvicorn(ASGI) → FastAPI (또는 NGINX → Gunicorn(UvicornWorker) → FastAPI)
적용 흐름(핵심 단계)
- FastAPI 앱 준비 (app = FastAPI())
- Uvicorn(또는 Gunicorn+UvicornWorker)로 실행(서비스화)
- NGINX가 정적은 직접 서빙(필요 시). API 요청은 Uvicorn으로 프록시
- FastAPI는 비동기/고성능에 강점이 있어 API 서버에 특히 적합
정리하면
- Django/Flask는 WSGI → Gunicorn
- FastAPI는 ASGI → Uvicorn(또는 Gunicorn+UvicornWorker)
- NGINX/Apache는 앞단에서 정적 처리 + Reverse Proxy
🕸 NGINX 설정 예시 3종(Django/Flask/FastAPI)
(모두 80 포트, Reverse Proxy, 정적 파일 분리 기준)
* 공통 전제
- 설정 파일 위치(우분투 기준)
/etc/nginx/sites-available/<서비스명>
/etc/nginx/sites-enabled/에 심볼릭 링크
- 기본 헤더(프록시 공통)
Host, X-Real-IP, X-Forwarded-For, X-Forwarded-Proto
1) Django: NGINX → Gunicorn(WSGI) → Django ~~~~~~~~~~~~~~~~~
(A) NGINX 설정 템플릿
server {
listen 80;
server_name example.com; # 또는 EC2 퍼블릭IP
# 정적 파일(collectstatic 결과)
location /static/ {
alias /var/www/django_static/; # <-- STATIC_ROOT
expires 30d;
add_header Cache-Control "public";
}
# 업로드 미디어 파일(선택)
location /media/ {
alias /var/www/django_media/; # <-- MEDIA_ROOT
expires 30d;
add_header Cache-Control "public";
}
# 동적 요청은 Gunicorn으로
location / {
proxy_pass http://unix:/run/gunicorn_django.sock;
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;
}
}
(B) Gunicorn은 보통 유닉스 소켓으로 실행
소켓 예: /run/gunicorn_django.sock (systemd에서 생성/관리)
2) Flask: NGINX → Gunicorn(WSGI) → Flask ~~~~~~~~~~~~~~~~~~~~
(A) NGINX 설정 템플릿
server {
listen 80;
server_name example.com;
# Flask 정적(선택: 직접 서빙할 때)
location /static/ {
alias /var/www/flask_static/;
expires 30d;
add_header Cache-Control "public";
}
location / {
proxy_pass http://unix:/run/gunicorn_flask.sock;
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;
}
}
3) FastAPI: NGINX → Uvicorn(ASGI) → FastAPI ~~~~~~~~~~~~~~~~~~~~~~~~~~
: FastAPI는 웹소켓/스트리밍이 흔해서, 프록시 설정에 그 옵션을 같이 넣는 게 안전하다.
(A) NGINX 설정 템플릿(권장)
server {
listen 80;
server_name example.com;
# 정적 파일(필요할 때만)
location /static/ {
alias /var/www/fastapi_static/;
expires 30d;
add_header Cache-Control "public";
}
location / {
proxy_pass http://127.0.0.1:8000; # uvicorn이 여기에 떠있다고 가정
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/Streaming 대비(권장)
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 300;
}
}
유닉스 소켓으로 받고 싶으면 proxy_pass http://unix:/run/uvicorn_fastapi.sock; 형태도 가능.
4) 적용(공통 명령)
sudo ln -s /etc/nginx/sites-available/<서비스명> /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx