본문으로 건너뛰기
개발 머꼬
개발 노트Nginx
hohyeon.dev34

설정에 분명히 있는 location이 적용되지 않은 이유

  • #Engineering Note
  • #Nginx

문제 발생

이미지에 캐시 헤더를 주려고 정규식 location을 넣었더니, 정적 파일용으로 만들어둔 접두사 location이 통째로 무시됐습니다.

location /assets/ { ... }              # 적용 안 됨
location ~* \.(png|jpg)$ { ... }       # /assets/logo.png 가 여기로 감

반대로 어떤 경로는 정규식이 있는데도 접두사 쪽이 이겨서 또 헷갈렸습니다.

원인 분석

nginx의 매칭은 "위에서 아래로"가 아닙니다. 문서가 순서를 정확히 설명합니다.

location은 접두사 문자열 또는 정규식으로 정의된다. 주어진 요청에 맞는 location을 찾기 위해 nginx는 먼저 접두사 문자열로 정의된 location들을 검사한다. 그중 가장 긴 접두사가 일치하는 location이 선택되어 기억된다. 그다음 정규식들이 설정 파일에 나타난 순서대로 검사된다. 정규식 검색은 첫 일치에서 종료되고 그 설정이 사용된다. 정규식과 일치하는 것이 없으면 앞서 기억해둔 접두사 location의 설정이 사용된다.

그래서 /assets/logo.png는 접두사 /assets/를 기억해두고도, 정규식 \.(png|jpg)$가 맞는 순간 그쪽으로 갑니다.

우선순위를 정리하면 이렇습니다.

  1. = 정확히 일치 — 즉시 종료
  2. ^~ 접두사 — 문서 그대로 가장 긴 접두사 location에 ^~ 수정자가 있으면 정규식은 검사되지 않습니다
  3. 정규식 ~(대소문자 구분) / ~*(무시) — 설정 파일 순서대로, 첫 일치에서 종료
  4. 나머지 중 가장 긴 접두사

해결 방안

  1. 정규식보다 우선시키려면 ^~를 붙입니다.
location ^~ /assets/ { ... }           # 이제 정규식이 검사되지 않는다
location ~* \.(png|jpg)$ { ... }
  1. 정확히 한 경로면 =를 씁니다. 헬스체크나 /favicon.ico처럼 자주 오는 경로에 쓰면 매칭 비용도 줄어듭니다.
location = /health { access_log off; return 200; }
  1. 정규식 순서를 의식합니다. 첫 일치에서 끝나므로, 더 좁은 정규식을 위에 둡니다.

  2. 정규식 남용을 줄입니다. 확장자 기반 규칙은 편해 보이지만 이 매칭 순서를 계속 헷갈리게 만듭니다. 경로 구조(/static/, /uploads/)로 나누면 접두사만으로 끝납니다.

  3. nginx -T로 최종 설정을 확인합니다. include가 여러 겹이면 어떤 location이 실제로 존재하는지부터 확인해야 합니다.

공식 문서

마지막 수정

좋아요북마크

댓글0

아직 댓글이 없어요. 첫 의견을 편하게 남겨 보세요.