Nginx는 Apache와 달리 PATH_INFO를 자동으로 처리하지 않아서 PHP 애플리케이션에서 URL 라우팅이 제대로 작동하지 않는 경우가 많습니다. 이 문제를 해결하는 다양한 방법들을 알아보겠습니다.
가장 기본적인 PATH_INFO 설정 방법입니다.
location ~ ^(.+\.php)(.*)$ {
fastcgi_split_path_info ^(.+\.php)(.*)$;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
include fastcgi_params;
}
존재하지 않는 파일에 대해 index.php로 라우팅하는 방법입니다.
server {
listen 80;
server_name example.com;
root /var/www/html;
index index.php;
location / {
try_files $uri $uri/ /index.php$is_args$args;
}
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
include fastcgi_params;
}
}
더 정확한 PATH_INFO 분리를 위한 설정입니다.
location ~ ^/api/(.+\.php)(/.*)?$ {
alias /var/www/api;
fastcgi_split_path_info ^(.+\.php)(/.*)?$;
fastcgi_param SCRIPT_FILENAME $request_filename;
fastcgi_param PATH_INFO $fastcgi_path_info if_not_empty;
fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
include fastcgi_params;
}
PHP 코드에서 PATH_INFO를 올바르게 처리하는 방법입니다.
<?php
// PATH_INFO 확인 및 설정
function getPathInfo() {
if (isset($_SERVER['PATH_INFO'])) {
return $_SERVER['PATH_INFO'];
}
// Nginx에서 PATH_INFO가 설정되지 않은 경우 대안
$requestUri = $_SERVER['REQUEST_URI'];
$scriptName = $_SERVER['SCRIPT_NAME'];
if (strpos($requestUri, $scriptName) === 0) {
return substr($requestUri, strlen($scriptName));
}
return '/';
}
$pathInfo = getPathInfo();
echo "PATH_INFO: " . $pathInfo;
Laravel, Symfony 등 프레임워크를 위한 설정입니다.
server {
listen 80;
server_name laravel.local;
root /var/www/laravel/public;
index index.php;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
}
}
RESTful API를 위한 PATH_INFO 설정입니다.
location /api {
rewrite ^/api/(.*)$ /api/index.php/$1 last;
}
location ~ ^/api/index\.php(/.*)?$ {
fastcgi_split_path_info ^(/api/index\.php)(/.*)?$;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
include fastcgi_params;
}
PATH_INFO 문제를 디버깅하기 위한 설정입니다.
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
# 디버깅 헤더 추가
add_header X-Script-Name $fastcgi_script_name;
add_header X-Path-Info $fastcgi_path_info;
fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
include fastcgi_params;
}
설정이 올바른지 확인하는 PHP 스크립트입니다.
<?php
header('Content-Type: text/plain');
echo "=== PATH_INFO Debug Information ===\n";
echo "REQUEST_URI: " . ($_SERVER['REQUEST_URI'] ?? 'Not set') . "\n";
echo "SCRIPT_NAME: " . ($_SERVER['SCRIPT_NAME'] ?? 'Not set') . "\n";
echo "PATH_INFO: " . ($_SERVER['PATH_INFO'] ?? 'Not set') . "\n";
echo "QUERY_STRING: " . ($_SERVER['QUERY_STRING'] ?? 'Not set') . "\n";
echo "PHP_SELF: " . ($_SERVER['PHP_SELF'] ?? 'Not set') . "\n";
echo "\n=== All $_SERVER variables ===\n";
foreach ($_SERVER as $key => $value) {
if (strpos($key, 'PATH') !== false || strpos($key, 'SCRIPT') !== false) {
echo "$key: $value\n";
}
}
특정 조건에서만 PATH_INFO를 처리하는 설정입니다.
location ~ \.php$ {
# PHP 파일이 실제로 존재하는지 확인
try_files $uri =404;
# PATH_INFO가 있는 경우에만 분리
if ($uri ~ "^(.+\.php)(.*)$") {
set $script $1;
set $path_info $2;
}
fastcgi_param SCRIPT_FILENAME $document_root$script;
fastcgi_param PATH_INFO $path_info;
fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
include fastcgi_params;
}
이러한 설정들을 상황에 맞게 적용하면 Nginx에서 PATH_INFO 관련 문제를 해결할 수 있습니다. 설정 후에는 반드시 테스트 스크립트로 확인하고, 애플리케이션의 라우팅이 정상적으로 작동하는지 검증해야 합니다.