2026년 8월 기준 WordPress 실행 환경

새 서버에서 홈페이지가 정상적으로 열린다고 해서 WordPress 이전이 끝난 것은 아닙니다. 그 상태는 대개 파일과 데이터베이스가 새 환경에서도 읽힌다는 첫 번째 확인에 가깝습니다. 안전한 이전은 이전 직전까지 생성된 데이터가 모두 반영됐는지, 실제 트래픽이 새 환경으로 들어오는지, TLS와 메일, Cron, 캐시, 외부 연동이 새 환경에서 동작하는지, 문제가 생겼을 때 어느 시점까지 어떻게 되돌릴지를 검증해야 끝납니다. 마지막에는 기존 환경의 쓰기를 막고 백업과 자격증명, DNS, 방화벽, 모니터링까지 정리합니다.

그래서 WordPress 이전은 파일 복사와 DB Import가 아니라 Preflight, Rehearsal, Cutover, Validation, Decommission 다섯 단계로 관리하는 편이 안전합니다.

WordPress 최신판은 7.1입니다. 공식 Release Archive의 7.1 Branch에는 아직 7.1만 올라와 있어 이 시점에는 7.1 계열 유지보수 릴리스가 확인되지 않습니다.[7]

WordPress Hosting Handbook은 PHP 8.4 이상을 운영 환경에 권합니다. PHP 8.5도 WordPress 6.9 이상에서 지원한다고 설명합니다. PHP 8.2와 8.3은 PHP Project에서 Security Support 단계이며 8.4와 8.5는 Active Support 상태입니다.[2]

DB에서는 문서 사이의 기준을 갈라야 합니다. WordPress Requirements의 MySQL 8.0 이상은 넓은 호환 기준이지만 MySQL 8.0의 EOL 날짜는 이미 2026년 4월을 지났습니다.[8] MariaDB 10.6 역시 Hosting Handbook에 적힌 EOL 날짜가 2026년 7월 6일입니다. 신규 환경은 현재 지원 중인 LTS 계열을 고르되, WordPress Core가 지원한다는 사실을 Plugin이나 Custom Query까지 자동으로 호환된다는 뜻으로 읽어서는 안 됩니다.[2]

WordPress Core
현재 공식 상태: 최신판 7.1 / 새 이전 대상에 적용할 기준: 최신판이라는 이유만으로 이전과 동시에 올리지 않는다
PHP 공개 권장
현재 공식 상태: 8.3 이상 / 새 이전 대상에 적용할 기준: 최소선이 아니라 현대적 권장 기준
PHP 운영 권장
현재 공식 상태: Hosting Handbook은 8.4 이상 권장 / 새 이전 대상에 적용할 기준: 전체 Plugin·Theme·Custom Code 검증 후 8.4를 기본 후보로 삼는다
PHP Core 최소
현재 공식 상태: WordPress 7.1은 PHP 7.4 이상 / 새 이전 대상에 적용할 기준: 실행 가능 하한일 뿐 신규 운영 환경의 목표 버전으로 보지 않는다
PHP 8.5
현재 공식 상태: WordPress Core 7.1이 지원하며 PHP Project의 Active Support 상태 / 새 이전 대상에 적용할 기준: 전체 확장 코드와 PHP Extension 검증을 통과했을 때 선택
DB 공개 권장
현재 공식 상태: MariaDB 10.11 이상 또는 MySQL 8.0 이상 / 새 이전 대상에 적용할 기준: DB 제품의 현재 지원 수명까지 함께 확인한다
DB Legacy 하한
현재 공식 상태: MySQL 5.5.5 이상에서 실행 가능 / 새 이전 대상에 적용할 기준: EOL이므로 신규 대상에 쓰지 않는다
현재 LTS 후보
현재 공식 상태: MySQL 8.4, MariaDB 10.11·11.4·11.8 / 새 이전 대상에 적용할 기준: Plugin·Custom Query·문자셋·Collation·SQL Mode 테스트 후 결정
HTTPS
현재 공식 상태: WordPress Requirements의 기본 조건 / 새 이전 대상에 적용할 기준: 인증서 발급뿐 아니라 Redirect·Proxy Header·Callback URL까지 검증

Core 업그레이드와 인프라 이전을 한 번에 하지 않는 이유

서버와 OS 변경, PHP 8.1에서 8.5로의 변경, MySQL 8.0에서 8.4로의 변경, WordPress 7.0에서 7.1로의 변경, Plugin과 Theme 동시 업데이트를 하나의 Cutover에 묶는 경우를 생각해 봅니다. 오류가 나면 원인이 서버 구성인지 PHP 호환성인지 DB 동작 차이인지 Core 변경인지 Plugin 업데이트인지 가리기 어렵습니다. 더 큰 문제는 일부 업데이트가 DB 구조나 저장 데이터를 바꾼 뒤에는 기존 환경으로 트래픽만 되돌리는 방식이 안전한 롤백이 아니라는 점입니다.

WordPress 7.1 Field Guide도 일부 내장 라이브러리 변경이 이를 쓰는 Plugin의 동작이나 스타일에 영향을 주므로 테스트가 필요하다고 설명합니다. WordPress Core의 PHP 호환성 표는 Core 범위의 판단이며 설치된 Plugin과 Theme, MU Plugin, Custom Code의 호환성까지 말해 주지는 않습니다.[9]

