nginx에서 한 도메인에 정적/API/WebSocket/서브앱 붙이기
실전 운영에서 많이 쓰는 nginx 라우팅 패턴과 흔한 함정(proxy_pass/alias/try_files)
한 도메인에서 정적 프론트(SSG/SPA) + API + WebSocket + 별도 앱(서브 디렉터리 마운트)을 같이 운영하는 패턴은 매우 흔합니다. 문제는 작은 실수로 404/무한리다이렉트/쿠키 누락/WS 끊김이 자주 발생한다는 점입니다.
1) 체크리스트
/.well-known/acme-challenge/는 SSL 갱신을 위해 예외 처리- 정적 파일은
try_files로 안전하게 서빙 (디렉터리 트래버설 방지) proxy_pass의 슬래시 유무를 의식 (/api/→ 업스트림 경로 결합 규칙)- WebSocket은
Upgrade/Connection헤더 설정 - 백엔드에 원본 정보를 전달:
X-Forwarded-For,X-Forwarded-Proto,Host - 민감 파일 차단:
.env,.git, 백업 파일 등
바로 쓰는 스니펫: nginx: 민감 파일(.env/.git/백업) 차단
2) 익명화된 예시 설정
server {
server_name example.com;
root /var/www/site/dist;
index index.html;
# LetsEncrypt
location /.well-known/acme-challenge/ {
root /var/www/letsencrypt;
}
# 민감 파일 차단 (필수)
include /etc/nginx/snippets/block-sensitive-files.conf;
# 정적 앱 (SPA fallback)
location / {
try_files $uri $uri/ /index.html;
}
# API 프록시
location /api/ {
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://127.0.0.1:3000/;
}
# WebSocket
location /ws/ {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_pass http://127.0.0.1:3001/;
}
# 서브앱 마운트(빌드 산출물 폴더를 붙이는 방식)
location ^~ /docs/ {
alias /var/www/docs/dist/;
try_files $uri $uri/ =404;
}
}
3) 흔한 함정
location /api/에서proxy_pass http://127.0.0.1:3000;처럼 “뒤 슬래시”가 빠지면 업스트림으로 전달되는 경로가 기대와 달라질 수 있습니다.alias는root와 동작 방식이 다릅니다.alias를 쓸 때는try_files경로도 함께 점검합니다.- 프록시 뒤 HTTPS인데 앱이 HTTP로 인식하면, 쿠키의
Secure설정/리다이렉트가 꼬일 수 있습니다. (프레임워크의trust proxy설정 필요)