Zend OPcache 개념과 설치 및 설정: php.ini 값과 JIT 비활성화

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

Zend OPcache는 PHP 스크립트를 바이트코드로 컴파일해 공유 메모리에 저장하고, 같은 파일을 다시 실행할 때 컴파일을 건너뛰게 하는 PHP 확장입니다. PHP 8.3을 사용하는 워드프레스 서버에서 JIT을 활성화한 뒤 전 페이지에 500 오류가 나자, OPcache는 그대로 두고 JIT만 비활성화해 복구했습니다.

PHP 5.5부터는 OPcache가 PHP에 기본으로 포함되어 배포됩니다.

1️⃣ Zend OPcache 개념: 바이트코드 캐싱

PHP 스크립트는 요청이 올 때마다 파일 읽기, 바이트코드 컴파일, 실행의 세 단계를 거칩니다. OPcache가 동작하면 같은 파일의 두 번째 요청부터 앞의 두 단계가 빠지고 실행만 남습니다.

OPcache가 바이트코드를 저장하는 공유 메모리는 PHP-FPM의 모든 워커가 함께 사용합니다. 같은 PHP-FPM에 연결된 사이트가 여럿이면, 그 사이트들의 스크립트도 한 공유 메모리에 저장됩니다.

🧩 OPcache 없음과 있음의 요청 처리
설명 다이어그램
🧠 OPcache
📨 요청
🧰 PHP-FPM 워커
워커 1첫 요청
워커 2두 번째 요청
워커 3대기
요청마다 세 단계첫 요청 · 세 단계실행만→
⚙️ PHP 스크립트 처리
파일 읽기빠짐
→
바이트코드 컴파일빠짐
→
실행PHP 실행 · 데이터베이스 조회
공유 메모리 사용 안 함↓ 바이트코드 저장↑ 공유 메모리의 바이트코드 사용
🧠 공유 메모리
바이트코드(컴파일된 PHP 코드)
PHP-FPM의 모든 워커가 함께 사용 · 사이트가 여럿이어도 한 공유 메모리
OPcache가 없으면 PHP 스크립트는 요청이 올 때마다 파일 읽기, 바이트코드 컴파일, 실행의 세 단계를 거칩니다.
OPcache가 없으면 같은 파일의 두 번째 요청도 파일 읽기, 바이트코드 컴파일, 실행의 세 단계를 다시 거칩니다.
OPcache가 동작하면 첫 요청은 세 단계를 거친 뒤 바이트코드를 공유 메모리에 저장합니다.
같은 파일의 두 번째 요청부터 앞의 두 단계가 빠지고 실행만 남으며, 공유 메모리는 PHP-FPM의 모든 워커가 함께 사용합니다.

OPcache가 저장하는 대상은 컴파일된 PHP 코드라, 페이지를 열 때마다 PHP 실행과 데이터베이스 조회는 그대로 일어납니다. 완성된 HTML을 저장해 PHP 실행 자체를 건너뛰는 것은 페이지 캐시의 역할입니다.

2️⃣ PHP OPcache 설치 확인

OPcache가 설치되어 있는지는 [php -v] 출력의 마지막 줄에서 확인합니다.

php -v
PHP 8.3.22 (cli) (built: Jun  3 2025 17:17:57) (NTS gcc x86_64)
Copyright (c) The PHP Group
Zend Engine v4.3.22, Copyright (c) Zend Technologies
    with Zend OPcache v8.3.22, Copyright (c), by Zend Technologies

마지막 줄이 없다면 dnf로 설치합니다. 패키지 이름은 보통 php-opcache이며, Remi 저장소로 여러 PHP 버전을 함께 설치했다면 php83-php-opcache처럼 버전이 붙습니다.

dnf -y install php-opcache

Remi 저장소의 php-opcache 패키지는 [/etc/php.d/10-opcache.ini]의 [zend_extension=opcache] 줄로 확장을 읽어 들입니다. 설치한 뒤 PHP-FPM을 다시 시작하면 웹 요청에도 OPcache가 적용됩니다.

3️⃣ OPcache 설정: php.ini 값

OPcache 설정은 [/etc/php.ini]의 [opcache] 부분과 [/etc/php.d/10-opcache.ini] 두 곳에 들어갈 수 있습니다.