안전한 기본 순서는 셋입니다. 기존 WordPress·Plugin·Theme 버전을 놓고 새 인프라를 먼저 Rehearsal합니다. 인프라 이전을 마치고 Observation Window를 통과합니다. Core와 PHP, DB 또는 Plugin 업그레이드는 별도 변경으로 수행합니다.

기존 PHP나 DB가 새 환경에서 제공되지 않아 변경이 불가피하다면, 이를 단순 서버 이전이 아니라 인프라 이전과 런타임 업그레이드가 결합된 변경으로 적습니다. 환경별 Acceptance Criteria와 Rollback Trigger도 각각 나눕니다.

서비스 작동 방식

의존 관계를 확인하고 전환을 검증함께 움직여야 할 시스템을 묶고 리허설과 되돌릴 조건을 갖춘 뒤 실제 전환을 수행합니다.

Bulk Copy → Final Sync → Traffic Cutover

전환은 세 동작으로 나뉩니다. Bulk Copy는 파일과 Uploads, DB를 새 환경으로 처음 복사합니다. 이 상태의 새 환경은 Rehearsal 대상입니다. 외부 메일과 결제, Webhook, Cron은 차단하거나 테스트 모드로 둡니다. 그동안 기존 환경에서는 실제 변경이 계속 일어납니다.

다음이 Write Freeze입니다. 관리자와 폼, 댓글, REST API, 결제 Callback, Cron, Queue의 쓰기를 통제한 뒤 Final Sync로 최종 DB와 Uploads Delta, 그 밖의 가변 파일을 옮깁니다. 이 상태의 새 환경이 Cutover Candidate이며 여기서 Smoke Test와 데이터 정합성을 확인합니다.

마지막이 Traffic Cutover입니다. DNS나 Reverse Proxy, Load Balancer를 바꿔 새 환경이 읽기와 쓰기를 받고, 기존 환경은 Write Blocked에 Cron·Queue Disabled 상태로 둡니다. Observation Window를 통과한 뒤에야 기존 환경을 Decommission합니다.

Bulk Copy 이후 기존 사이트에서 주문과 회원, 댓글, 파일 업로드가 계속 발생했다면 처음 복사한 데이터는 Cutover 시점의 최신 상태가 아닙니다. Final Sync 없이 트래픽만 바꾸면 “접속은 되지만 최근 데이터가 사라진 사이트”가 됩니다.

Master Migration Checklist

아래 다섯 단계가 이 글의 본문입니다. Preflight는 무엇을 옮기는지 확정합니다. Rehearsal은 전환을 한 번 끝까지 수행하고 Cutover는 최신 데이터와 실제 트래픽을 함께 옮깁니다. Validation은 화면이 아니라 기능과 운영 증거로 승인합니다. Decommission은 기존 서버를 끄는 일까지 이전 작업으로 다룹니다.

각 단계의 표는 실제 값을 채워 쓰는 템플릿입니다. 항목마다 Owner와 Evidence를 남겨야 다음 사람이 같은 판단을 되풀이하지 않습니다.

1. Preflight — 무엇을 옮기는지 먼저 확정한다

Preflight의 목적은 서버 정보를 모으는 데 그치지 않습니다. 어떤 상태가 복사 대상인지, 무엇이 외부 시스템에 남아 있는지, Cutover 전후 어느 환경이 정본인지 정하는 단계입니다.

Environment Compatibility Matrix는 실제 값을 채워 쓰는 템플릿입니다. MATCH는 단순 일치, TEST_REQUIRED는 Rehearsal 필요, BLOCK은 Cutover 전에 해결해야 함을 뜻합니다. 기존 환경과 새 환경의 값을 나란히 적고 판정을 남깁니다.

WordPress Hosting Handbook은 json과 mysqli를 필수 PHP Extension으로 설명합니다. 원격 요청과 미디어, 문자 처리, TLS, 압축 등에 필요한 여러 Extension은 따로 권합니다. PHP 버전이 같다는 것만으로 서버 환경이 같다고 판단하지 못하는 이유입니다.[2]

Preflight Checklist의 23개 항목을 아래에서 각각 확인합니다. 완료 표시와 해당 Evidence를 함께 남깁니다.

환경·Plugin·Theme·Custom Code에 이어 쓰기 경로, Uploads, Cache, Cron과 Queue를 확인합니다.

메일·외부 연동·DNS·TLS·Proxy·보안 규칙·복원 가능성을 확인하고 정본과 전환 승인 조건을 확정합니다. 각 항목의 기록 양식은 체크리스트에 연결했습니다.

정본은 한 문장으로 정합니다. 시점마다 어디가 정본인지 아래처럼 적어 둡니다. WordPress DB만 정본이라고 쓰면 모자랍니다. Uploads가 파일시스템에 있고 결제 결과가 외부 PG에 있으며 메일 상태가 발송 사업자에 있다면, 이전 대상은 이미 여러 시스템에 흩어져 있습니다.

