nginx.conf 는 http 블록 안에서 include conf.d/*.conf; 로 개별 설정 파일을 불러옵니다. 서비스마다 파일을 나누면 배포·롤백 단위가 명확해집니다.
이 레슨에서는 conf.d/app.conf 하나에 upstream 과 server 블록을 함께 둡니다. 서비스가 여러 개면 파일도 여러 개로 나눕니다.
upstream 은 백엔드 서버 목록에 이름을 붙입니다. keepalive N 을 주면 nginx 와 백엔드 사이 연결을 재사용해 매 요청마다 TCP 를 새로 맺지 않습니다.
| 지시어 | 의미 |
|---|---|
server host:port |
백엔드 주소 |
backup |
평소엔 안 쓰고 장애 시에만 사용 |
keepalive N |
유지할 연결 수 |
같은 요청에 여러 location 이 겹칠 수 있어 nginx 는 정해진 순서로 하나를 고릅니다. 순서를 모르면 정적 파일 요청이 프록시로 새거나 그 반대가 됩니다.
| 우선순위 | 문법 | 동작 |
|---|---|---|
| 1 | location = /path |
정확히 일치하면 즉시 종료 |
| 2 | location ^~ /path/ |
접두사 일치 중 최長, 찾으면 정규식 생략 |
| 3 | location ~ /re/, ~* |
정규식, 파일에 쓴 순서로 첫 일치 |
| 4 | location /path/ |
일반 접두사 중 가장 긴 것 |
^~ 는 "이 접두사면 정규식은 볼 필요 없다"는 뜻이라 정적 파일 경로처럼 확실히 끊고 싶을 때 씁니다.
location 뒤에 슬래시가 있고 proxy_pass 뒤에도 슬래시가 있으면 location 접두사를 떼고 넘깁니다. proxy_pass 에 슬래시가 없으면 요청 경로 전체를 그대로 붙입니다.
요청 /api/orders, location /api/ 기준으로 비교하면 다음과 같습니다.
| proxy_pass | 백엔드가 받는 경로 |
|---|---|
http://app_backend/; |
/orders (접두사 제거) |
http://app_backend; |
/api/orders (접두사 유지) |
백엔드 앱이 /api 컨텍스트로 배포돼 있으면 슬래시를 빼고, 루트로 배포돼 있으면 슬래시를 붙입니다. 이 차이를 놓치면 404 가 나는데 원인을 못 찾는 경우가 많습니다.
기본값인 proxy_pass 만 쓰면 백엔드는 모든 요청이 nginx(127.0.0.1)에서 온 것으로 보입니다. 아래 네 헤더로 원래 정보를 넘깁니다.
| 헤더 | 값 | 용도 |
|---|---|---|
Host |
$host |
백엔드 가상호스트 판단 |
X-Real-IP |
$remote_addr |
실제 클라이언트 IP |
X-Forwarded-For |
$proxy_add_x_forwarded_for |
프록시 경유 IP 체인 |
X-Forwarded-Proto |
$scheme |
원래 http/https 여부 |
proxy_connect_timeout·proxy_send_timeout·proxy_read_timeout 은 각각 연결·요청 전송·응답 대기 한계입니다. 기본값은 모두 60초입니다.
| 지시어 | 기본값 | 의미 |
|---|---|---|
proxy_connect_timeout |
60s | 백엔드 연결까지 대기 |
proxy_send_timeout |
60s | 요청 본문 전송 간격 |
proxy_read_timeout |
60s | 응답 사이 대기 |
연결은 보통 빨리 실패하므로 짧게(5초), 응답은 앱의 가장 긴 요청보다 길게 잡습니다. 엑셀 다운로드처럼 오래 걸리는 경로는 별도 location 으로 빼서 값을 다르게 줍니다.
nginx 는 백엔드 응답을 버퍼에 모았다가 클라이언트로 보냅니다. 버퍼가 작으면 응답이 클 때마다 임시 파일로 흘러넘쳐(proxy_temp_path) 디스크 I/O 가 늘어납니다.
| 지시어 | 예시 | 의미 |
|---|---|---|
proxy_buffer_size |
16k |
헤더용 첫 버퍼 크기 |
proxy_buffers |
8 16k |
개수와 크기 |
기본값은 1m 이라 파일 업로드 API 는 바로 413 을 받습니다. 업로드를 받는 서버 또는 location 에 client_max_body_size 를 앱이 허용하는 최대치보다 조금 크게 둡니다.
너무 크게 잡으면 큰 요청 하나가 워커 메모리·디스크를 오래 붙잡을 수 있어, 앱의 실제 한도에 맞춰 정합니다.
웹소켓은 HTTP 로 시작해 Upgrade 헤더로 프로토콜을 바꿉니다. nginx 가 이 헤더를 백엔드로 넘기지 않으면 연결이 일반 HTTP 로 끊깁니다.
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";이미지·css·js 를 굳이 Tomcat 까지 보낼 이유가 없습니다. location ^~ /static/ 에서 alias(또는 root)로 바로 서빙하고 expires 로 캐시를 지시합니다.
| 지시어 | 예시 | 의미 |
|---|---|---|
alias |
/app/nginx/html/static/ |
요청 경로를 이 경로로 치환 |
root |
/app/nginx/html |
요청 경로를 이 아래에 그대로 붙임 |
expires |
7d |
캐시 유효 기간 헤더 |
alias 는 location 접두사를 떼고 뒤에 붙이고, root 는 접두사를 포함해 그대로 붙인다는 차이를 기억해 둡니다.
수정한 파일은 바로 반영하지 말고 nginx -t 로 문법을 검사한 뒤 systemctl reload nginx 로 적용합니다. reload 는 워커 프로세스만 새로 띄워 기존 연결을 끊지 않습니다.
이 레슨의 스크립트는 실제 nginx 바이너리가 없는 환경에서도 검증할 수 있게 중괄호 짝을 세는 awk 검사를 먼저 실행합니다.
무중단으로 백엔드를 바꿔치기하는 절차(upstream 서버를 하나씩 내리고 reload)는 리눅스 운영 05 를 참조합니다. 이 레슨은 그 전 단계인 프록시 설정 자체에 집중합니다.