- 웹사이트로 들어오는 요청을 잘 정리해서, 빠르게 처리해주는 "문지기" 역할을 하는 프로그램
- 웹사이트에 사용자가 많이 들어오면, 요청이 몰려서 서버가 버벅
거릴 수 있는데, 이때 Nginx가 이 처리를 도와줘서 속도도 빠르게 하고, 안정성도 높여준다.
- 정적 파일 제공
- 이미지, HTML, CSS 같은 고정된 파일을 직접 빠르게 전송함.
-> 백엔드 서버까지 가지 않고 여기서 바로 처리- 요청 분산 (로드 밸런싱)
- 사람이 몰릴 때, 여러 서버로 요청을 나눠줌.
-> "너는 서버 A", "넌 서버 B"처럼 분산 시켜서 부하를 줄여줌.- 역방향 프록시 (Reverse Proxy)
- 클라이언트 요청을 대신 받아서 백엔드 서버로 전달하고, 응답을 받아서
다시 돌려줌.
-> 서버가 직접 외부와 통신 안해도 됨.
( Gunicorn은 직접 브라우저와 소통하기엔 한계가 있음 (정적 파일, SSL처리, 보안 등)
그래서 Nginx가 요청을 대신 받고, Gunicorn에게 전달한다. )- 보안
- SSL(https) 설정도 가능하고, 악성 접근을 필터링할 수도 있음.
비유를 들자면 레스토랑에 손님이 들어와서 주문을 하면 웨이터(Nginx)가 손님의
주문을 받아서 주방(서버)으로 전달하고, 요리가 나오면 다시 손님에게 가져다주는 역할이다.
손님이 많으면, 웨이터(Nginx)가 알아서 분산해서 처리하는 것이다.
위 파일로 전체 구조를 설명하면server블록 하나로 구성 되어있고, 4가지의 목적을 가지고 있다.
1. 도메인 이름 설정 (handsomepotato.p-e.kr)
2. 정적 파일 서빙 (static, media)
3. API 요청을 백엔드 서버로 전달 (proxy)
4. SPA (Single Page Application) fallback 처리1. 도메인 이름 설정 (상세 설명)
server { listen 443 ssl; server_name handsomepotato.p-e.kr;
- 443 포트 : HTTPS 통신을 위한 포트
- ssl : 이 설정은 SSL 인증서를 사용할 거라는 뜻
- server_name : 이 설정에 맞는 도메인으로 요청이 들어왔을 때 이 블록이 실행됨.
-> 즉,https://handsomepotato.p-e.kr으로 들어오면 이 설정이 적용됨.2. 정적 파일 서빙 (정적 파일 처리)
location /static/ { alias /home/ubuntu/TeamProject_BE/static/; } location /media/ { alias /home/ubuntu/TeamProject_BE/media/; }
- /static/ -> 정적 파일 (css, js등)을 Nginx가 직접 제공
- /media/ -> 사용자 업로드 이미지 같은 미디어 파일 제공
- alias 는 해당 경로로 직접 연결해줘서, Django까지 안 가고 Nginx가 빠르게 처리해줌.
3. API 요청을 백엔드 서버로 전달 (API 요청 + CORS 헤더 처리)
location /api/ { proxy_pass http://unix:/srv/gunicorn/gunicorn.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; }
- /api/ 로 시작하는 요청은 Django 백엔드(Gunicorn) 로 전달됨.
- proxy_pass : Gunicorn 소켓에 요청 전달
-> 🔌 그럼 gunicorn.sock은?
Gunicorn이 열어놓은 Unix 소켓 파일
마치 "문" 하나를 열어두고 Nginx가 거기로 요청을 전달하는 느낌
proxy_pass http://unix:/srv/gunicorn/gunicorn.sock;
이건 "Nginx야, 이 요청을 Gunicorn 소켓을 통해 Django에 전달해줘!" 라는 의미
참고: http://127.0.0.1:8000처럼 포트로도 통신할 수 있지만, unix socket 방식이 더 빠르고 보안성도 좋음.✅ 정리와 비유
Gunicorn 소켓은 "Gunicorn이라는 백엔드 서버가 Nginx와 통신하기 위해 여는 통로"이고, Nginx는 이 통로를 통해 요청을 전달하는 역할을 한다.
📦 Gunicorn: 진짜 주방장 (Django 앱 실행)
🔌 Gunicorn 소켓: 주방으로 연결된 "전화선" 혹은 "주문서 제출함"
🚪 Nginx: 웨이터 (브라우저 요청 받음)
🥡 브라우저 요청: 손님의 주문
🧾 proxy_pass: "주문서를 제출함에 넣기"
- proxy_set_header : 원래 클라이언트 정보를 백엔드로 넘김.
-> $host : 원래 요청한 도메인
-> $remote_addr : 진짜 클라이언트 IP
-> $proxy_add_x_forwarded_for : 프록시 거친 IP들
-> $scheme : http인지 https인지
✅ 이 설정은 역방향 프록시 (Reverse Proxy)의 전형적인 구성이고, CORS 처리 시
요청 정보가 정확히 전달되도록 함.4. SPA fallback 처리
location / { include proxy_params; proxy_pass http://unix:/srv/gunicorn/gunicorn.sock; }
- 이건 Vue/React 같은 SPA(Single Page Application) 용
- /api/, /static/, /media/ 가 아닌 모든 요청은 여기로 들어옴.
- 프론트엔드 라우팅에서 주소가 /detail/1 처럼 되어 있어도 제대로 작동하게 만들어 줌.
- 역시 Gunicorn에 전달됨.
📦 여기서 SPA란?
SPA는 페이지 전체를 새로고침하지 않고, 필요한 부분만 JS로 바꿔서 보여주는 방식
주소가 바뀌어도 서버에 실제로 다른 페이지를 요청하지 않고 JS 라우터가 내부에서
페이지를 바꿔줌.🔥 그런데 문제는?
예를 들어 https://handsomepotato.p-e.kr/detail/1로 직접 들어가면
브라우저는 서버(Nginx)에게 "detail/1 페이지를 줘!" 라고 요청함.
→ 그런데 그 주소에 해당하는 실제 정적 HTML 파일은 없음
→ 그래서 404 Not Found가 뜨게 돼.
✅ 해결 방법location / { include proxy_params; proxy_pass http://unix:/srv/gunicorn/gunicorn.sock; }/static, /media, /api가 아닌 나머지 모든 경로는 Django에 넘겨줌.
혹은 Vue/React에서는 보통 index.html 하나만 있으면 되니까
그걸 항상 기본으로 서빙하게 해주는 구조로 바꿔줄 수 있음.
덧붙이자면 Vue/React는 URL을 프론트에서 처리하지만, 브라우저 주소창에 직접 치면 그걸 서버가 처리하는 줄 알고 요청하니까
그걸 서버(Nginx)에서 "얘는 프론트엔드 라우팅이야!"라고 인식해서 기본 파일을 주는 거지
📌 요약 : /detail/1처럼 라우터에서만 인식되는 경로도 정상 동작하게 만들어주는 장치
브라우저에서 https://handsomepotato.p-e.kr 로 접속하면
Nginx는 server_name handsomepotato.p-e.kr; 설정을 보고
해당 server 블록을 사용하게 됨.
그리고 그 안의 location 블록들이 요청 URL 경로에 따라 작동함.
예를 들어:
/static/style.css → 정적 파일 서빙
/api/post/3 → Gunicorn으로 전달
/ 또는 /detail/1 → SPA fallback 처리
| 역할 | 설명 |
|---|---|
| HTTPS 설정 | listen 443 ssl, server_name 사용 |
| 정적 파일 제공 | /static/, /media/ 경로에서 Nginx가 직접 서빙 |
| API 요청 프록시 | /api/ 경로는 Gunicorn에 전달 + 헤더 세팅 |
| SPA 처리 | 나머지 요청은 Gunicorn에 넘겨서 프론트 라우팅 대응 |