□ Preflight 1 / Scope 문서
이전 범위가 인프라 변경인지, URL 변경인지, Core·PHP·DB Upgrade까지 포함하는지 구분
□ Preflight 2 / Environment Matrix
WordPress·PHP·DB 버전과 PHP Extension을 기록
□ Preflight 3 / Plugin Inventory
활성·비활성 Plugin 전체와 버전·요구 PHP·Custom Table을 기록
□ Preflight 4 / Theme Inventory
Parent·Child Theme, Custom Template, 빌드 산출물을 기록
□ Preflight 5 / MU Plugin·Drop-in 목록
mu-plugins , object-cache.php , advanced-cache.php , 기타 Drop-in을 확인
□ Preflight 6 / Custom Code Register
functions.php , Snippet, 별도 PHP 파일, 배포 스크립트 등 Custom Code를 확인
□ Preflight 7 / Network Map
Multisite 여부, 사이트 수, Domain Mapping, Subdomain/Subdirectory 구조를 확인
□ Preflight 8 / Writer Inventory
WooCommerce·예약·회원·댓글·폼 등 Write-heavy 기능을 분류
□ Preflight 9 / Uploads Inventory
wp-content/uploads 와 별도 Upload 경로·외부 저장소·최근 변경량을 측정
□ Preflight 10 / Cache Map
Page Cache의 위치와 Bypass Route를 확인
□ Preflight 11 / Object Cache Map
Object Cache의 Prefix·DB·Drop-in·공유 여부를 확인
□ Preflight 12 / CDN Configuration
CDN의 Origin·Cache Rule·Purge 경로를 확인
□ Preflight 13 / Cron Inventory
WP-Cron인지 System Cron인지, 어느 서버에서 무엇을 실행하는지 확인
□ Preflight 14 / Queue Snapshot
Plugin Queue·Pending·Failed 작업과 Worker 위치를 확인
□ Preflight 15 / Mail Flow Map
SMTP·Mail API·발신 도메인·인증·반송 확인 경로를 기록
□ Preflight 16 / Integration Register
Form, Webhook, Payment Callback, 외부 API의 Endpoint와 Secret을 확인
□ Preflight 17 / DNS Export
DNS Record, 현재 TTL, Proxy 여부, 권한 보유자를 확인
□ Preflight 18 / Certificate Inventory
모든 Hostname의 TLS 인증서와 갱신 책임을 확인
□ Preflight 19 / Proxy Contract
Reverse Proxy가 전달하는 Host·Scheme·Client IP Header를 확인
□ Preflight 20 / Security Rule Export
WAF·접근 통제 규칙 중 Admin·REST·Webhook에 영향을 주는 항목을 확인
□ Preflight 21 / Restore Evidence
DB·파일·설정 Backup이 있고 실제 Restore 가능한지 확인
□ Preflight 22 / Source-of-Truth Table
DB, Uploads, 외부 거래 데이터별 Source of Truth를 선언
□ Preflight 23 / Cutover Runbook
Acceptance Criteria, Rollback Trigger, 승인자와 연락 경로를 확정
Rehearsal 중
WordPress DB와 Uploads의 정본은 기존 환경입니다. Cron·Queue는 기존 환경만 실행하고 외부 결제와 메일은 실제 시스템을 씁니다.
Write Freeze 후 Final Sync 중
DB와 Uploads의 정본은 여전히 기존 환경이되 쓰기가 멈춘 상태입니다. Cron·Queue는 중지하거나 Drain하고 수신 중인 Callback은 따로 통제합니다.
Cutover Candidate
DB와 Uploads의 정본 후보가 새 환경으로 넘어옵니다. Cron·Queue는 아직 실행을 미루고 외부 연동은 테스트 요청만 허용합니다.
Acceptance 통과 후
DB와 Uploads의 정본이 새 환경으로 바뀝니다. Cron·Queue도 새 환경만 실행하고 새 Endpoint와 정합성을 확인합니다.
Observation Window
정본과 실행 모두 새 환경에 있고, 외부 시스템과 지속적으로 대조합니다.
Layer
반드시 비교할 항목
Pass Evidence
WordPress Core버전, 자동 업데이트 정책, Core 수정 여부Version·Checksum·변경 기록
PHP버전, SAPI, FPM 설정, Memory·Timeoutphpinfo 또는 구성 Export, 기능 테스트
PHP Extensionsjson, mysqli, curl, mbstring, intl, openssl, xml, zip, 이미지 처리 모듈Extension 목록과 Upload·Remote Request 테스트
DatabaseMySQL·MariaDB 종류와 버전, Charset, Collation, SQL Mode, Timezone, Packet SizeImport Log, 주요 Query, 문자·정렬 검증
Web ServerNginx·Apache, Rewrite, Upload Limit, 압축, 정적 파일 처리Permalink·Admin·REST·대용량 Upload 테스트
Plugin활성·비활성 목록, 버전, PHP·Core 요구사항, License, Custom Table기능별 Acceptance Test
ThemeParent·Child Theme, 버전, 빌드 파일, Template Override주요 Template·반응형·관리 화면 검증
MU Plugin파일 목록, 로딩 순서, 환경별 조건초기 Bootstrap과 관리자 기능 테스트
Custom CodeTheme Functions, Drop-in, Snippet, 별도 App·API코드 목록과 Critical Flow 테스트
MultisiteSubdomain·Subdirectory, Network Table, Domain Mapping, Cookie·Upload PathNetwork Admin과 사이트별 테스트
Uploads·Storage경로, 소유자, 권한, 외부 Object Storage, Generated File개수·용량·최근 파일·썸네일 검증
Object CacheRedis·Memcached, DB 번호, Prefix, Serializer, Drop-inCache Flush 후 Read·Write·Session 테스트
Page Cache·CDNCache Key, Bypass Route, Purge, OriginHIT·MISS와 Admin 제외, Purge 확인
WP-Cron·System Cron호출 방식, 주기, 사용자, DISABLE_WP_CRON이벤트 목록과 실행 로그
QueueWorker 위치, Pending·Failed 작업, RetryQueue 상태와 중복 실행 부재
MailSMTP·API 방식, From Domain, 인증, Bounce·Log실제 수신과 Provider Log
Webhook·CallbackEndpoint, Secret, IP 제한, Retry, Idempotency고유 Test ID와 수신 Log
DNS·TLS·Proxy·WAFRecord, TTL, Certificate, Origin, Forwarded Header, Rule외부와 Origin 양쪽 테스트
MonitoringUptime, PHP Error, Web Log, DB, Disk, Queue, AlertDashboard와 Alert Route 검증
Environment Compatibility Matrix — MATCH는 단순 일치, TEST_REQUIRED는 Rehearsal 필요, BLOCK은 Cutover 전 해결

