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 설정이 가장 중요합니다.