PHP-FPM이란 | PHP-FPM 설치 및 설정

공정위 광고 문구 Ver 3.1
공정위 광고 문구 Ver 3.2(모바일 전용)
테스트 환경 RHEL 계열AlmaLinux 9.8Apache 2.4 + PHP-FPM 8.3root 계정2026-10-26 확인

PHP-FPM은 웹 서버가 넘긴 PHP 요청을 미리 띄워 둔 워커 프로세스가 받아 처리하는 FastCGI 프로세스 관리자입니다. Apache가 운영되고 있는 AlmaLinux 9 서버에서 설치 여부와 사이트 계정별 풀·소켓 설정을 확인하고, 설정 검사와 상태 확인까지 실제 출력으로 정리했습니다.

Apache는 mod_php로 PHP를 직접 실행할 수도 있지만 PHP-FPM에 넘기면 웹 서버와 PHP가 분리됩니다. Nginx는 PHP를 직접 실행하지 못해 PHP-FPM 같은 FastCGI 프로세스에 넘깁니다. 그래서 PHP-FPM 하나에 Apache와 Nginx 어느 쪽이든 붙일 수 있습니다. 아래 풀 설정과 소켓 구조는 PHP-FPM과 Nginx를 연결할 때도 그대로 적용됩니다.

1️⃣ PHP-FPM이란: CGI와 FastCGI의 차이

CGI(Common Gateway Interface)는 웹 서버가 외부 프로그램을 실행해 동적 콘텐츠를 만드는 표준 방식이며, 요청이 들어올 때마다 프로그램을 새로 시작합니다. 요청마다 프로세스를 만들고 지우는 비용이 쌓여 접속이 늘수록 서버 응답이 느려집니다.

FastCGI는 이 비용을 없애기 위해 프로그램을 미리 띄워 두고 요청을 이어서 처리하는 방식입니다. 이는 쓸 때마다 컴퓨터를 켰다 끄는 것과, 켜 둔 컴퓨터를 바로 쓰는 것의 차이입니다. PHP-FPM(FastCGI Process Manager)은 PHP를 FastCGI로 운영하는 관리자이며, PHP 5.3.3 버전부터 PHP에 포함되었습니다.

PHP-FPM은 워커 묶음인 풀(pool)마다 정한 개수의 워커를 미리 띄워 두고, 웹 서버가 소켓으로 넘긴 요청을 빈 워커가 받아 처리한 뒤 다음 요청을 기다립니다. 그림과 CSS 같은 정적 파일은 웹 서버가 직접 응답하고 PHP 파일만 PHP-FPM으로 넘어갑니다. 웹 서버가 소켓에 요청을 넘기는 방법만 다르며, Apache는 mod_proxy_fcgi 모듈을, Nginx는 fastcgi_pass 설정을 사용합니다.

🧩 CGI와 PHP-FPM의 요청 처리
설명 다이어그램
⚙️ PHP 실행
🌐 웹 서버
🌐 ApacheNginx
📨 요청 1 · index.php📨 요청 2 · wp-login.php📨 요청 3 · index.php
정적 파일(그림·CSS)은 웹 서버가 직접 응답
요청마다 실행FastCGI · 소켓→
🧱 CGI 프로세스
요청 1새 프로세스 → 처리 → 종료
요청 2새 프로세스 → 처리 → 종료
요청 3새 프로세스 → 처리 → 종료
처리가 끝나면 프로세스도 사라짐 · 다음 요청은 다시 시작
🧰 PHP-FPM 풀 [siteuser]
워커 1요청 1
워커 2요청 2
워커 3요청 3
워커 4대기
워커 5대기
미리 띄운 워커가 요청을 받고, 끝나면 다음 요청을 기다림
Apache가 CGI로 PHP를 실행하면 요청마다 PHP 프로세스를 새로 시작하고 처리가 끝나면 종료하므로, 요청이 늘수록 프로세스를 만드는 비용이 쌓입니다.
Nginx는 CGI 프로그램을 직접 실행하는 모듈이 없어 이 조합은 사용하지 않으며, PHP는 FastCGI로 PHP-FPM에 넘깁니다.
Apache는 mod_proxy_fcgi로 PHP 요청을 소켓에 넘기고, 미리 띄워 둔 PHP-FPM 워커가 받아 처리한 뒤 다음 요청을 기다립니다.
Nginx는 fastcgi_pass로 같은 소켓에 넘기며, 웹 서버가 달라도 PHP-FPM 풀은 하나로 같습니다.

2️⃣ PHP-FPM 설치: 패키지 확인과 dnf 설치