php --ini
Configuration File (php.ini) Path: /etc
Loaded Configuration File:         /etc/php.ini
Scan for additional .ini files in: /etc/php.d
Additional .ini files parsed:      /etc/php.d/10-opcache.ini,

php.d 폴더의 파일은 php.ini 다음에 읽히므로, 같은 항목을 두 곳에 적으면 php.d 쪽 값이 적용됩니다.

아래 표는 PHP 8.3의 기본값과, 확인한 워드프레스 서버에 적용된 값입니다.

항목PHP 8.3 기본값적용 값뜻
opcache.enable11OPcache 사용
opcache.enable_cli01명령줄 PHP(wp-cli 등)에서도 사용
opcache.memory_consumption1281024바이트코드를 저장하는 공유 메모리(MB)
opcache.interned_strings_buffer816같은 문자열을 한 번만 저장하는 메모리(MB)
opcache.max_accelerated_files1000010000캐시할 수 있는 키 수 상한(실제 상한은 이 값 이상의 소수, 10000이면 16229)
opcache.max_wasted_percentage510메모리가 모자라고 버려진 공간이 이 비율을 넘으면 캐시를 비우고 다시 시작
opcache.validate_timestamps11파일이 바뀌었는지 확인
opcache.revalidate_freq260파일 변경 확인 주기(초)
opcache.jittracingdisableJIT 방식(PHP 8.4부터 기본값 disable)
opcache.jit_buffer_size00JIT 메모리, 0이면 JIT이 동작하지 않음(PHP 8.4부터 기본값 64M)

[/etc/php.ini]의 [opcache] 부분에 넣은 값은 아래와 같습니다. 메모리 크기는 서버 메모리에, [opcache.max_accelerated_files]는 워드프레스 파일 수에 맞춰 정합니다.

[opcache]
opcache.enable=1
opcache.enable_cli=1
opcache.memory_consumption=1024
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=10000
opcache.max_wasted_percentage=10
opcache.validate_timestamps=1
opcache.revalidate_freq=60

php.ini에 [zend_extension] 줄을 다시 넣으면 확장을 두 번 읽게 되어 [Cannot load Zend OPcache] 경고가 출력됩니다.

[opcache.revalidate_freq]가 60이면 PHP 파일을 수정한 뒤 최대 60초 동안 이전 코드가 실행될 수 있습니다.

PHP 파일이 자주 바뀌는 워드프레스 서버는 [opcache.validate_timestamps]를 1로 두어 파일 변경을 확인하게 합니다. Symfony 문서가 운영 서버에 권하는 0은 새 버전을 배포할 때만 PHP 파일이 바뀌는 서버에 맞는 값입니다.

[opcache.validate_timestamps]를 0으로 두어도 관리자 화면에서 업데이트하면 워드프레스가 바뀐 파일의 캐시를 직접 비웁니다. 그러나 wp-cli로 업데이트하거나 SSH로 파일을 수정하면 PHP-FPM을 다시 시작하기 전까지 이전 코드가 실행됩니다.

4️⃣ OPcache JIT 비활성화

PHP 8의 JIT은 CPU 연산이 많은 작업을 빠르게 하는 기능이라, 워드프레스처럼 웹 요청을 처리하는 애플리케이션에서는 효과가 작습니다. PHP JIT RFC에 실린 워드프레스 측정에서도 JIT을 활성화한 쪽은 초당 326건, 비활성화한 쪽은 315건이었습니다.

PHP 8.3.22를 사용하는 워드프레스 서버에서 [opcache.jit=tracing]과 [opcache.jit_buffer_size=128M]으로 JIT을 활성화했습니다. 사흘 뒤 요청이 몰려 PHP-FPM 워커가 여러 번 다시 시작된 날, 전 페이지에서 500 오류가 발생했습니다.

오류 기록에는 [Allowed memory size of 1073741824 bytes exhausted] 메시지가 남았습니다. 메시지 뒤에 붙은 [tried to allocate 4295229440 bytes]는 PHP 메모리 한도 1GB에서 4GB를 한 번에 할당하려 한 기록입니다. JIT을 비활성화하자 같은 요청이 정상적으로 처리되었습니다.

