notes
nginx
nginx 기본 구조·리버스 프록시 설정과 운영 시 주의점 메모.
서버에 앱을 올려 두면 보통 Node는 3000·13002처럼 내부 포트에서만 듣고, 바깥에는 80/443만 열어 둔다. 그때 앞에서 받아 넘겨 주는 게 nginx다. 여기엔 내가 실제로 쓰는 리버스 프록시 패턴만 모아 둔다.
- 바깥엔 80/443만 열고, 앱은 내부 포트에서 nginx가
proxy_pass로 받아 넘긴다. - 설정은
http→server→location으로 좁아지고, location은 가장 긴 prefix가 이긴다. - 바꾼 설정은 항상
nginx -t && nginx -s reload로 반영한다.
nginx가 하는 일
nginx(“engine x”)는 HTTP 웹 서버이면서 리버스 프록시·캐시·로드밸런서·TCP/UDP 프록시도 한다. Igor Sysoev가 만들었고 BSD 계열 라이선스. 동시 접속을 이벤트 기반으로 나눠서 메모리 적게 쓰는 쪽으로 유명하다.
내가 실무에서 쓰는 역할은 거의 이거다.
- 바깥 80/443 받기
- 안쪽 앱(Next standalone, Nest, Docker 컨테이너 포트)으로
proxy_pass - 정적 파일·이미지 일부는 nginx가 직접 서빙
- SSL 종료(인증서는 certbot 등)
앱이 몇 개든 바깥에서 보이는 건 nginx 하나다. 도메인이나 경로로 갈라서 각 포트로 보내면 된다.
프로세스 구조
마스터 프로세스 하나 + 워커 여러 개. 마스터가 설정을 읽고 워커를 관리하고, 실제 요청은 워커가 처리한다. worker_processes는 CPU 코어에 맞추거나 auto로 둔다.
설정은 보통 /etc/nginx/nginx.conf. Debian/Ubuntu면 sites-available / sites-enabled로 가상 호스트를 나눈다.
# 설정 문법 검사
sudo nginx -t
# 반영 (끊김 없이 워커 교체)
sudo nginx -s reload
# 또는
sudo systemctl reload nginx
reload는 새 워커를 띄운 뒤 옛 워커가 진행 중인 요청만 마무리하고 죽는다. 문법 틀리면 롤백한다. 그래서 배포 스크립트에 nginx -t && nginx -s reload를 넣는 습관을 들였다.
설정 뼈대
지시어는 ;로 끝나는 단순형과 { } 블록(컨텍스트)이 있다. http → server → location 순으로 좁아진다.
http {
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://127.0.0.1:3000;
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;
}
location /images/ {
root /var/www;
}
}
}
location은 가장 긴 prefix가 이기고, ~ 정규식은 그다음에 본다. =는 정확히 일치할 때만, ^~는 prefix가 맞으면 정규식 검사를 건너뛴다. 이미지 확장자만 로컬에서 주고 나머지는 앱으로 넘기는 패턴도 자주 쓴다.
location / {
proxy_pass http://127.0.0.1:3000/;
}
location ~ \.(gif|jpg|png)$ {
root /data/images;
}
Docker랑 같이 쓸 때
컨테이너 앱을 13002:3000처럼 올려 두고 nginx는 호스트(또는 nginx 컨테이너)에서 proxy_pass http://127.0.0.1:13002로 붙인다. Cloud V L7 LB 뒤에 둘 때도 LB → nginx(또는 바로 앱 포트) 포트만 맞추면 된다.
같은 머신에 도메인이 여러 개면 server_name으로 server 블록을 나눈다. 예전에 nginx - domain cross setting 쪽에 적어 둔 것과 같은 결.
HTTPS는 certbot으로 인증서를 받고 443 블록을 하나 더 두는 식으로 붙인다. 80은 443으로 돌려보내기만 한다.
sudo certbot --nginx -d example.comserver {
listen 80;
server_name example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:13002;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
# 웹소켓 쓸 때
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}자주 걸린 실수
proxy_set_header빼먹음 — 앱이 Host/프로토콜을 잘못 읽어 리다이렉트 루프나 쿠키 도메인 꼬임.nginx -t없이 reload — 문법 깨진 채 재시작하다가 죽는 경우.- sites-enabled 심볼릭 링크 안 함 —
sites-available만 고치고 enabled에ln -s를 안 해서 반영이 안 됨. - 앱 포트만 방화벽에 열어둠 — 바깥에는 80/443만, 앱 포트는
127.0.0.1에서만 듣게 두는 게 안전하다.
로그는 보통 /var/log/nginx/access.log, error.log. 502면 일단 업스트림(앱)이 살아 있는지, 포트·방화벽부터 본다.