2. Rehearsal — 실제 전환 전에 한 번 끝까지 수행한다

Rehearsal은 새 서버에서 홈 화면을 띄우는 테스트가 아닙니다. Cutover와 같은 순서로 복사와 Import, 설정, 검증을 수행하고 걸리는 시간과 실패 지점을 적는 작업입니다.

운영 도메인이 그대로 유지된다면, 테스트를 위해 DB 전체 URL을 임시 도메인으로 바꾸기보다 승인된 테스트 장비에서 Hosts Override나 임시 Proxy Routing을 쓰는 편이 불필요한 DB 변경을 줄입니다. 임시 Hostname을 써야 한다면 검색엔진 차단뿐 아니라 실제 메일과 결제, Webhook, Cron이 실행되지 않도록 따로 막습니다.

URL이 바뀌는 경우를 봅니다. WordPress의 Option과 Widget, Theme 설정, Plugin 데이터에는 PHP Serialized Data가 들어갑니다. 직렬화된 문자열에는 값의 길이가 함께 저장되므로, 길이가 다른 URL을 Raw SQL의 전역 REPLACE()로 바꾸면 데이터가 깨집니다. WordPress 공식 Migration 문서는 이를 경고합니다. WP-CLI의 search-replace는 Serialized Data를 알아보고 처리한다고 설명합니다.[1]

안전한 기본 절차는 새 환경의 복사본에서 먼저 Dry Run을 수행하는 것입니다. wp search-replace에 옛 주소와 새 주소를 주고 --skip-columns=guid와 --dry-run을 붙여 변경 대상과 건수만 확인합니다. 결과와 DB Backup을 검토한 뒤에만 같은 명령에서 --dry-run을 뺍니다. Plugin이 WordPress에 등록되지 않은 Custom Table을 쓴다면 테이블을 먼저 확인한 뒤 --all-tables-with-prefix 사용 여부를 정합니다. Multisite 전체를 대상으로 할 때는 --network가 필요하지만 이것만으로 Network 구조 검토가 끝나지는 않습니다. WP-CLI 기본 동작은 현재 사이트에 등록된 테이블을 대상으로 하며 --network와 --all-tables-with-prefix는 범위를 넓히는 옵션입니다.[3]

guid는 URL처럼 보여도 바꾸지 않습니다. WordPress는 이를 Post의 지속적인 식별자로 쓰며 Domain이 바뀌어도 그대로 두도록 공식 문서에서 밝힙니다. guid를 바꾸면 Feed Reader가 기존 글을 새 글로 인식하는 문제가 생깁니다.[1]

Dry Run 성공도 최종 증거는 아닙니다. 변경 후에는 메뉴와 Block·Widget 설정, CSS의 배경 이미지, 미디어 URL, SEO Metadata, Plugin Custom Table과 Redirect를 실제 화면과 DB에서 확인해야 합니다.

Staging 또는 Temporary Host를 운영 트래픽과 분리
Pass Criteria: 일반 사용자가 접근하지 않고 검색 색인과 실제 외부 Side Effect가 차단됨
실제 목표 PHP·DB·Web Server로 실행
Pass Criteria: Fatal Error와 Deprecated 폭증 없이 Critical Flow 동작
파일 소유자와 권한 복원
Pass Criteria: WordPress가 필요한 디렉터리에만 쓰고 과도한 전역 쓰기 권한이 없음
DB Export·Import 수행
Pass Criteria: Import Error가 없고 주요 Table·Entity 수가 예상 범위와 일치
URL 변경 Dry Run과 적용
Pass Criteria: Serialized Data가 유지되고 guid가 바뀌지 않음
Permalink·Rewrite 구성
Pass Criteria: 글·페이지·REST API·Admin 경로가 정상 응답
Upload 생성과 썸네일 처리
Pass Criteria: 원본과 파생 이미지가 생성되고 공개 URL에서 읽힘
Plugin·Theme·MU Plugin·Custom Code 실행
Pass Criteria: Critical Flow별 Acceptance Criteria 통과
메일·Webhook·결제는 테스트 모드로 검증
Pass Criteria: 운영 사용자나 실제 거래에 Side Effect가 없음
Bulk Copy와 Final Sync 예상 시간 측정
Pass Criteria: 계획한 Maintenance Window 안에 수행 가능
Rollback Rehearsal
Pass Criteria: Traffic Reversal과 기존 환경 재활성화 절차가 문서대로 가능
Rollback Trigger 확정
Pass Criteria: 누가 어떤 증거로 언제 중단할지 분명함

