From d406e54fcf1e03b45a19349f8f3a596d410f7635 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=B3=B4=EA=B3=A4?= Date: Sun, 22 Feb 2026 21:39:15 +0900 Subject: [PATCH] =?UTF-8?q?docs:=20[guides]=20PHP-FPM=20=EC=B4=88=EB=B3=B4?= =?UTF-8?q?=EC=9E=90=20=EA=B0=80=EC=9D=B4=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - PHP-FPM 개념, 역사(CGI→mod_php→PHP-FPM), 구조 설명 - Nginx-PHP-FPM 관계 및 FastCGI 프로토콜 - SAM 컨테이너별 설정(www.conf) 상세 - 자주 묻는 질문 (502 에러, 워커 부족, 재시작 등) --- INDEX.md | 1 + guides/php-fpm-guide.md | 261 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 262 insertions(+) create mode 100644 guides/php-fpm-guide.md diff --git a/INDEX.md b/INDEX.md index 384016e..a0e650c 100644 --- a/INDEX.md +++ b/INDEX.md @@ -104,6 +104,7 @@ docs/ | [project-launch-roadmap.md](guides/project-launch-roadmap.md) | 런칭 준비 현황 | 런칭 관련 작업 시 | | [production-env-sync.md](guides/production-env-sync.md) | 운영 전환 시 .env 동기화 절차 | 테스트→운영 전환 시 | | [server-how-it-works.md](guides/server-how-it-works.md) | 서버 동작 원리 초보자 가이드 | 신규 합류 시 | +| [php-fpm-guide.md](guides/php-fpm-guide.md) | PHP-FPM 초보자 가이드 | PHP-FPM 개념 이해 시 | | [jenkins-setup-guide.md](guides/jenkins-setup-guide.md) | Jenkins CI/CD 셋업 가이드 | Jenkins 설치/설정 시 | ### quickstart/ - 빠른 시작 diff --git a/guides/php-fpm-guide.md b/guides/php-fpm-guide.md new file mode 100644 index 0000000..ef19a06 --- /dev/null +++ b/guides/php-fpm-guide.md @@ -0,0 +1,261 @@ +# PHP-FPM 초보자 가이드 + +> **작성일**: 2026-02-22 +> **대상**: SAM 프로젝트에 새로 합류한 개발자 + +--- + +## 1. 개요 + +### 1.1 PHP-FPM이란 + +**PHP-FPM**(FastCGI Process Manager)은 PHP 코드를 실행하는 **프로세스 관리자**다. +Nginx는 PHP를 직접 실행하지 못하므로, PHP-FPM이 대신 실행하고 결과를 돌려준다. + +### 1.2 이 문서의 목적 + +[서버 동작 원리 가이드](server-how-it-works.md)에서 PHP-FPM을 간략히 소개했다. +이 문서는 **왜 필요한지**, **어떻게 동작하는지**, **SAM에서 어떤 설정으로 쓰이는지**를 다룬다. + +--- + +## 2. PHP가 웹에서 동작하는 방식의 역사 + +### 2.1 CGI → mod_php → PHP-FPM + +``` +[1세대 CGI] 요청마다 PHP 프로세스 생성/종료 → 느림 +[2세대 mod_php] Apache에 PHP 내장 → 빠르지만 Nginx 불가, 메모리 낭비 +[3세대 PHP-FPM] Nginx와 분리, 워커 풀 재사용 → 빠르고 유연 ← SAM이 사용 +``` + +**비유로 이해하기**: + +| 세대 | 비유 | +|------|------| +| CGI | 손님마다 직원을 채용하고 해고하는 식당 | +| mod_php | 직원이 주방장(Apache)과 한 몸 — 따로 관리 불가 | +| **PHP-FPM** | 안내 데스크(Nginx)와 업무 창구(PHP-FPM) 분리된 은행 | + +### 2.2 요약 + +| 세대 | 방식 | 장점 | 단점 | +|------|------|------|------| +| CGI | 매번 프로세스 생성 | 단순 | 느림, 리소스 낭비 | +| mod_php | Apache에 내장 | CGI보다 빠름 | Nginx 불가, 메모리 낭비 | +| **PHP-FPM** | 독립 프로세스 관리 | 빠름, 유연 | 설정 필요 | + +--- + +## 3. PHP-FPM의 구조 + +### 3.1 Master / Worker 모델 + +PHP-FPM은 **Master 프로세스** 1개와 **Worker 프로세스** 여러 개로 구성된다. + +``` +PHP-FPM +┌──────────────────────────────────┐ +│ Master 프로세스 (관리자) │ +│ ├── Worker 1 (대기 중) │ +│ ├── Worker 2 (요청 처리 중) │ +│ ├── Worker 3 (대기 중) │ +│ ├── Worker 4 (요청 처리 중) │ +│ └── Worker 5 (대기 중) │ +└──────────────────────────────────┘ +``` + +**은행 창구 비유**: + +| PHP-FPM | 은행 | +|---------|------| +| Master 프로세스 | 지점장 (직원 수 조절, 감독) | +| Worker 프로세스 | 창구 직원 (실제 업무 처리) | +| `pm.max_children` | 최대 창구 수 | +| 요청 큐 | 대기 번호표 줄 | + +- **Master**: 워커 생성/종료, 비정상 워커 재시작, 포트 9000 대기 +- **Worker**: PHP 코드 실행, 1 Worker = 1 요청, 완료 후 다음 요청 대기 + +### 3.2 포트 9000과 프로세스 관리 모드 + +PHP-FPM은 **TCP 포트 9000**에서 요청을 기다린다. + +``` +Nginx ──── TCP 9000 ────→ PHP-FPM Master ──→ 빈 Worker에 배정 +``` + +Master가 Worker 수를 관리하는 3가지 모드: + +| 모드 | 설명 | SAM | +|------|------|-----| +| `static` | 항상 고정 수 유지 | - | +| **`dynamic`** | 트래픽에 따라 조절 | **사용 중** | +| `ondemand` | 요청 올 때만 생성 | - | + +--- + +## 4. Nginx와 PHP-FPM의 관계 + +### 4.1 왜 Nginx는 PHP를 직접 못 실행하는가 + +Nginx는 정적 파일 서빙과 리버스 프록시 전용이다. PHP 해석 엔진이 없으므로 `.php` 파일을 실행할 수 없다. + +### 4.2 FastCGI 프로토콜 + +Nginx와 PHP-FPM은 **FastCGI** 프로토콜로 통신한다. + +``` +브라우저 ──HTTP──→ Nginx ──FastCGI──→ PHP-FPM ──→ PHP 실행 + │ +브라우저 ←──HTTP── Nginx ←──FastCGI── PHP-FPM ←────┘ +``` + +Nginx가 FastCGI로 전달하는 주요 정보: +- `SCRIPT_FILENAME` — 실행할 PHP 파일 경로 (`/var/www/mng/public/index.php`) +- `REQUEST_METHOD` — GET, POST 등 +- `QUERY_STRING` — URL 파라미터 + +### 4.3 역할 분담 + +``` +┌─────────────────────┐ ┌─────────────────────┐ +│ Nginx │ │ PHP-FPM │ +│ │ TCP │ │ +│ • SSL 종료 │ 9000 │ • PHP 코드 실행 │ +│ • 도메인 라우팅 │─────→│ • Laravel 구동 │ +│ • 정적 파일 서빙 │ │ • DB 조회 │ +│ • 보안 필터링 │ │ • HTML/JSON 생성 │ +└─────────────────────┘ └─────────────────────┘ +``` + +--- + +## 5. SAM에서의 PHP-FPM + +### 5.1 컨테이너 구조 + +``` +Docker +├── sam-nginx-1 ── 외부 리버스 프록시 +├── sam-api-1 +│ └── Supervisor +│ ├── php-fpm ← 포트 9000 +│ ├── nginx ← 컨테이너 내부 웹서버 +│ ├── queue-worker ← 백그라운드 작업 +│ └── scheduler ← 60초 예약 작업 +├── sam-mng-1 +│ └── Supervisor +│ ├── php-fpm ← 포트 9000 +│ ├── nginx ← 컨테이너 내부 웹서버 +│ └── queue-worker x2 +└── sam-mysql-1 +``` + +Supervisor가 PHP-FPM과 Nginx를 함께 관리한다. 컨테이너 시작 시 Supervisor가 모든 프로세스를 기동한다. + +### 5.2 PHP-FPM 설정 (`www.conf`) + +SAM 설정 파일 위치: `docker/mng/www.conf` + +```ini +[www] +user = www-data +group = www-data +listen = 0.0.0.0:9000 + +pm = dynamic +pm.max_children = 20 +pm.start_servers = 5 +pm.min_spare_servers = 5 +pm.max_spare_servers = 10 +pm.max_requests = 500 +``` + +**각 설정의 의미**: + +| 설정 | 값 | 의미 | +|------|-----|------| +| `pm` | `dynamic` | 트래픽에 따라 워커 수 조절 | +| `pm.max_children` | `20` | 최대 동시 처리 수 (= 최대 창구 20개) | +| `pm.start_servers` | `5` | 시작 시 워커 수 | +| `pm.min_spare_servers` | `5` | 최소 대기 워커 수 | +| `pm.max_spare_servers` | `10` | 최대 대기 워커 수 | +| `pm.max_requests` | `500` | 500건 처리 후 워커 재시작 (메모리 누수 방지) | + +### 5.3 워커 수의 동적 변화 + +``` +워커 수 +20 ┤ ■■■■ (피크) +10 ┤ ■■■■■ ■■■■■ + 5 ┤ ■■■■■■■■■■■■■ ■■■■■■■■ + 0 ┤────────────────────────────────────────────── + 새벽 오전 점심 오후 +``` + +### 5.4 Docker 이미지 + +SAM은 `php:8.4-fpm` 공식 이미지를 기반으로 한다. 이미지 이름의 `fpm`이 PHP-FPM 내장을 의미한다. + +```dockerfile +FROM php:8.4-fpm +# Supervisor로 php-fpm + nginx 동시 기동 +CMD ["/usr/bin/supervisord"] +``` + +--- + +## 6. 자주 묻는 질문 + +### 6.1 "502 Bad Gateway 에러가 뭔가요?" + +Nginx가 PHP-FPM에 연결 실패 시 발생한다. PHP-FPM이 죽었거나, 컨테이너가 비정상 시작된 경우다. + +```bash +# 컨테이너 상태 확인 +docker ps + +# 로그 확인 +docker logs sam-mng-1 +``` + +### 6.2 "워커가 부족하면?" + +20개 워커가 모두 처리 중이면 새 요청은 대기열에 들어간다. 너무 오래 대기하면 504 Gateway Timeout이 발생한다. `pm.max_children`을 올리거나 느린 코드를 최적화한다. + +### 6.3 "PHP-FPM을 재시작하려면?" + +```bash +# 컨테이너 전체 재시작 +docker restart sam-mng-1 + +# PHP-FPM만 재시작 +docker exec sam-mng-1 supervisorctl restart php-fpm +``` + +### 6.4 "프로세스 상태를 확인하려면?" + +```bash +docker exec sam-mng-1 supervisorctl status +# nginx RUNNING pid 8, uptime 2:30:00 +# php-fpm RUNNING pid 9, uptime 2:30:00 +# queue-worker_00 RUNNING pid 10, uptime 2:30:00 +``` + +### 6.5 "php artisan serve와 뭐가 다른가요?" + +`php artisan serve`는 개발용 간이 서버로 동시 요청 1개만 처리한다. PHP-FPM은 워커 수만큼 동시 처리가 가능한 프로덕션용이다. SAM은 PHP-FPM을 사용한다. + +--- + +## 관련 문서 + +| 문서 | 설명 | +|------|------| +| [server-how-it-works.md](server-how-it-works.md) | 서버 동작 원리 전체 가이드 | +| [docker-setup.md](../specs/docker-setup.md) | Docker 환경 설정값 상세 | + +--- + +**최종 업데이트**: 2026-02-22