RHEL 계열 서버에 dnf로 PHP를 설치했다면 php-fpm 패키지가 함께 설치되어 있습니다. rpm으로 설치 여부부터 확인합니다. PHP 설치 과정은 록키 리눅스 APM 설치와 같습니다.

rpm -qa | grep php-fpm
php-fpm-8.3.36-1.module_php.8.3.el9.remi.x86_64

출력이 비어 있으면 설치되지 않은 상태이며, dnf로 설치합니다.

dnf -y install php-fpm

설치가 끝나면 같은 rpm 명령으로 패키지 이름이 출력되는지 다시 확인합니다.

3️⃣ PHP-FPM 설정: www.conf 풀과 소켓, 정적·동적 모드

설정 파일은 전체 설정 [/etc/php-fpm.conf]와 풀 설정 [/etc/php-fpm.d/www.conf] 둘입니다. 기본 풀 www.conf에서 먼저 볼 줄은 listen과 pm이며, 설치 직후 값은 다음과 같습니다.

grep -E '^(listen|pm) ' /etc/php-fpm.d/www.conf
listen = /run/php-fpm/www.sock
pm = dynamic

listen은 웹 서버가 요청을 넘길 자리이며, 8.3 버전의 기본값은 유닉스 소켓 [/run/php-fpm/www.sock]입니다. 옛 버전의 기본값이었던 [127.0.0.1:9000]은 TCP 포트로 받는 방식입니다. 같은 서버 안에서는 소켓이 포트 연결 과정을 거치지 않아 더 가볍고, listen.owner와 listen.group으로 접근 권한을 파일 권한처럼 제한할 수 있습니다.

🔲 정적 모드와 동적 모드 설정

pm은 워커를 띄우는 방식이며 static·dynamic·ondemand 셋 중 하나를 지정합니다. 정적 모드는 pm.max_children에 적은 개수를 항상 띄워 두며, 아래 설정은 워커 100개를 유지합니다.

pm = static
pm.max_children = 100

동적 모드는 기본값이며 요청량에 따라 워커 수가 증감합니다. 아래 설정은 시작할 때 12개를 띄우고, 쉬는 워커를 6개 이상 18개 이하로 유지하며, 최대 120개까지 늘립니다.

pm = dynamic
pm.max_children = 120
pm.start_servers = 12
pm.min_spare_servers = 6
pm.max_spare_servers = 18

ondemand 모드는 요청이 올 때만 워커를 띄우고 pm.process_idle_timeout이 지나면 종료하므로, 접속이 드문 사이트에 맞고 접속이 잦은 사이트에는 맞지 않습니다.

세 모드는 워커를 띄우는 시점과 증감 방식이 다릅니다.

모드워커를 띄우는 방식맞는 사이트
static(정적)pm.max_children에 적은 개수를 항상 띄워 둠접속이 잦은 사이트
dynamic(동적)기본값 · 요청량에 따라 pm.start_servers·pm.min_spare_servers·pm.max_spare_servers 안에서 증감접속량이 오르내리는 사이트
ondemand요청이 올 때만 띄우고 pm.process_idle_timeout이 지나면 종료접속이 드문 사이트

max_children은 서버 메모리를 워커 하나가 사용하는 메모리로 나눠 정합니다. [max_children] 도달 경고가 쌓여도 바로 올리지 않고 로그로 워커를 채운 요청부터 가려냅니다.

메모리와 업로드 상한은 PHP 전체 설정인 php.ini에서 정하며, 운영하는 사이트에 맞춰 워커 수와 함께 조정합니다.

memory_limit = 1024M
post_max_size = 128M
upload_max_filesize = 128M

세 값은 PHP 스크립트 하나가 사용할 메모리 상한과 한 번에 올릴 수 있는 파일 크기이며, 바꾼 뒤 PHP-FPM을 재시작해야 적용됩니다.

🔲 사이트 계정별 풀 설정

사이트가 여럿이면 www.conf 하나를 같이 사용하지 않고 계정마다 풀 파일을 만들어 실행 계정과 소켓을 나눕니다. 한 사이트의 PHP가 다른 계정의 파일을 읽지 못하고, 워커 개수도 사이트별로 정해집니다.

vi /etc/php-fpm.d/siteuser.conf

파일에는 풀 이름과 실행 계정, 소켓 경로, 워커 수를 적습니다.

[siteuser]
user = siteuser
group = nobody
listen = /run/php-fpm/siteuser.sock
listen.owner = siteuser
listen.group = nobody
listen.mode = 0660
pm = dynamic
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 35
chdir = /home/siteuser/www