3. Cutover — 최신 데이터와 실제 트래픽을 함께 옮긴다

Cutover는 열두 단계로 진행합니다. Bulk Copy 확인에서 시작해 Write Freeze와 Cron·Queue 통제, Final DB Sync와 Final Upload Sync, 설정 최종 적용, Smoke Test를 거쳐 트래픽을 전환합니다. 이어 TLS와 캐시를 확인한 뒤 새 환경의 쓰기를 엽니다.

Write Freeze는 관리자 공지만으로 끝나지 않습니다. WordPress의 쓰기 경로는 /wp-admin/에만 있지 않습니다. 댓글과 회원 가입, 문의·예약·설문 Form, REST API, admin-ajax.php, 결제·배송·CRM Callback이 쓰기 경로입니다. 예약 발행과 WP-Cron, Plugin Queue와 재시도 Worker, 외부 프로그램의 Application Password와 API 요청이 모두 쓰기 경로입니다. 관리자 화면에 Maintenance 안내를 띄웠어도 Webhook과 Cron이 계속 돌면 Final DB Sync 이후 데이터가 다시 달라집니다. Write-heavy 사이트에서는 쓰기 주체를 모두 멈추거나, 멈추지 못하는 쓰기를 별도 원장으로 적어 재조정합니다.

짧은 Write Freeze조차 허용되지 않는 사이트라면 이 Runbook의 단순 Final Dump 방식만으로는 모자랍니다. Replication이나 변경 데이터 추적, Callback 재처리와 정합성 대조를 포함한 별도의 Online Migration 설계가 필요합니다.

DNS TTL은 완료 시각을 정해 주지 않습니다. TTL을 미리 낮추면 기존 Cache가 만료된 뒤 새 Record를 더 빨리 조회하게 만듭니다. 그러나 이미 조회한 Resolver의 TTL은 남은 시간 동안 계속 줄고, 일부 Resolver는 장애 회피를 위해 만료된 데이터를 일시적으로 내놓기도 합니다. 따라서 “TTL을 300초로 낮췄으므로 5분 뒤 전 세계가 새 서버를 본다”는 식으로 Cutover 시간을 약속해서는 안 됩니다.[6][10] 전환 후에는 여러 Resolver와 네트워크에서 결과를 확인합니다. 요청이 어느 Backend에 닿았는지는 서버 로그나 테스트용 Deployment Marker로 가립니다. Marker에는 Origin IP나 내부 Hostname 같은 민감한 정보를 넣지 않습니다.

TLS와 Proxy, WAF에서는 일곱 가지를 봅니다. 모든 실제 Hostname이 인증서에 들어갔는지 확인합니다. Edge와 Origin 사이 TLS도 정상인지 확인합니다. HTTP에서 HTTPS로 가는 Redirect가 Loop를 만들지 않는지 확인합니다. Reverse Proxy가 원래 Host와 HTTPS Scheme을 WordPress에 올바르게 전달하는지 확인합니다. 새 Origin IP·Port·Health Check가 반영됐는지 확인합니다. WAF가 Login과 Admin, REST API, Webhook, Payment Callback을 잘못 막지 않는지 확인합니다. 기존 Origin으로 직접 접속해 쓰기를 만들지 못하는지입니다.

순서
작업
완료 조건
1Bulk Copy 완료 상태 확인새 환경에 기준 시점의 DB와 파일이 존재
2변경 공지와 Write Freeze 시작관리자·사용자·API·Callback의 쓰기 경로가 통제됨
3기존 환경 Cron·Queue 통제Final Sync 중 새 데이터나 외부 Side Effect가 생기지 않음
4Final DB SyncFreeze 기준 시점까지의 DB가 새 환경에 반영됨
5Final Upload SyncBulk Copy 이후 추가·변경·삭제된 파일이 반영됨
6URL과 환경 설정 최종 적용운영 URL·DB·Secret·Proxy 설정이 목표값과 일치
7Cutover Candidate Smoke TestLogin·Read·Write·Upload 등에 차단 조건이 없음
8DNS·Proxy·Load Balancer 전환외부 요청이 새 환경으로 들어옴
9TLS 확인인증서·Chain·Redirect·Forwarded Scheme 정상
10Page Cache·Object Cache·CDN 무효화이전 응답, 이전 Origin, 오래된 객체가 제거됨
11새 환경 Write Open새 환경만 정본으로 쓰기 시작
12기존 환경 Write Block 유지우회 접속으로 새 데이터가 생기지 않음
Cutover 순서 — 열두 단계와 각 단계의 완료 조건

4. Validation — 화면이 아니라 기능과 운영 증거로 승인한다

검증은 “담당자가 둘러봤는데 괜찮았다”로 끝내지 않습니다. 항목별 Owner와 Pass Criteria를 미리 정합니다. 그리고 요청 ID와 로그, 수신 결과처럼 다시 확인되는 Evidence를 남깁니다.

