nginx가 어떤 location을 선택했는지 어떻게 디버깅하나요?
설정과 요청 URI를 이 테스터에 넣으면 이긴 블록과 나머지 블록이 탈락한 이유를 볼 수 있습니다. 실행 중인 서버라면 error_log /var/log/nginx/debug.log debug; 를 추가하고 선택된 location 이름이 담긴 "using configuration" 줄을 찾으세요. 두 방법은 서로 다른 질문에 답합니다. 로그는 살아 있는 서버가 무엇을 했는지 알려주고, 이 페이지는 아직 배포하지 않은 설정이 무엇을 할지 알려줍니다.
nginx location 정규식이 왜 동작하지 않나요?
보통 세 가지 이유 중 하나이며, 판정 표가 어느 쪽인지 짚어 줍니다. 앞선 정규식이 이미 매칭돼서 내 정규식은 실행조차 되지 않았거나 — 정규식은 파일 순서대로 시도되고 첫 매칭이 이깁니다. 아니면 가장 긴 매칭 접두사가 ^~ 를 달고 있어 정규식 단계를 통째로 건너뛰었거나. 아니면 정규식은 멀쩡한데 URI가 생각과 다른 경우입니다. 매칭은 퍼센트 디코딩과 .. 해석을 거치고 쿼리 문자열이 제거된 정규화된 경로를 대상으로 수행됩니다.
정확 일치가 왜 걸리지 않나요?
= location은 URI가 패턴으로 시작하는 게 아니라 전체가 같아야 합니다. location = /a/ 는 /a 와 매칭되지 않고, location = /a 는 /a/b 와 매칭되지 않습니다. 여기서 끝 슬래시는 평범한 문자이므로 두 형태는 서로 다른 문자열입니다. 정확 일치 location이 매칭되면 탐색은 즉시 끝나고 나머지는 비교조차 되지 않습니다.
nginx는 location 블록에서 쿼리 문자열을 매칭하나요?
아니요. 쿼리 문자열은 정규화 과정에서 분리되고 location 선택은 경로만 대상으로 수행됩니다. location = /a 가 /a?x=/b 요청에 매칭되는 이유가 이것입니다. 파라미터로 분기하려면 블록 안에서 $arg_name 이나 $args 를 읽어야 합니다. 알아 둘 만한 미묘한 점이 하나 있습니다. %3F 는 경로에 그대로 남는 물음표 문자로 디코딩되므로, /a%3Fx=1 은 쿼리 문자열이 비어 있고 경로에 ? 가 들어 있습니다.
nginx location에 JavaScript 정규식 문법을 쓸 수 있나요?
아니요 — nginx는 PCRE를 쓰고, 그 차이가 실제로 문제가 됩니다. 이 페이지는 ECMAScript 정규식만 존재하는 브라우저에서 돌아가므로, PCRE 전용 구문은 조용히 잘못 평가되는 대신 감지되어 표시됩니다. 아토믹 그룹, 소유 수량자, (?i) 같은 인라인 수식자, [[:alpha:]] 같은 POSIX 클래스, 그리고 JavaScript가 아무 말 없이 평범한 글자로 읽어 버리는 \A, \K 같은 이스케이프가 여기에 해당합니다. 어떤 location이 표시되면 나머지 후보는 그대로 nginx 순서대로 평가되지만, 그 블록의 판정은 실제 서버에서 확인해야 합니다. 패턴 자체를 작성하는 중이라면 정규식 테스터가 ECMAScript 문법을 깊이 다룹니다. nginx location 접두사 매칭은 대소문자를 구분하나요?
Linux에서는 구분합니다 — location /Static/ 은 /static/x 와 매칭되지 않습니다. macOS나 Cygwin처럼 대소문자를 구분하지 않는 파일 시스템에서는 nginx가 접두사를 대소문자 구분 없이 비교하고, 나아가 모든 정규식 location이 ~* 처럼 동작하도록 강제합니다. 이 페이지는 운영 서버가 거의 항상 돌리는 Linux 동작을 모델링합니다. Mac에서 개발하고 Linux에 배포한다면 이 차이가 배포 전까지 깨진 규칙을 가려 줄 수 있습니다.
try_files가 선택된 location 블록을 바꾸나요?
아니요. location 선택이 먼저 끝나고, try_files 는 이미 이긴 블록 안에서 그다음에 실행됩니다. 요청이 내 try_files 가 든 블록에 아예 도달하지 못한다면 그 지시어는 무의미합니다 — 흔한 원인은 폴백을 가진 접두사 블록이 손쓰기 전에 ~ \.php$ 정규식이 요청을 가져가는 것입니다. 나중에 발생하는 내부 리다이렉트는 매칭을 다시 시작하므로, 재작성된 URI는 location 목록의 맨 위부터 다시 해석됩니다.
슬래시 없이 디렉터리를 요청하면 nginx가 왜 301을 반환하나요?
서로 다른 두 가지 메커니즘이 그 결과를 냅니다. 이름이 / 로 끝나는 location이 proxy_pass 나 다른 *_pass 지시어를 달고 있으면, 슬래시 없는 같은 경로 요청은 정규식이 평가되기도 전에 location 선택 도중 301로 응답됩니다. 별개로, 정적 파일 모듈은 경로가 디스크의 실제 디렉터리로 해석될 때 301을 냅니다. 첫 번째는 여기서 보이고, 두 번째는 파일 시스템에 달려 있습니다. location = /path 를 추가하면 첫 번째가 억제됩니다.
중첩된 location 블록이 결과를 바꾸나요?
바꿉니다. 그것도 놓치기 쉬운 방식으로 바꿉니다. nginx는 이긴 접두사 location 안으로 내려가 그 자식들을 탐색하므로, 중첩된 정규식이 부모 레벨의 정규식보다 먼저 시도됩니다. 바깥 블록의 ^~ 는 그 블록 자신의 중첩 정규식으로부터 스스로를 지켜 주지 못하고, 바깥 레벨의 형제가 먼저 이기면 중첩 때문에 전역적으로 더 긴 접두사가 도달 불가가 될 수도 있습니다. 중첩 블록은 작성한 그대로의 들여쓰기로 여기서 모델링됩니다.
제 nginx 설정이 어딘가로 업로드되나요?
아니요. 구문 분석과 매칭은 평범한 문자열 연산으로 브라우저 안에서 처리됩니다 — 서버 호출이 없고 남기는 것도 없습니다. 실제 server 블록에는 업스트림 호스트명, 내부 포트, 인증서 경로, 인증 규칙이 들어 있으므로 이 점은 대부분의 도구보다 여기서 더 중요합니다. 말만 믿을 필요는 없습니다. 브라우저 개발자 도구를 열고 입력하는 동안 Network 패널이 조용한지 확인하거나, 아예 네트워크를 끊고 계속 테스트해 보세요. 외부 요청이 하나도 없다는 사실은 빌드마다 도는 자동 계약 테스트로도 강제되므로 조용히 되돌아갈 수 없습니다.