listen.owner와 listen.group은 소켓 파일의 소유자와 그룹이며, PHP-FPM이 시작할 때 이 값으로 소켓을 만듭니다. 웹 서버가 nobody 계정으로 실행되면 listen.group을 nobody로, apache 계정이면 apache로 적어 웹 서버가 소켓을 열 수 있게 합니다.

listen.owner = siteuser
listen.group = nobody
listen.mode = 0660

이 세 줄은 풀 파일마다 들어가며, 값을 바꾼 뒤에는 재시작해야 소켓이 새 권한으로 다시 만들어집니다.

🔲 slowlog 설정

slowlog는 request_slowlog_timeout보다 오래 걸린 요청의 실행 위치를 기록하는 파일이며, 값이 0이면 기록하지 않습니다. 느린 요청의 원인을 찾을 때 3s처럼 초 단위로 지정해 켭니다.

slowlog = /var/log/php-fpm/www-slow.log
request_slowlog_timeout = 0

기록된 파일에는 느린 요청의 스크립트 경로와 그때 실행 중이던 함수가 남아, 어느 플러그인이나 코드가 시간을 끌었는지 확인할 수 있습니다.

4️⃣ Apache 연동: VirtualHost 설정과 소켓 권한

Apache는 mod_proxy_fcgi 모듈로 PHP 파일 요청을 풀의 소켓에 넘깁니다. VirtualHost 안의 FilesMatch에 SetHandler 한 줄을 넣으며, 사이트마다 그 계정의 소켓을 적습니다.

# 사이트 계정마다 VirtualHost 하나 · SetHandler 에 그 계정의 소켓(SetHandler 대신 ProxyPassMatch 로도 연결 가능)
<VirtualHost *:80>
    ServerName example.com
    ServerAlias www.example.com
    DocumentRoot /home/siteuser/www

    <Directory /home/siteuser/www>
        Options -Indexes +FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>

    <FilesMatch \.php$>
        SetHandler "proxy:unix:/run/php-fpm/siteuser.sock|fcgi://localhost"
    </FilesMatch>
</VirtualHost>

DocumentRoot와 Directory는 그 계정의 웹 루트이며, Options의 -Indexes는 폴더 목록이 브라우저에 노출되는 것을 막습니다.

🔲 소켓 권한 설정

풀을 시작하면 listen.owner·listen.group·listen.mode 값으로 소켓이 만들어지며, 권한이 맞는지 ls로 확인합니다.

ls -l /run/php-fpm/
합계 4
srw-rw----  1 siteuser_a nobody 0 10월 22 23:34 siteuser_a.sock
-rw-r--r--  1 root       root   7 10월 26 03:00 php-fpm.pid
srw-rw----  1 siteuser_b nobody 0 10월 22 23:34 siteuser_b.sock
srw-rw----+ 1 root       root   0 10월 22 23:34 www.sock

권한이 어긋나 웹 서버가 소켓을 열지 못하면 방문자는 503 오류를 받으며, 재시작 없이 바로 맞출 때는 chown과 chmod로 소유자와 권한을 지정합니다.

사용자와 그룹을 콜론으로 구분하는 지금 문법입니다.

chown siteuser:nobody /run/php-fpm/siteuser.sock

소유자를 바꾼 뒤 권한을 660으로 맞춥니다.

chmod 660 /run/php-fpm/siteuser.sock

사용자와 그룹을 점으로 구분하는 옛 문법이며, AlmaLinux 9의 chown에서도 그대로 실행됩니다.

chown siteuser.nobody /run/php-fpm/siteuser.sock

소유자를 바꾼 뒤 권한을 660으로 맞춥니다.

chmod 660 /run/php-fpm/siteuser.sock

두 문법의 결과는 같으며, 어느 쪽을 사용해도 소켓의 소유자가 siteuser, 그룹이 nobody로 바뀝니다.

🔲 Nginx 연동: fastcgi_pass 설정

Nginx는 server 블록 안 PHP 파일 location에서 fastcgi_pass로 같은 풀의 소켓에 요청을 넘깁니다.

location ~ \.php$ {
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_pass unix:/run/php-fpm/siteuser.sock;
}

Nginx가 nginx 계정으로 실행되면 풀 파일의 listen.group을 nginx로 적어야 소켓을 열 수 있습니다.

5️⃣ 설정 검사와 재시작: php-fpm -t, systemctl

설정을 바꾼 뒤에는 바로 재시작하지 않고 php-fpm -t로 문법 검사를 먼저 합니다. 풀 파일에 오타가 있으면 재시작 때 PHP-FPM 전체가 내려가 모든 사이트가 503을 받기 때문입니다.