WP-Cron과 System Cron은 다른 것입니다. WP-Cron은 전통적인 System Cron처럼 계속 도는 Scheduler가 아닙니다. 기본 동작에서는 Page Load가 발생할 때 예정된 작업이 있는지 검사합니다. 트래픽이 없으면 정해진 시각보다 늦게 실행됩니다.[11] System Cron으로 wp-cron.php나 WP-CLI를 정기적으로 호출하도록 구성한 사이트에서는 Page Load 기반 호출을 DISABLE_WP_CRON으로 끄기도 합니다. 이전할 때는 WordPress 안에 예정된 Event가 그대로 있는지와, 새 서버의 OS Scheduler가 실제로 WordPress Cron을 호출하는지를 각각 확인합니다. wp cron test는 WP-Cron Spawn 동작을 검사하는 도구입니다. System Cron을 쓰는 구성에서는 OS Scheduler의 실행 로그와 실제 Event 완료 기록까지 따로 확인합니다. 기존 서버와 새 서버가 동시에 Cron을 실행하면 메일과 구독, 예약, 재고 동기화가 중복 처리됩니다.[4]

메일 함수 성공과 수신 성공은 다릅니다. WordPress의 wp_mail()이 true를 반환해도 수신자가 메일을 받았다는 뜻이 아닙니다. 공식 함수 문서도 그 값은 사용된 전송 방식이 요청을 오류 없이 처리했다는 뜻일 뿐이라고 밝힙니다.[5] 메일 검증에는 여섯 가지 Evidence가 필요합니다. WordPress나 Plugin이 발송 요청을 생성했는가. SMTP·Mail API Provider가 요청을 받아들였는가. 발신 도메인과 인증이 정상인가. 실제 Test Mailbox에 도착했는가. Spam·Bounce·Block 여부는 어떤가. 비밀번호 재설정과 주문, Form 등 Template별로 확인했는가입니다. PHP의 mail() 호출이나 wp_mail() 반환값만 보고 Pass를 주지 않습니다.

Site Health가 모두 Green이어도 전체 Acceptance는 아닙니다. Site Health는 WordPress와 Plugin, Theme, Server, DB, Filesystem Permission 등 구성 정보와 알려진 문제를 확인하는 데 유용합니다. Upload 비활성화, Loopback 실패, 오래된 PHP, HTTP Request 차단 같은 문제도 잡습니다.[12] 그러나 주문 결제와 실제 메일 수신, 외부 Webhook, Analytics, 최신 데이터 정합성, DNS 전환과 롤백 가능성을 대신 검증하지는 않습니다. 따라서 Site Health가 모두 Green이라는 사실은 Migration Acceptance의 한 항목이지 전체 증거가 아닙니다.

검증 대상
기본 Owner
Pass Criteria
HomeWordPress Owner운영 도메인에서 기대한 Home이 열리고 새 Backend로 처리됨
ReadContent Owner대표 글·페이지·검색·분류·미디어가 정상이며 최근 콘텐츠가 존재
AdminWordPress OwnerDashboard 진입, 메뉴, Editor, Plugin 관리 화면에 오류와 Redirect Loop 없음
LoginApp Owner로그인·로그아웃·비밀번호 재설정과 권한별 접근이 정상
SessionApp Owner연속 요청에서 Session이 유지되고 이전 환경과 잘못 공유되지 않음
WriteContent Owner테스트 글과 설정 변경이 새 DB에 저장되고 Front에 반영
UploadContent Owner파일 업로드·썸네일 생성·조회·삭제가 정상
FormBusiness Owner제출 데이터가 저장되고 후속 처리 상태까지 확인
EmailMail Owner요청 처리뿐 아니라 실제 수신, Provider Log, 반송 여부까지 확인
WebhookIntegration Owner고유 Test ID가 서명 검증을 통과해 한 번만 처리됨
PaymentCommerce Owner승인된 Test·Sandbox Flow에서 Callback과 주문 상태가 일치
WP-CronWordPress Owner예정 이벤트가 정해진 호출 방식으로 실행되고 중복 실행되지 않음
System CronInfrastructure Owner지정 사용자·주기·명령으로 실행되며 새 환경만 호출
QueueApp OwnerPending과 Failed가 예상 범위이고 Old·New Worker가 동시에 실행되지 않음
Object CacheApp OwnerFlush 후 정상 재생성되고 다른 환경과 Key가 충돌하지 않음
Page CacheWeb Owner동적 경로가 Bypass되고 공개 페이지의 HIT·MISS가 의도와 일치
CDNWeb Owner새 Origin을 쓰며 Purge 후 이전 콘텐츠가 남지 않음
RedirectSEO·Web OwnerHTTP·WWW·이전 URL의 목적지가 맞고 Chain과 Loop가 없음
대표 URLSEO Owner공개 URL만 대표 주소로 출력되고 Temporary Host가 남지 않음
robotsSEO Owner운영 정책과 일치하며 Staging용 전체 차단이 남지 않음
SitemapSEO Owner운영 URL을 쓰고 주요 콘텐츠가 포함되며 정상 응답
AnalyticsAnalytics OwnerPage View와 주요 Event가 수집되고 Tag가 중복 실행되지 않음
LogsOperations OwnerPHP Fatal·DB Error·Permission Error·5xx가 비정상으로 늘지 않음
MonitoringOperations OwnerUptime·Latency·Error·Disk·DB·Queue 감시가 새 환경을 대상으로 동작
Site HealthWordPress OwnerMigration 관련 Critical Issue가 없고 환경 정보가 Matrix와 일치
Business AcceptanceBusiness Approver핵심 업무 여정이 모두 Pass하고 미해결 위험이 승인 범위 안에 있음
Validation / Owner / Pass Criteria — 스물여섯 항목의 승인 기준
서비스 작동 방식

