PHP-FPM(FastCGI Process Manager)의 기본 설정은 보수적이어서 서버 메모리를 제대로 활용하지 못합니다. 올바른 설정으로 PHP 애플리케이션 성능을 크게 향상시킬 수 있습니다.
PHP-FPM 설치
# Ubuntu
sudo apt install -y php8.2-fpm
# 상태 확인
sudo systemctl status php8.2-fpm
pm(Process Manager) 설정 방식
/etc/php/8.2/fpm/pool.d/www.conf:
dynamic (권장: 일반 서버)
pm = dynamic
# 최소 유지할 유휴 워커 수
pm.min_spare_servers = 2
# 최대 유지할 유휴 워커 수
pm.max_spare_servers = 5
# 시작 시 워커 수
pm.start_servers = 3
# 최대 동시 처리 가능 요청 수
pm.max_children = 20
static (고트래픽 서버)
pm = static
pm.max_children = 30 # 항상 이 수만큼 워커 유지
ondemand (저사양 서버)
pm = ondemand
pm.max_children = 10
pm.process_idle_timeout = 10s # 유휴 워커 종료 대기 시간
max_children 계산법
# PHP 프로세스 하나의 평균 메모리 사용량 확인
ps aux | grep php-fpm | awk '{print $6}' | sort -n | tail -5
# 계산 공식:
# max_children = (사용 가능한 메모리) / (PHP 프로세스 평균 메모리)
# 예: 4GB RAM, PHP 프로세스당 50MB = 4096 / 50 ≈ 80
# 단, 다른 서비스(Nginx, MySQL 등) 메모리 여유분을 남겨두어야 함
요청 처리 제한
# 워커 하나가 처리할 최대 요청 수 (메모리 누수 방어)
pm.max_requests = 500
# 단일 요청 최대 실행 시간 (초)
request_terminate_timeout = 60s
느린 요청 로그 (Slow Log)
# 실행 시간이 긴 PHP 요청 기록
slowlog = /var/log/php8.2-fpm-slow.log
request_slowlog_timeout = 5s # 5초 이상 걸리는 요청 기록
# 느린 로그 확인
sudo tail -f /var/log/php8.2-fpm-slow.log
보안 설정
# 특정 디렉터리 외 PHP 실행 차단 (중요!)
security.limit_extensions = .php
# 환경 변수 노출 방지
clear_env = no
# open_basedir로 접근 가능한 디렉터리 제한
php_admin_value[open_basedir] = /var/www/html:/tmp
# 위험 PHP 함수 비활성화
php_admin_value[disable_functions] = exec,passthru,shell_exec,system,proc_open,popen
php.ini 성능 설정
# /etc/php/8.2/fpm/php.ini
; OPcache 활성화 (PHP 코드 캐싱으로 성능 향상)
opcache.enable=1
opcache.memory_consumption=128
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=4000
opcache.revalidate_freq=60
opcache.fast_shutdown=1
; 메모리 제한
memory_limit = 256M
; 업로드 제한
upload_max_filesize = 20M
post_max_size = 20M
; 최대 실행 시간
max_execution_time = 30
; 에러 로그 (프로덕션에서는 화면 출력 비활성화)
display_errors = Off
log_errors = On
error_log = /var/log/php8.2-error.log
Nginx와 PHP-FPM 연동
# /etc/nginx/sites-available/mysite
server {
listen 443 ssl;
server_name example.com;
root /var/www/html;
index index.php;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
# PHP-FPM 소켓 (TCP 대신 Unix 소켓이 빠름)
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
# 타임아웃 (php.ini의 max_execution_time과 맞춤)
fastcgi_read_timeout 60s;
}
# 업로드 디렉터리 PHP 실행 차단
location ~ ^/uploads/.*\.php$ {
deny all;
}
}
설정 적용 및 검증
# 설정 문법 검사
sudo php-fpm8.2 -t
# 재시작
sudo systemctl reload php8.2-fpm
# 상태 및 워커 수 확인
sudo systemctl status php8.2-fpm
ps aux | grep php-fpm | wc -l
# OPcache 상태 확인
php -r "var_dump(opcache_get_status());"
멀티 사이트 풀 설정
여러 사이트를 운영할 때는 사이트별로 별도 풀을 만드는 것이 보안상 안전합니다:
# /etc/php/8.2/fpm/pool.d/site1.conf
[site1]
user = site1user
group = site1user
listen = /run/php/php8.2-fpm-site1.sock
listen.owner = www-data
listen.group = www-data
pm = dynamic
pm.max_children = 10
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
PHP-FPM 최적화는 WordPress, Laravel 등 PHP 기반 애플리케이션의 응답 속도와 안정성에 직접적인 영향을 줍니다. 서버 메모리에 맞는 max_children 설정이 가장 중요합니다.