php-fpm -t
[26-Oct-2026 17:33:45] NOTICE: configuration file /etc/php-fpm.conf test is successful

검사를 통과하면 설정 파일 경로와 함께 [test is successful] 메시지가 출력되며, 그다음 PHP-FPM에 반영합니다. 소켓 경로나 listen.owner처럼 소켓을 다시 만들어야 하는 변경은 restart로 반영합니다. 운영 중인 서버에서 워커 수 같은 값만 바꿨다면 reload로 반영합니다.

systemctl restart php-fpm

VirtualHost를 고쳤으면 Apache도 재시작합니다.

systemctl restart httpd

서버를 다시 켰을 때 자동으로 실행되도록 enable로 등록합니다.

systemctl enable php-fpm

등록 여부는 is-enabled로 확인합니다.

systemctl is-enabled php-fpm
enabled

status로 풀마다 워커가 떠 있는지 확인합니다.

systemctl status php-fpm
● php-fpm.service - The PHP FastCGI Process Manager
     Loaded: loaded (/usr/lib/systemd/system/php-fpm.service; enabled; preset: disabled)
     Active: active (running) since x
    Process: 3934033 ExecReload=/bin/kill -USR2 $MAINPID (code=exited, status=0/SUCCESS)
   Main PID: 1333314 (php-fpm)
     Status: "Processes active: 4, idle: 21, Requests: x, slow: 0, Traffic: x"
      Tasks: x
     Memory: x
        CPU: x
     CGroup: /system.slice/php-fpm.service
             ├─  41920 "php-fpm: pool siteuser_a"
             ├─  94143 "php-fpm: pool siteuser_b"
             ├─1333314 "php-fpm: master process (/etc/php-fpm.conf)"
             ├─3934078 "php-fpm: pool www"
             └─4009016 "php-fpm: pool siteuser_a"

10월 26 03:00:01 server.example.com systemd[1]: Reloading The PHP FastCGI Process Manager...
10월 26 03:00:01 server.example.com systemd[1]: Reloaded The PHP FastCGI Process Manager.

Status 줄의 active와 idle이 지금 처리 중인 워커와 쉬는 워커이며, CGroup에는 풀 이름별로 워커가 나열됩니다. 출력의 호스트 이름과 풀 이름은 예시 값으로 바꿨습니다.

🔢 FAQ & 추천 콘텐츠

mod_php는 Apache 프로세스 안에서 PHP를 실행해 설정이 간단하지만, Apache 워커마다 PHP가 올라가 메모리를 많이 사용하고 실행 계정을 사이트별로 나누기 어렵습니다. PHP-FPM은 PHP를 별도 프로세스로 분리해 사이트마다 계정과 워커 수를 정할 수 있어, 사이트가 여럿이거나 Nginx를 사용하는 서버는 PHP-FPM을 사용합니다.

systemctl reload php-fpm은 마스터 프로세스에 USR2 신호를 보내 설정을 다시 읽고 워커를 교체합니다. process_control_timeout을 지정하면 처리 중인 요청을 마친 워커부터 교체합니다(공식 문서 기준). restart는 모든 워커를 한 번에 내렸다 올리므로 그 순간의 요청이 끊길 수 있어, 운영 중인 서버에서는 reload를 먼저 사용합니다.

RHEL 계열의 기본 로그는 [/var/log/php-fpm/error.log]이며, 워커 부족 경고(seems busy·max_children)와 풀 시작·중지 기록이 여기에 남습니다. 풀마다 php_admin_value[error_log]로 지정한 파일에는 그 사이트 PHP 코드의 오류가 따로 기록됩니다. 기본 풀은 [/var/log/php-fpm/www-error.log]에 기록됩니다.

ℹ️ 제휴 안내
본 사이트의 콘텐츠에는 제휴 링크가 포함되어 있습니다. 방문자가 이 링크를 통해 상품 또는 서비스를 구매하면 본 사이트는 판매처로부터 수수료를 지급받습니다. 이 과정에서 구매자가 지불하는 금액(이벤트 할인 시 금액이 내려갑니다↓)은 오르지 않습니다. 게시된 가격·할인·재고 정보는 작성 시점 기준이며 실제와 다를 수 있으므로, 구매 전 판매처에서 최종 확인하시기 바랍니다. 상품 선정과 평가는 자체 기준에 따라 작성되며, 수수료 지급 여부가 소개 순서나 평가 내용에 영향을 주지 않습니다.

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다

인간임을 증명하세요: 1   +   1   =