proxy_pass 끝의 슬래시 하나 때문에 백엔드가 404를 돌려준 이유
문제 발생
관리자 API를 프록시하는데 백엔드가 계속 404였습니다.
location /api/ {
proxy_pass http://127.0.0.1:3000; # 슬래시 없음
}/api/posts 요청이 백엔드에 /api/posts로 도착했습니다. 백엔드는 /posts를 기대하고 있었습니다. 슬래시를 붙였더니 이번에는 다른 location에서 경로가 뭉개졌습니다.
원인 분석
proxy_pass에 URI가 있느냐 없느냐로 동작이 완전히 갈립니다. nginx 문서가 두 경우를 분명히 나눕니다.
URI가 있으면 치환됩니다 — 지시문에 URI가 지정되면 요청 URI 중 location과 일치한 부분이 지시문에 지정된 URI로 대체됩니다. 문서의 예시대로 location /name/ + proxy_pass http://127.0.0.1/remote/;에서 /name/test는 /remote/test가 됩니다.
URI가 없으면 원본이 그대로 갑니다 — 클라이언트가 보낸 형태 그대로의 요청 URI가 전달됩니다. location /some/path/ + proxy_pass http://127.0.0.1;이 그 경우입니다.
즉 http://127.0.0.1:3000은 "URI 없음"이라 /api/posts가 그대로 가고, http://127.0.0.1:3000/은 "URI 있음(/)"이라 /api/ 부분이 /로 치환되어 /posts가 갑니다. 슬래시 하나가 이 분기를 결정합니다.
문서는 예외도 명시합니다 — location이 정규식으로 지정된 경우와 named location 안에서는 대체할 부분을 결정할 수 없으므로 proxy_pass를 URI 없이 지정해야 합니다.
해결 방안
- 접두사를 떼고 넘기려면 양쪽 다 슬래시로 끝냅니다.
location /api/ {
proxy_pass http://127.0.0.1:3000/; # /api/posts → /posts
}- 경로를 그대로 넘기려면 URI를 붙이지 않습니다.
location /api/ {
proxy_pass http://127.0.0.1:3000; # /api/posts → /api/posts
}-
정규식 location에는 URI를 붙이지 않습니다. 문서가 금지하는 조합이고, 필요하면
rewrite ... break;로 URI를 먼저 바꾼 뒤 넘깁니다 — 이때는 지시문의 URI가 무시되고 변경된 전체 요청 URI가 전달됩니다. -
헤더도 함께 챙깁니다. 경로만 맞추고
Host,X-Forwarded-For,X-Forwarded-Proto를 빠뜨리면 백엔드가 만드는 절대 URL과 클라이언트 IP가 전부 틀어집니다. -
실제로 도착한 경로를 로그로 확인합니다. 추측하지 말고 백엔드 접근 로그를 봅니다 — 이 문제는 설정만 봐서는 양쪽 다 맞아 보입니다.
댓글0
댓글을 남기려면 로그인이 필요해요. 로그인
아직 댓글이 없어요. 첫 의견을 편하게 남겨 보세요.