DISABLE_WP_CRON = true 설정은 wp-cron.php 엔드포인트를 차단하지 않습니다. 단지 WordPress가 자체 루프백(loopback) 요청을 보내는 것을 중단할 뿐입니다. 파일은 여전히 웹에서 접근 가능하므로, 누구나 해당 파일에 접속하여 전체 WordPress 부트스트랩(bootstrap)을 강제로 실행할 수 있습니다.
이 숨겨진 진입점은 특히 트래픽이 많은 사이트에서 CPU, 메모리 및 PHP 워커(worker)를 낭비할 수 있습니다. 만약 문을 잠갔다고 생각했다면, 아직은 아닙니다.
이 설정이 자주 오해받는 이유
WordPress가 예약된 작업을 실행할 때, 먼저 자체 wp-cron.php 파일에 대해 빠른 HTTP 요청을 시도합니다. DISABLE_WP_CRON을 true로 설정하면 코어(core)에 해당 내부 요청을 건너뛰도록 지시합니다. 하지만 코어는 웹 서버 설정을 변경하거나 wp-cron.php에 인증 레이어를 추가하지 않습니다. 스크립트는 여전히 공개 URL로 남아 있으며, PHP 프로세스가 조기에 중단되더라도 200 상태 코드를 반환합니다.
URL을 발견한 공격자가 이를 반복적으로 핑(ping)하면, WordPress는 매번 모든 플러그인, 테마 및 데이터베이스를 로드하게 됩니다. 공유 호스팅이나 PHP 워커가 제한적인 사이트의 경우, 이 단일 엔드포인트가 서비스 거부(DoS) 공격 벡터가 될 수 있습니다.
실제로 수행해야 할 작업
예약된 작업을 시스템 수준의 스케줄러(cron, systemd-timer 등)로 옮기고 공개된 문을 닫으려면 다음 다섯 단계를 따르십시오.
1. 내부 루프백 비활성화
wp-config.php에 다음 줄을 추가합니다.
define( 'DISABLE_WP_CRON', true );
이 작업은 WordPress가 자체 HTTP 요청을 시도하는 것은 막아주지만, 외부 호출을 막지는 못합니다.
2. 웹 서버에서 wp-cron.php 차단
예를 들어 Nginx를 사용하는 경우, 403 Forbidden을 반환하는 location 블록을 삽입합니다.
location = /wp-cron.php {
return 403;
}
이제 서버는 PHP가 시작되기도 전에 요청을 거부하므로 부트스트랩 비용을 제거할 수 있습니다.
3. 안전장치로 mu-plugin 추가
wp-cron.php에 도달하는 모든 요청을 기록하고 403으로 종료하는 must-use 플러그인(wp-content/mu-plugins에 위치)을 생성합니다. 이는 다른 호스트 이름이나 CDN 에지 규칙 등을 통해 서버 규칙을 우회하는 요청을 잡아냅니다.
4. Action Scheduler 비동기 호출 억제
많은 플러그인이 Action Scheduler 라이브러리를 사용하며, 이는 자체적인 루프백 요청을 생성할 수 있습니다. action_scheduler_queue_runner에 훅(hook)을 걸어 CLI가 아닌 요청에 대해 조기에 반환(return early)함으로써, 라이브러리가 자체적인 통로를 열려고 시도하는 것을 방지하십시오.
5. WP-Cron 훅에서 큐 러너(queue runner) 연결 해제
wp cron 훅에 연결된 기본 Action Scheduler 큐 러너를 제거합니다. 이를 통해 명령줄(command line)에서 명시적으로 실행할 때만 큐가 작동하도록 보장할 수 있습니다.
올바른 작업 실행 방법
공개 엔드포인트를 차단한 후에는 시스템 스케줄러를 사용하여 WP-CLI를 통해 1분마다(또는 필요한 주기마다) WordPress를 호출하십시오.
wp cron event run --due-now
이 단일 명령은 제어된 환경에서 코어 cron 이벤트와 Action Scheduler 큐를 모두 처리하며, 다른 CLI 작업에서 사용하는 것과 동일한 PHP 프로세스를 사용합니다.
측정 가능한 이점
- 보안 – 인증되지 않은 사용자가 무거운 백그라운드 작업을 시작할 수 없습니다.
- 성능 – PHP 워커를 실제 방문자를 위해 사용할 수 있으며, 잘못된 cron 호출로 인한 메모리 급증이 사라집니다.
- 신뢰성 – 스케줄링이 선제적으로 이루어집니다. 방문자의 페이지 로드가 아닌 시스템 cron에 의해 구동되므로 작업이 정확히 언제 실행되는지 알 수 있습니다.
변경 후 주의 깊게 살펴볼 사항
wp-cron.php의 HTTP 상태 코드에 의존하지 마십시오. PHP에 의해 차단되더라도 여전히 200을 반환할 수 있습니다. 대신 다음을 확인하십시오.
- Action Scheduler 큐 크기를 모니터링하십시오. 큐가 계속 커진다면 작업 실행이 누락되었음을 의미할 수 있습니다.
- wp-cron.php location 블록에서 발생하는 "403" 로그 항목을 서버 로그에서 확인하십시오.
- 트래픽 피크 시간대에 PHP-FPM 또는 FastCGI 프로세스 수를 관찰하여 부하가 감소했는지 확인하십시오.
주의 사항
일부 관리자는 트래픽이 적은 사이트에서 자연스럽게 cron이 트리거되도록 하기 위해 DISABLE_WP_CRON을 false로 유지합니다. 위의 방식은 그러한 의존성을 완전히 제거하지만, 유지 관리 단계가 추가됩니다. 즉, 시스템 스케줄러가 안정적으로 실행되는지 반드시 확인해야 합니다. 서버의 cron 데몬이 실패하면 예약된 작업도 중단됩니다. 이러한 함정을 피하려면 설정을 완료한 후 시스템 cron 서비스에 대한 모니터링을 병행하십시오.
요약: DISABLE_WP_CRON을 true로 설정하는 것은 WordPress가 자체적으로 핑을 보내는 것만 막을 뿐, 공개된 wp-cron.php 엔드포인트를 닫지는 않습니다. 웹 서버에서 파일을 차단하고, mu-plugin 폴백(fallback)을 추가하며, 모든 예약된 작업을 WP-CLI를 통해 시스템 스케줄러로 라우팅하십시오. 이렇게 하면 사이트 보안을 강화하고, 불필요한 PHP 작업을 줄이며, 백그라운드 작업의 실행 시점을 정밀하게 제어할 수 있습니다.