관측에서 복구와 개선까지 이어지는 운영서비스 지표와 경보를 기준으로 대응하고 변경 이력과 사후 보고를 다음 개선에 연결합니다.

5. Decommission — 기존 서버를 끄는 것도 이전 작업이다

새 환경이 정상이라고 판단한 직후 기존 서버를 지우면 안 됩니다. 반대로 기존 환경을 무기한 살려 두는 것도 안전하지 않습니다. 오래된 Server와 Plugin, Credential, Firewall Rule이 관리되지 않은 채 남아 새로운 공격면과 운영 혼선을 만들기 때문입니다.

Observation Window의 길이를 모든 사이트에 똑같이 적용하지 못합니다. 최소한 핵심 예약 작업의 한 주기, 실제 또는 승인된 합성 Write Flow, 메일과 Webhook, 결제 Callback, Cache 만료와 재생성, 운영 시간대의 실제 트래픽, Backup과 Monitoring의 정기 실행을 실제로 관측하는 기간이어야 합니다. 매월 한 번 실행되는 Critical Job이 있다면 이틀간 홈페이지가 정상이라는 이유만으로 그 작업을 검증했다고 보지 못합니다.

Observation Window 운영
종료 조건: 미해결 Critical Issue가 없고 종료 기준을 채움
기존 환경 Write Block
종료 조건: 우회 Domain·IP·관리 경로에서도 새 데이터가 생기지 않음
기존 Cron·Queue 중지
종료 조건: 외부 Side Effect와 중복 작업이 생기지 않음
기존 환경 최종 Backup
종료 조건: DB·파일·설정의 Restore 가능한 사본과 식별자 보존
Backup Retention 확정
종료 조건: 법적·계약·운영 정책에 맞는 삭제일과 Owner 지정
Credential Rotation
종료 조건: 기존 서버가 갖고 있던 DB·SMTP·API·Webhook Secret을 필요 범위에서 교체
DNS Cleanup
종료 조건: Old Record, Temporary Host, 검증용 Entry 제거
TLS Cleanup
종료 조건: 쓰지 않는 Certificate·Challenge·갱신 작업 정리
Firewall·Allowlist Cleanup
종료 조건: 기존 IP·Port·관리 접근 허용 제거
Monitoring Cleanup
종료 조건: 중복 Alert 제거, 필요한 Historical Data 보존
Backup·Security Agent Cleanup
종료 조건: 불필요한 비용·권한·중복 작업 제거
Shutdown Approval
종료 조건: Business·Application·Infrastructure Owner의 승인 기록
Server Termination
종료 조건: 종료 시각, 자산 ID, 최종 증거 기록
사후 문서 갱신
종료 조건: Runbook·Architecture·Credential Owner·Asset Registry 최신화

WordPress-specific Rollback Contract

Rollback Contract는 “문제가 생기면 DNS를 원래대로 바꾼다”는 문장이 아닙니다. WordPress에서는 DB와 Uploads, Cron, Queue, Form, 주문, 메일, Callback이 동시에 상태를 바꾸므로 어느 시점까지 단순 복귀가 가능한지 먼저 정해야 합니다.

새 환경이 아직 실제 쓰기를 받지 않았다면 대체로 기존 환경으로 트래픽을 되돌리고 Write Block을 해제하는 절차가 가능합니다. 이 단계가 가장 단순한 Rollback Window입니다.

새 환경에서 쓰기가 시작된 뒤에는 주문과 결제 상태, 회원·로그인·비밀번호 변경, 댓글·게시물·예약, 업로드 파일, Form 제출, Webhook 처리 결과, Cron·Queue가 만든 변경, 외부로 발송된 메일이 새 환경에 생겨 있습니다. 이 상태에서 트래픽만 기존 서버로 돌리면 새 환경에서 생긴 데이터가 사용자에게 사라져 보이거나, 같은 Callback과 Queue가 두 번 처리됩니다.

따라서 넷 가운데 하나가 필요합니다. 새 쓰기를 기존 환경에 안전하게 재반영하거나, 외부 원장과 양쪽 DB를 대조해 수동으로 조정하거나, 기존 환경으로 되돌리는 대신 새 환경에서 Forward Fix를 하거나, 위험이 풀릴 때까지 새 쓰기를 다시 잠그고 제한 운영을 하는 것입니다. 어느 방법이 가능한지는 Cutover 전에 정합니다. Rollback 시점에 처음 논의하면 이미 데이터가 갈라진 뒤입니다.

코드와 설정, DB, 트래픽을 아우르는 일반적인 Rollback Architecture는 별도 문서가 다룹니다. 이 글은 그 원칙을 WordPress의 DB·Uploads·Cron·Plugin·외부 Callback 상황에 적용한 실행 계약에 집중합니다.