JIT은 [/etc/php.d/10-opcache.ini]에 아래 두 줄을 넣어 비활성화합니다. [/etc/php.ini]에 JIT 설정이 남아 있어도 이 파일의 값이 적용됩니다.

opcache.jit=disable
opcache.jit_buffer_size=0

PHP 8.3은 [opcache.jit_buffer_size] 기본값이 0이라, 따로 설정하지 않으면 JIT이 동작하지 않습니다. PHP 8.4부터는 [opcache.jit] 기본값도 disable입니다.

5️⃣ 설정 적용 및 확인

바꾼 설정은 PHP-FPM을 다시 시작해야 적용됩니다.

systemctl restart php-fpm

다시 시작하면 OPcache 공유 메모리가 비워지고, 새 설정으로 다시 할당됩니다.

php -i | grep -E '^opcache\.(enable|memory_consumption|revalidate_freq|validate_timestamps|jit) '
opcache.enable => On => On
opcache.jit => disable => disable
opcache.memory_consumption => 1024 => 1024
opcache.revalidate_freq => 60 => 60
opcache.validate_timestamps => On => On

[php -i]가 출력하는 값은 명령줄 PHP의 설정이며, RHEL 계열은 PHP-FPM도 같은 [/etc/php.ini]와 [/etc/php.d] 파일을 읽으므로 값이 같습니다.

명령줄에서 [opcache_get_status()]를 호출하면 캐시된 스크립트가 0개로 나옵니다. 명령줄 PHP는 실행할 때마다 공유 메모리를 새로 만들기 때문에, PHP-FPM의 사용량은 아래 파일을 웹 문서 폴더에 올려 브라우저로 확인합니다.

<?php
header('Content-Type: text/plain');
$s = opcache_get_status(false);
print_r($s['memory_usage']);
print_r($s['opcache_statistics']);
print_r($s['interned_strings_usage']);
var_dump($s['cache_full']);

[cache_full]이 true면 공유 메모리나 키가 다 찬 상태입니다. 확인한 뒤에는 이 파일을 바로 삭제합니다.

워드프레스 사이트 세 곳이 같은 PHP-FPM을 사용하는 서버에서는 공유 메모리 1024MB 가운데 317MB를 사용하고 있었습니다. 캐시된 스크립트는 사이트마다 3,366~4,222개, 모두 11,358개였습니다.

OPcache는 스크립트를 실제 경로로 저장하고, 상대 경로로 불러온 파일에는 작업 디렉터리를 붙인 키를 하나 더 만들기 때문에 키 수가 스크립트 수보다 많아집니다. 스크립트 11,358개에 키는 상한 16,229개가 다 찼고, 문자열 버퍼 16MB도 남은 공간이 없었습니다.

키가 다 차면 새 스크립트는 캐시되지 않고 요청마다 컴파일됩니다. 5분 21초 사이에 캐시 미스는 18,408건에서 36,027건으로 늘었지만, 캐시된 스크립트 수는 11,358개 그대로였습니다.

워드프레스를 여러 개 운영하거나 플러그인이 많은 서버는 [opcache.max_accelerated_files]를 키 상한이 차지 않도록 넉넉하게 정합니다. 20000으로 정하면 실제 키 상한은 32,531개가 됩니다. 문자열 버퍼가 다 찼다면 [opcache.interned_strings_buffer]도 함께 늘립니다.

🔢 FAQ & 추천 콘텐츠

PHP 7.2에서 제거된 설정이라, PHP 8에서는 php.ini에 남아 있어도 동작에 영향이 없습니다. 예전 설정을 옮겨 온 서버라면 이 줄은 지워도 됩니다.

OPcache는 컴파일된 PHP 코드를, Redis 오브젝트 캐시는 데이터베이스 조회 결과를 저장합니다. 저장하는 대상이 달라 함께 사용할 수 있습니다.

PHP-FPM으로 PHP를 실행하는 서버는 OPcache가 PHP-FPM 안에서 동작하므로 PHP-FPM만 다시 시작합니다. Apache 모듈(mod_php)로 PHP를 실행하는 서버라면 Apache를 다시 시작합니다.

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

답글 남기기

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

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