실제 예제로 배우는 Nginx location 매칭 규칙
Nginx 설정을 수정하고 리로드한 뒤, 왜 location 블록이 적용되지 않는지 의아해한 적이 있을 것입니다. 정적 파일 요청이 PHP 핸들러로 가거나, API 라우트가 catch-all에 삼켜지는 경우 말이죠. 원인은 종종 Nginx의 location 매칭 알고리즘에 있습니다. 생각보다 간단하지 않습니다.
이 가이드에서는 Nginx가 location 블록을 선택하는 방법을 실제 테스트 가능한 예제와 함께 분석합니다. 끝까지 읽으면 어떤 블록이 왜 선택되는지 정확히 알게 될 것입니다.
Nginx Location 매칭 작동 방식
요청이 들어오면 Nginx는 URI를 정의된 모든 location 블록과 비교합니다. 매칭 과정은 특정 순서를 따릅니다:
- 정확 일치 (
=) — 최우선순위. 발견되면 Nginx는 중단하고 이를 사용합니다. - 최장 접두사 일치 — Nginx는 가장 길게 일치하는 접두사 location을 기억합니다.
- 정규식 일치 (
~또는~*) — 나타나는 순서대로 확인됩니다. 일치하는 첫 번째 정규식이 이기며, 접두사 일치를 덮어씁니다 (^~가 사용되지 않은 경우). ^~를 사용한 접두사 일치 — 가장 길게 일치하는 접두사에^~가 있으면 Nginx는 정규식 검사를 건너뛰고 이를 사용합니다.- 정규식이 일치하지 않으면 최장 접두사 일치가 사용됩니다.
이것이 핵심 알고리즘입니다. 실제로 어떻게 작동하는지 살펴보겠습니다.
Location 수정자: 빠른 참조
| 수정자 | 구문 | 매치 유형 | 우선순위 |
|---|---|---|---|
= | location = /path | 정확 | 최상 |
^~ | location ^~ /path | 접두사 (정규식 없음) | 높음 |
~ | location ~ \.php$ | 정규식 (대소문자 구분) | 중간 |
~* | location ~* \.(jpg|png)$ | 정규식 (대소문자 무시) | 중간 |
| 없음 | location /path | 접두사 | 최하 |
실제 예제 1: 정적 파일 vs. PHP
다음과 같은 일반적인 설정을 생각해 보세요:
server {
listen 80;
server_name example.com;
location / {
root /var/www/html;
}
location ~ \.php$ {
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
}
}
/index.php 요청은 정규식 \.php$와 일치하므로 PHP-FPM으로 전달됩니다. /logo.png 요청은 정규식과 일치하지 않으므로 접두사 /로 폴백되어 정적 파일을 제공합니다. 간단하죠?
하지만 /uploads/photo.php를 정적 파일로 제공하고 싶다면 (실제로 이미지일 수도 있음) 어떻게 할까요? 정확 일치를 추가할 수 있습니다:
location = /uploads/photo.php {
root /var/www/html;
}
이제 이 정확 일치가 정규식보다 우선합니다.
실제 예제 2: 접두사와 정규식을 사용한 API 라우팅
/api/ 아래에 API가 있고 정적 응답을 반환하는 헬스 체크를 제외한 모든 요청을 백엔드로 프록시하고 싶다고 가정해 보세요.
location = /api/health {
return 200 "OK";
}
location /api/ {
proxy_pass http://backend;
}
location ~ ^/api/v[0-9]+/special {
proxy_pass http://special-backend;
}
/api/health를 추적해 보겠습니다: 정확 일치가 이기고 200을 반환합니다. /api/users의 경우: 정확 일치도 없고 정규식도 일치하지 않으므로 (special과 일치하지 않음) 최장 접두사 /api/가 사용됩니다. /api/v1/special의 경우: 정규식이 일치하므로 접두사를 덮어쓰고 special-backend로 전달됩니다.
이는 정규식이 접두사 일치를 덮어쓸 수 있음을 보여줍니다. 접두사가 항상 이기게 하려면 대신 ^~를 사용하면 됩니다.
실제 예제 3: ^~의 힘
/static/ 디렉토리에 .php로 끝나더라도 절대 PHP로 처리되어서는 안 되는 파일들이 있다고 상상해 보세요. ^~를 사용하면 Nginx가 정규식 location을 확인하지 않도록 보장합니다.
location ^~ /static/ {
root /var/www/html;
}
location ~ \.php$ {
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
}
/static/script.php 요청은 접두사 ^~ /static/과 일치합니다. ^~ 덕분에 Nginx는 정규식 검사를 건너뛰고 파일을 직접 제공합니다. ^~ 없이는 정규식이 일치하여 PHP-FPM이 이를 실행할 수 있습니다—잠재적인 보안 위험입니다.
흔한 함정과 피하는 방법
- 정규식 순서가 중요합니다: Nginx는 설정에 나타나는 순서대로 정규식 location을 확인합니다. 더 구체적인 패턴을 먼저 배치하세요.
- 후행 슬래시 누락:
location /api와location /api/는 다릅니다. 전자는/api와/apix를 일치시키고, 후자는/api/와/api/users를 일치시킵니다. 정확하게 작성하세요. - 겹치는 접두사: 최장 접두사가 이기므로
/api/v1/users의 경우location /api/v1이location /api보다 우선합니다. - 정적 자산에
^~를 잊는 경우: 정규식이 정적 파일 요청을 가로채지 않도록 사용하세요. - 대소문자 구분:
~는 대소문자를 구분하고~*는 구분하지 않습니다. 파일 확장자에는~*를 사용하세요.
Location 매칭 디버깅
어떤 location이 사용되는지 확실하지 않다면 Nginx에서 디버그 로깅을 활성화하세요. 서버 블록에 error_log /var/log/nginx/error.log debug;를 추가하고 리로드한 후 로그를 확인하세요. test location: "/api/users"와 using configuration "/api/" 같은 줄을 볼 수 있습니다.
또는 각 location에 임시로 return 200 "matched: /api/";를 사용하여 어느 것이 응답하는지 확인할 수 있습니다.
FAQ
Nginx location 수정자의 우선순위는 어떻게 되나요?
정확 일치 (=)가 가장 높고, 그다음 ^~가 있는 최장 접두사, 그다음 순서대로 정규식 (~ 또는 ~*), 마지막으로 ^~가 없는 최장 접두사 일치입니다.
정규식 location이 접두사 location을 덮어쓸 수 있나요?
예, 접두사 location이 ^~를 사용하지 않는 한 가능합니다. 정규식 location은 최장 접두사 일치 후에 확인되며, 정규식이 일치하면 일반 접두사보다 우선합니다.
특정 파일에만 location을 일치시키려면 어떻게 하나요?
=를 사용한 정확 일치를 사용하세요. 예: location = /favicon.ico. 이렇게 하면 정확히 해당 URI만 일치됩니다.
Nginx 설정 마스터하기
location 매칭을 이해하는 것은 안정적인 Nginx 설정의 핵심입니다. nginx -t로 설정을 테스트하고 의심스러울 때는 디버그 로그를 사용하세요. Nginx 로그를 다루고 트래픽 패턴을 분석해야 한다면 Nginx Log Analyzer를 사용하여 로그를 빠르게 파싱하고 시각화해 보세요.