Docker로 운영하는 워드프레스가 느릴 때는 데이터베이스, PHP 페이지 생성, 이미지 전송을 따로 나눠서 개선해야 합니다. 이 글은 Redis Object Cache, W3 Total Cache, ShortPixel을 운영 중인 사이트에 안전하게 적용하는 순서를 정리한 실전 가이드입니다.
핵심 구조: Redis DB 0은 오브젝트 캐시, DB 1은 페이지 캐시, DB 2는 데이터베이스 캐시로 분리합니다. Redis는 외부 포트를 열지 않고 WordPress와 같은 Docker 내부 네트워크에만 연결합니다.
왜 세 단계로 나눠야 할까?
- 오브젝트 캐시: 반복해서 읽는 WordPress 옵션과 게시물 데이터를 Redis에 저장합니다.
- 페이지 캐시: PHP가 완성한 HTML을 저장해 익명 방문자 요청을 빠르게 처리합니다.
- 이미지 최적화: 원본과 썸네일 용량을 줄여 실제 다운로드 시간을 단축합니다.
| 계층 | 도구 | Redis DB |
|---|---|---|
| 오브젝트 캐시 | Redis Object Cache | 0 |
| 페이지 HTML 캐시 | W3 Total Cache | 1 |
| SQL 결과 캐시 | W3 Total Cache | 2 |
| 이미지 압축 | ShortPixel | 해당 없음 |
1. 변경 전에 현재 구성을 확인한다
운영 서버에서는 Compose 파일부터 수정하면 안 됩니다. WordPress 컨테이너명, DB 연결 방식, 네트워크, 볼륨, 기존 Redis를 먼저 확인합니다.
docker ps --no-trunc --format "table {{.Names}}\t{{.Image}}\t{{.Ports}}\t{{.Networks}}\t{{.Status}}"
docker ps -a --format "table {{.Names}}\t{{.Image}}\t{{.Ports}}\t{{.Networks}}\t{{.Status}}"
docker inspect <wordpress-container> --format '{{json .Mounts}}'
docker inspect <wordpress-container> --format '{{json .NetworkSettings.Networks}}'
/var/www/html이 named volume이면 wp-config.php도 볼륨 안에 있을 가능성이 큽니다. 다른 Redis가 있더라도 별도 Docker 네트워크이고 호스트 6379 포트를 공개하지 않았다면 전용 Redis와 충돌하지 않습니다.
2. Compose와 wp-config.php를 백업한다
Copy-Item .\compose.yml .\compose.yml.bak
docker exec --user root <wordpress-container> cp -p \
/var/www/html/wp-config.php \
/var/www/html/wp-config.php.bak
W3 Total Cache는 .htaccess와 WordPress drop-in 파일을 만들 수 있으므로 .htaccess, object-cache.php도 추가로 백업하면 복구가 쉽습니다.
3. WordPress 전용 Redis를 추가한다
redis:
image: redis:7-alpine
container_name: myblog-redis
restart: unless-stopped
command: redis-server --maxmemory 256mb --maxmemory-policy allkeys-lru
volumes:
- myblog_redis_data:/data
networks:
- internal
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5
mem_limit: 320m
Redis에는 ports를 추가하지 않습니다. WordPress와 같은 내부 네트워크의 서비스만 myblog-redis:6379로 접근하게 합니다.
docker compose config --quiet
docker compose up -d redis
docker exec myblog-redis redis-cli ping
docker exec myblog-redis redis-cli CONFIG GET maxmemory-policy
PONG과 allkeys-lru가 나오면 Redis 서버는 정상입니다.
4. W3 Total Cache를 쓸 때는 PhpRedis를 확인한다
Redis Object Cache는 자체 Predis 클라이언트로 연결될 수 있지만, W3 Total Cache의 Redis 엔진은 WordPress PHP에 PhpRedis 확장이 있어야 정상 인식되는 경우가 있습니다. 공식 WordPress 이미지를 기반으로 사용자 이미지를 만드는 방법이 재현성이 좋습니다.
FROM wordpress:6.8.2-php8.3-apache
RUN set -eux; \
apt-get update; \
apt-get install -y --no-install-recommends $PHPIZE_DEPS; \
pecl install redis-6.3.0; \
docker-php-ext-enable redis; \
apt-get purge -y --auto-remove \
-o APT::AutoRemove::RecommendsImportant=false $PHPIZE_DEPS; \
rm -rf /var/lib/apt/lists/*
버전은 적용 시점의 안정 버전을 확인해 고정합니다. 빌드 후에는 WordPress 데이터 볼륨을 유지한 채 애플리케이션 컨테이너만 재생성합니다.
docker compose build wordpress
docker compose up -d --no-deps wordpress
docker exec <wordpress-container> php -m
5. Redis Object Cache를 연결한다
define('WP_REDIS_HOST', 'myblog-redis');
define('WP_REDIS_PORT', 6379);
define('WP_REDIS_DATABASE', 0);
define('WP_CACHE', true);
이 상수는 wp-settings.php를 불러오기 전에 있어야 합니다. Docker의 WORDPRESS_CONFIG_EXTRA에도 같은 설정을 남기되, 기존 wp-config.php가 있으면 실제 파일이 자동 갱신되지 않을 수 있으므로 반드시 직접 확인합니다.
wp plugin install redis-cache --activate
wp redis enable
wp redis status
Status: Connected, Drop-in: Valid, Ping: PONG이 나오면 오브젝트 캐시가 연결된 것입니다.
6. W3 Total Cache의 Page·Database Cache를 Redis로 설정한다
wp plugin install w3-total-cache --activate
- Page Cache: Redis, 서버
myblog-redis:6379, DB ID 1 - Database Cache: Redis, 서버
myblog-redis:6379, DB ID 2 - W3TC Object Cache: 끔
- HTTPS 페이지 캐시: 켬
W3TC Object Cache는 끄는 것이 중요합니다. 이미 Redis Object Cache 플러그인이 object-cache.php를 관리하고 있기 때문입니다.
wp w3-total-cache fix_environment apache
wp w3-total-cache flush all
wp-content/advanced-cache.php, wp-content/db.php, wp-content/object-cache.php가 존재하는지 확인합니다.
7. Redis에 실제 키가 생기는지 검증한다
docker exec myblog-redis redis-cli INFO keyspace
docker exec myblog-redis redis-cli -n 0 DBSIZE
docker exec myblog-redis redis-cli -n 1 DBSIZE
docker exec myblog-redis redis-cli -n 2 DBSIZE
Page Cache는 첫 익명 페이지 요청 후 DB 1에 키가 생겨야 합니다. Database Cache는 기존 Page Cache가 요청을 먼저 처리하면 DB까지 내려가지 않으므로 REST API 같은 페이지 캐시 우회 요청으로 검사합니다.
curl -H "Host: example.com" \
-H "X-Forwarded-Proto: https" \
"http://127.0.0.1:8080/wp-json/wp/v2/posts?per_page=1&_fields=id"
docker exec myblog-redis redis-cli -n 2 DBSIZE
8. ShortPixel로 이미지를 최적화한다
wp plugin install shortpixel-image-optimiser --activate
관리자 화면의 설정 → ShortPixel에서 API 키를 입력합니다. 일반 블로그는 Lossy, 원본 백업 켬, 썸네일 최적화 켬으로 시작하는 것이 무난합니다. ShortPixel CDN과 WebP·AVIF는 중요하지 않은 이미지 한 장으로 먼저 시험한 뒤 활성화하는 편이 안전합니다.
WordPress는 원본 이미지 하나에서 여러 썸네일을 만듭니다. 원본, 각 썸네일, WebP, AVIF가 각각 크레딧을 사용할 수 있으므로 미디어 → Bulk ShortPixel을 누르기 전에 예상 사용량을 확인해야 합니다.
문제가 생겼을 때 확인할 순서
docker compose ps에서 모든 서비스가 healthy인지 확인합니다.redis-cli ping이 PONG인지 확인합니다.php -m에서 redis 확장이 로드됐는지 확인합니다.wp redis status의 Connected, Valid, PONG을 확인합니다.- W3TC의
advanced-cache.php와db.php를 확인합니다. - DB 1·2에 실제 Redis 키가 생성되는지 확인합니다.
- HTTP 200 응답과 500 오류 여부를 확인합니다.
마지막 체크리스트
- Compose와 wp-config.php 백업
- 기존 Redis·포트·네트워크 충돌 조사
- Redis 외부 포트 미공개
- Object/Page/Database Cache의 DB ID 분리
- PhpRedis 로드 확인
- ShortPixel API 키 비공개
- 모든 컨테이너 running/healthy
- 사이트 HTTP 200 및 500 오류 없음
공식 참고 자료
문서 확인일: 2026년 7월 30일. 플러그인과 이미지 버전은 적용 시점의 공식 문서를 다시 확인하세요.