Field
기록할 내용
Rollback Authority복귀를 승인할 역할과 대리인
Decision DeadlineCutover 후 단순 복귀 판단이 가능한 마지막 시각
Old Environment ModeWrite Blocked, Cron·Queue Disabled
Source of Truth Before Freeze기존 DB와 Uploads
Source of Truth After Acceptance새 DB와 Uploads
Traffic Reversal MethodDNS·Proxy·Load Balancer별 실행 순서
Restore PointFinal Sync 직전과 직후 Backup 식별자
Rollback TriggerLogin·Write·Payment·Data Integrity·Error 등 구체 조건
New-write Detection새 환경에 생긴 Post·User·Order·Upload·Form·Queue 목록
External Reconciliation결제·Webhook·메일·CRM 상태 대조 방법
Cache ActionObject·Page·CDN Cache 무효화 순서
Cron·Queue Authority어느 환경을 언제 다시 활성화할지
Evidence Owner로그·DB 비교·요청 ID를 모을 담당자
Business Approval데이터 손실과 중복 처리 위험을 승인할 역할
Closure CriteriaRollback 완료와 운영 정상화를 판정할 조건
Rollback Contract Template — Cutover 전에 채우는 열다섯 칸

사이트 유형별 추가 항목

기본 체크리스트 위에 유형별로 더할 항목이 있습니다. 여섯 갈래로 나눠 봅니다.

WordPress 공식 Migration 문서도 Multisite는 DB 여러 곳에 서버명과 경로가 있어 단일 사이트보다 복잡하다고 설명합니다. wp_site와 wp_blogs, 사이트별 Options, SUBDOMAIN_INSTALL 같은 설정은 따로 검토해야 합니다.[1]

일반 콘텐츠 사이트
기본 체크리스트에 추가할 것: 댓글·회원 가입·Form이 실제로 쓰기를 만드는지 확인, 예약 발행과 Sitemap 갱신, 최근 Uploads Delta
Write-heavy 사이트
기본 체크리스트에 추가할 것: Write Freeze 대상 API 전체, 주문·예약·재고·구독 원장, Payment Callback Retry와 Idempotency, Queue Drain, Final Entity Count, Cutover 이후 신규 Write 추적
WooCommerce
기본 체크리스트에 추가할 것: 주문·결제·환불·재고·쿠폰·메일·Webhook·Scheduled Action을 각각 검증하고 외부 PG 원장과 상태 대조
Membership·LMS
기본 체크리스트에 추가할 것: 로그인 Session, 권한·수강 상태·진도·구독 갱신·비밀번호 메일·Background Job 검증
Multisite
기본 체크리스트에 추가할 것: wp_site, wp_blogs, 각 사이트의 Options, Domain Mapping, Network-activated Plugin, Upload Path, Wildcard DNS·TLS, Cookie Domain, Network Admin 검증
Multisite URL 변경
기본 체크리스트에 추가할 것: WP-CLI --network 범위 확인, 각 사이트의 home·siteurl과 Upload 설정, Network Table 수동 검토, Subdomain·Subdirectory 전환 여부 확인

Observation Log Template

Observation Log에는 Credential과 개인 데이터, 전체 결제 정보를 옮겨 적지 않습니다. 필요하면 식별 가능한 최소 Request ID나 내부 Evidence ID만 남깁니다. 한 줄에 하나의 관측을 적고 Timestamp와 Observer, Test ID, Observed 값, 결과, Action과 Owner를 함께 채웁니다.

Observation Window를 닫을 때는 최소한 관측 시작과 종료 시각, 관측한 핵심 여정과 예약 작업, 메일 수신 확인, Webhook과 결제 대조 결과, 기존 환경에서 감지된 쓰기 여부, 미해결 사건, 롤백 산출물 검증 여부, 종료 승인자를 적습니다.

Cutover
기능·이벤트: Login / 처리 Backend: New / Expected: 로그인과 Session 유지 / Evidence: Log ID
Validation
기능·이벤트: Upload / 처리 Backend: New / Expected: 원본과 썸네일 생성 / Evidence: Screenshot 또는 Log
Validation
기능·이벤트: Mail / 처리 Backend: New / Expected: 실제 수신 / Evidence: Provider Message ID
Observation
기능·이벤트: Cron·Queue / 처리 Backend: New / Expected: 정시 단일 실행 / Evidence: Event 또는 Job ID
Observation
기능·이벤트: Error Review / 처리 Backend: New / Expected: 기준 대비 비정상 증가 없음 / Evidence: Dashboard

이전 완료의 기준

“새 서버에서 사이트가 잘 보인다”는 것은 Validation의 첫 행에 가깝습니다. 안전하게 Migration이 끝났다고 말하려면 여섯 질문에 모두 답해야 합니다. 최종 데이터는 어느 환경에 있는가. 기존 환경과 새 환경에서 동시에 쓰기가 일어나지 않았는가. 사용자와 관리자, 외부 시스템의 실제 기능이 통과했는가. 메일과 Cron, Queue, Cache, Webhook이 새 환경에서만 동작하는가. 장애가 나면 어느 시점까지 어떻게 되돌리는가. 기존 서버와 Credential을 언제 어떤 승인으로 없애는가입니다.

먼저 이 글의 Master Migration Checklist를 실제 Runbook으로 옮겨 Owner와 Evidence를 채웁니다. 일반적인 롤백 설계와 백업·복원 가능성은 각각 별도 문서가 다루며, 이전 후 WordPress 운영 책임의 배분도 별도 운영 문서로 관리합니다.