NeedU V1 → V2 5차 Production 마이그레이션 결과 보고서 - 100-hours-a-week/KTB4-4th-wiki GitHub Wiki
NeedU V1 → V2 5차 Production 마이그레이션 결과 보고서
1. 개요
1.1 목적
2026년 10월 19일 진행한 5차 Production 마이그레이션에서는 V1 EC2 환경에서 V2 ECS/RDS 환경으로 데이터베이스 및 서비스 트래픽을 이전하는 절차를 검증했다.
이번 리허설의 주요 목적은 다음과 같다.
- MySQL DMS Full Load 및 CDC 동기화 검증
- PostgreSQL 데이터 이전 및 정합성 검증
- Production ECS 및 ALB Target Health 확인
- DNS Pre-switch 및 Preflight 자동화 검증
- GitHub Actions 기반 Cutover 실행
- Write Gate 활성화 시간 측정
- k6 조회 부하 테스트 및 HTTP 오류 분석
- V1/V2 JWT 인증 호환성 확인
1.2 마이그레이션 환경
| 항목 | 내용 |
|---|---|
| 수행 일자 | 2026-10-19 |
| 대상 | V1 → V2 Production |
| V1 | EC2 + Nginx + Docker Compose |
| V1 DB | EC2 MySQL / PostgreSQL |
| V2 | ALB + ECS Frontend/Backend/AI |
| V2 DB | RDS MySQL / PostgreSQL |
| MySQL 이전 | AWS DMS Full Load + CDC |
| PostgreSQL 이전 | pg_dump / pg_restore |
| 대상 도메인 | needu.gift |
| 트래픽 전환 | ALB Listener Rule |
| 쓰기 제한 | ALB Write Gate |
| 자동화 | GitHub Actions |
| 부하 테스트 | k6 |
| 모니터링 | Grafana, CloudWatch |
1.3 주요 결과
| 검증 항목 | 결과 | 판정 |
|---|---|---|
| Production Grafana | 10:10 KST 구성 완료 | PASS |
| DMS Full Load | 10:17:10~10:18:30 | PASS |
| DMS Validation | 정상 보고 | PASS |
| DMS CDC | 지연 약 0~4초 | 최종 정합성 확인 필요 |
| ECS Runtime Control | 10:19:30~10:21:30 | PASS |
| ECS FE/BE/AI | 각각 Running 2개 | PASS |
| ALB FE/BE Target | 각각 Healthy 2개 | PASS |
| DNS Pre-switch | 10:23:20~10:24:10 | 완료 |
| Preflight | 1분 2초(62초) | PASS |
| Cutover 단계 | 3분 12초(192초) | SUCCESS |
| Preflight + Cutover 전체 | 4분 21초(261초) | SUCCESS |
| Write Gate ON | 11:25:45 | 확인 |
| Write Gate OFF | 11:27:54 | 확인 |
| Write Freeze | 2분 9초(129초) | 확인 |
| JWT 인증 | V1/V2 서명 키 불일치 | FAIL |
| HTTP 401 | 인증 실패 발생 | 확인 |
| MySQL 최종 RPO 0 | 최종 증빙 부족 | 미확정 |
| PostgreSQL 최종 정합성 | 최종 증빙 부족 | 미확정 |
2. Production 마이그레이션 타임라인
2.1 실행 기록
모든 시각은 2026-10-19 KST 기준이다.
| 시각 | 단계 | 작업 및 결과 |
|---|---|---|
| 09:56 | 사전 준비 | Production 마이그레이션 절차 공유 |
| 09:57 | Grafana | Production 대시보드 미구성 확인 |
| 10:10 | Grafana | Production 대시보드 구성 완료 |
| 10:11 | CI/CD | Backend Production CD 실행 안내 |
| 10:17:10 | DMS | Full Load + CDC 시작 |
| 10:18:30 | DMS | Full Load 100%, Validation 정상 |
| 10:19:30 | ECS | Prod Runtime Control 시작 |
| 10:21:30 | ECS | Runtime Control 성공 |
| 10:21:30 이후 | ECS/ALB | Running 2/2 및 Target Health 정상 |
| 10:23:20 | DNS | Production DNS Pre-switch 시작 |
| 10:24:10 | DNS | Production DNS Pre-switch 완료 |
| 약 10:44 | 모니터링 | ALB 요청률 및 k6 지표 관측 |
| 약 10:46 | ALB | HTTP RPS 약 1.8 |
| 약 10:52 | ALB | Target 4xx 관측 |
| 약 10:58 | ALB | ALB 4xx 관측 |
| 11:23:40 | 자동화 | Preflight + Cutover 재시작 보고 |
| 11:25:45 | Write Gate | Gate ON |
| 11:27:54 | Write Gate | Gate OFF |
| 정확한 시각 미확인 | 자동화 | Preflight + Cutover SUCCESS |
| 정확한 시각 미확인 | 인증 | JWT 서명 키 불일치로 HTTP 401 발생 |
2.2 단계별 소요 시간
| 단계 | 소요 시간 |
|---|---|
| DMS Full Load | 1분 20초 |
| ECS Runtime Control | 2분 |
| DNS Pre-switch | 50초 |
| Preflight | 1분 2초(62초) |
| Cutover 단계 | 3분 12초(192초) |
| Preflight + Cutover 전체 | 4분 21초(261초) |
| Write Freeze | 2분 9초(129초) |
2.3 GitHub Actions 전체 실행 시간
GitHub Actions에서 확인한 실행 기록은 다음과 같다.
Oct 19, 11:23 AM GMT+9
4m 21s
4분 21초는 Preflight와 Cutover를 포함한 전체 자동화 실행 시간이다.
Preflight = 62초
Cutover 단계 = 192초
단계별 소요 시간 합계 = 254초
전체 실행 시간 = 261초
차이 = 7초
전체 실행 시간과 개별 단계의 소요 시간 합계 사이에 7초 차이가 있다.
해당 차이는 단계 간 전환 및 실행 오버헤드 등이 원인일 수 있으나, 정확한 원인은 GitHub Actions 로그를 통해 확인해야 한다.
2.4 Write Freeze 계산
GitHub Actions Cutover 결과:
Result: success
Gate ON: 2026-10-19T02:25:45Z
Gate OFF: 2026-10-19T02:27:54Z
KST 변환 결과:
Gate ON = 2026-10-19 11:25:45 KST
Gate OFF = 2026-10-19 11:27:54 KST
Write Freeze = 129초
= 2분 9초
2.5 실행 시간 비교
| 구분 | 소요 시간 | 의미 |
|---|---|---|
| 전체 실행 시간 | 261초 | Preflight + Cutover |
| Preflight | 62초 | 사전 조건 검증 |
| Cutover | 192초 | 실제 전환 단계 |
| Write Freeze | 129초 | 쓰기 요청 제한 구간 |
Write Freeze는 Cutover 단계 192초 중 129초를 차지한다.
129 / 192 × 100 = 약 67.2%
따라서 Cutover 단계의 약 67.2% 동안 Write Gate가 활성화됐다.
전체 자동화 실행 시간 261초 중 Write Gate 활성화 비율은 약 49.4%다.
Write Freeze는 쓰기 요청이 제한된 구간이므로 전체 서비스 중단 시간과 동일하지 않다.
3. MySQL 마이그레이션 검증
3.1 DMS Full Load 및 CDC
V1 EC2 MySQL에서 V2 Production RDS MySQL로 데이터를 이전하기 위해 AWS DMS를 사용했다.
| 항목 | 결과 |
|---|---|
| Source | V1 EC2 MySQL |
| Target | V2 Production RDS MySQL |
| 이전 방식 | Full Load + CDC |
| 시작 | 10:17:10 KST |
| Full Load 완료 | 10:18:30 KST |
| 소요 시간 | 1분 20초 |
| 완료율 | 100% |
| Validation | 정상 보고 |
| CDC 지연 | 약 0~4초 |
| 최종 정합성 | 추가 검증 필요 |
3.2 DMS CDC 분석
Grafana에서 DMS Source 및 Target Latency를 확인했다.
- Source Latency: 약 0~4초
- Target Latency: 약 0~4초
- 지속적인 복제 지연 누적은 관측되지 않음
다만 CDC Latency가 0초로 감소하더라도 전체 데이터 정합성이나 RPO 0을 보장하지는 않는다.
3.3 DMS 중지 및 복구 정책
Production Cutover 자동화에는 다음 정책이 적용돼 있다.
DMS is never restarted automatically after it has been stopped.
DMS 중지 이후 Cutover 오류가 발생하더라도 복제를 자동 재시작하지 않는다.
따라서 ALB를 V1으로 복원하는 것과 DMS CDC를 재개하는 것은 별도 복구 절차로 구분해야 한다.
3.4 검증 결과
- DMS Full Load: PASS
- DMS Validation: 정상 보고
- CDC 지연: 관측 완료
- 최종 데이터 정합성: 미확정
- RPO 0: 미확정
4. PostgreSQL 마이그레이션 검증
4.1 이전 방식
PostgreSQL은 MySQL과 달리 pg_dump 및 pg_restore를 이용해 데이터를 이전하도록 설계했다.
검증 대상은 다음과 같다.
- 임베딩 모델 메타데이터
- 상품 Catalog 데이터
- 상품 문서 및 임베딩
- Catalog 동기화 기록
- pgvector 확장
- 벡터 인덱스
4.2 검증 결과
Production Preflight에서 PostgreSQL 데이터 및 인덱스에 대한 사전 검증을 수행했다.
그러나 이번 5차 Cutover 이후 최종 데이터 행 수, PK 및 해시 비교 결과는 별도 증빙이 필요하다.
따라서 사전 검증 성공과 최종 데이터 정합성 확보를 구분해야 한다.
4.3 검증 판정
- PostgreSQL 사전 검증: PASS
- Cutover 이후 최종 데이터 정합성: 미확정
- PostgreSQL RPO 0: 미확정
5. Preflight 및 Cutover 자동화 검증
5.1 Production Preflight
Preflight는 Cutover 이전 인프라 및 데이터 상태를 검증했다.
주요 검증 항목은 다음과 같다.
- DNS 및 ALB 라우팅
- ECS Running Task
- ALB Target Health
- RDS 상태
- DMS Full Load 및 Validation
- MySQL 데이터 사전 검증
- PostgreSQL 데이터 사전 검증
- Write Gate 비활성 상태
| 항목 | 결과 |
|---|---|
| Workflow 단계 | Production Preflight |
| 실행 시간 | 62초 |
| Result | PASS |
5.2 Production Cutover
| 항목 | 결과 |
|---|---|
| Workflow 단계 | Production Cutover |
| 실행 시간 | 192초 |
| Result | SUCCESS |
| Gate ON | 11:25:45 KST |
| Gate OFF | 11:27:54 KST |
| Write Freeze | 129초 |
5.3 전체 자동화 실행 결과
| 항목 | 결과 |
|---|---|
| 실행 시작 표시 | 2026-10-19 11:23 AM KST |
| 전체 실행 시간 | 261초 |
| 포함 단계 | Preflight + Cutover |
| 최종 결과 | SUCCESS |
5.4 자동 복구 정책
Failure before Gate release automatically restores ALB V1 and removes the Gate.
DMS is never restarted automatically after it has been stopped.
Gate 해제 전 실패 시 ALB를 V1으로 복원하고 Gate를 제거하도록 설계했다.
다만 DMS 중지 이후에는 복제를 자동 재개하지 않는다.
이번 5차에서는 자동화가 SUCCESS로 종료됐으므로 실제 실패 상황에서의 자동 복구 동작은 검증하지 않았다.
6. k6 조회 부하 테스트
6.1 테스트 목적
Cutover 전후 조회 API의 가용성과 응답시간을 확인한다.
주요 측정 지표는 다음과 같다.
- HTTP 요청 성공률
- HTTP 실패율
- 인증 오류 발생 여부
- HTTP p95 응답시간
- Cutover 전후 요청 처리 연속성
6.2 관측 결과
| 지표 | 결과 |
|---|---|
| HTTP Success Rate | 100% 표시 시계열 존재 |
| HTTP Failure Rate | 일부 실패 시계열 존재 |
| HTTP p95 | 시계열 관측 |
| 인증 오류 Label | error_code="1401" |
| 전체 성공률 | 미확정 |
Success Rate 패널과 Failure Rate 패널에서 서로 다른 결과가 나타났다.
이는 Label 필터 또는 집계 기준 차이일 가능성이 있다.
특정 실패 시계열이 100%로 표시됐다는 사실만으로 전체 요청이 실패했다고 판단할 수는 없다.
6.3 검증 결과
- k6 메트릭 수집: 확인
- 인증 실패 관련 시계열: 확인
- 전체 HTTP 성공률: 추가 검증 필요
- Cutover 중 조회 가용성: 최종 판정 보류
7. Production ALB 트래픽 및 오류 분석
7.1 HTTP Request Rate
| 시각 | 관측 결과 |
|---|---|
| 10:10~10:42 | 대부분 약 0 RPS |
| 10:43경 | 요청률 증가 시작 |
| 10:44경 | 약 1 RPS |
| 10:46경 | 최대 약 1.8 RPS |
| 10:47~11:00 | 대체로 약 1 RPS |
Production ALB를 통한 요청 유입을 확인했다.
다만 해당 관측 구간은 실제 Cutover 시각과 다르므로 Cutover 순간의 요청률을 직접 나타내지는 않는다.
7.2 HTTP 4xx
| 시각 | 지표 | 관측값 |
|---|---|---|
| 10:52경 | Target 4xx | 약 1 |
| 10:58경 | ALB 4xx | 약 2 |
| 11:00경 | ALB 4xx | 약 1 |
5차 마이그레이션에서는 V1/V2 JWT 서명 키 불일치로 HTTP 401 오류가 발생했다.
다만 Grafana의 4xx 지표는 여러 상태 코드를 함께 집계하므로 관측된 모든 4xx를 JWT 오류로 단정할 수 없다.
7.3 HTTP 5xx
- 10:14~10:18경 ALB 5xx 일부 관측
- 10:50경 이후 ALB 5xx 일부 관측
- Target 5xx는 별도 시계열에서 확인되지 않음
일부 오류는 DMS 및 ECS Runtime 기동 이전에 발생했다.
따라서 JWT 인증 실패와 직접적인 인과관계는 확인되지 않았다.
7.4 Target Response Time p95
| 시각 | p95 |
|---|---|
| 10:23~10:42 | 약 2~6ms |
| 10:43경 | 약 53ms |
| 10:46경 | 약 45ms |
| 10:47~11:00 | 약 10~20ms |
일시적으로 약 53ms까지 상승한 이후 대체로 10~20ms 수준으로 관측됐다.
ALB Target Response Time은 클라이언트 전체 응답시간과 다르므로 k6 HTTP p95와 구분해야 한다.
8. ECS 및 ALB Target Health 분석
8.1 ECS Running Task
| 서비스 | Running |
|---|---|
| Frontend | 2 |
| Backend | 2 |
| AI | 2 |
8.2 ALB Target Health
| 서비스 | Healthy Host |
|---|---|
| Frontend | 2 |
| Backend | 2 |
FE/BE/AI ECS Task 및 ALB Target Health는 정상 상태로 확인됐다.
그러나 인프라 Health가 정상이어도 JWT 인증 오류가 발생할 수 있다는 한계를 확인했다.
따라서 ECS 및 ALB Health Check와 별도로 실제 사용자 인증 검증이 필요하다.
9. 발견된 문제 및 원인 분석
9.1 V1/V2 JWT 서명 키 불일치
9.1.1 현상
5차 Production 마이그레이션에서 HTTP 401 Unauthorized 오류가 발생했다.
V1에서 발급한 JWT를 V2 Backend에서 검증하는 과정에서 인증 실패가 발생했다.
9.1.2 원인
V1과 V2 Production 환경에 설정된 JWT 서명 키가 서로 달랐다.
따라서 기존 V1 토큰을 V2 Backend에서 정상적으로 검증하지 못했다.
9.1.3 영향
- 기존 사용자 인증 실패
- k6 조회 API 결과에 영향 가능
- Cutover 이후 사용자 인증 연속성 저하
- 인프라 Health Check로 탐지하기 어려운 기능적 장애 발생
9.1.4 개선 방향
- Cutover 이전 V1/V2 JWT 서명 키 호환성 확인
- 기존 V1 JWT를 이용한 V2 인증 테스트
- Production Preflight에 인증 검증 추가
- Parameter Store 설정 일치 여부 확인
- 로그인 및 인증 API Smoke Test 자동화
JWT Secret 원문은 보고서 및 로그에 노출하지 않는다.
9.2 k6 메트릭 집계 기준 불일치
Success Rate와 Failure Rate 패널에 서로 다른 결과가 나타났다.
향후 전체 요청 기준 성공률과 API별 실패율을 구분해 집계해야 한다.
9.3 Cutover 자동 복구 미검증
자동 복구 정책은 존재하지만 실제 실패 상황에서 정상 동작하는지는 확인하지 않았다.
향후 Fault Injection을 통해 다음 항목을 검증해야 한다.
- Gate ON 이후 실패
- DMS 중지 이후 실패
- ALB 전환 실패
- Gate OFF 실패
- V1 복원 이후 데이터 정합성
10. 한계 및 미검증 항목
10.1 JWT 복구 완료 시각
JWT 서명 키 불일치 원인은 확인됐으나 설정 수정 시각과 복구 완료 시각은 확보되지 않았다.
10.2 Cutover 중 서비스 가용성
전체 k6 요청 기준 성공률 및 실패율이 확정되지 않았다.
10.3 데이터 정합성
DMS Full Load 및 Preflight는 통과했으나 최종 MySQL RPO 0과 PostgreSQL 전체 데이터 정합성은 추가 검증이 필요하다.
10.4 최종 ALB 라우팅
Cutover 자동화는 SUCCESS였으나 최종 Listener Rule의 V1 0% / V2 100% 상태는 별도 증빙이 필요하다.
10.5 Write Freeze 중 사용자 영향
129초 동안 차단된 쓰기 요청 수와 재시도 결과는 확보되지 않았다.
10.6 자동 복구
실제 장애 주입을 통한 자동 복구 검증은 수행되지 않았다.
11. 향후 개선 사항
| 개선 항목 | 적용 방향 |
|---|---|
| JWT 호환성 | V1/V2 서명 키 및 인증 검증 정책 확인 |
| Preflight | 기존 JWT를 이용한 V2 인증 테스트 추가 |
| Smoke Test | 로그인·조회·쓰기 API 검증 강화 |
| ALB 4xx | HTTP 상태 코드별 원인 분석 |
| ALB 5xx | ALB/Target 오류 분리 |
| k6 | 전체 요청 기준 성공률·실패율 집계 |
| Cutover | Preflight와 Cutover 단계별 시간 기록 |
| Write Freeze | Gate ON/OFF 구간 최적화 |
| DMS | 최종 CDC 및 Validation 증빙 저장 |
| PostgreSQL | 최종 데이터 정합성 검증 강화 |
| ALB | 전환 전후 Listener Rule 가중치 저장 |
| 자동 복구 | 실패 단계별 Fault Injection |
| 모니터링 | Cutover 실제 시각에 맞춘 Grafana 분석 |
12. 최종 결론
2026년 10월 19일 진행한 NeedU V1 → V2 5차 Production 마이그레이션에서는 DMS Full Load, ECS Runtime 기동, DNS Pre-switch 및 GitHub Actions 기반 마이그레이션 자동화를 수행했다.
DMS Full Load는 1분 20초 만에 완료됐으며, ECS FE/BE/AI는 각각 Running Task 2개를 유지했다.
Production Preflight는 1분 2초, Cutover 단계는 3분 12초가 소요됐다.
**Preflight와 Cutover를 포함한 전체 자동화 실행 시간은 4분 21초(261초)**였다.
Write Gate는 11:25:45 KST에 활성화되고 11:27:54 KST에 해제됐다.
따라서 **5차 Write Freeze는 2분 9초(129초)**로 확인됐다.
Cutover 단계 192초 중 129초 동안 쓰기 요청이 제한됐으며, 이는 약 67.2%에 해당한다.
그러나 V1/V2 JWT 서명 키 불일치로 HTTP 401 인증 오류가 발생했다.
이는 ECS 및 ALB Health Check가 정상이어도 사용자 인증 기능에 장애가 발생할 수 있음을 보여준다.
따라서 Production Cutover 자동화 성공 여부와 실제 서비스 기능 정상 여부를 구분해야 한다.
또한 MySQL 최종 RPO 0, PostgreSQL 데이터 정합성, k6 전체 성공률 및 최종 ALB 라우팅은 추가 검증이 필요하다.
최종 판정: Preflight + Cutover 전체 261초 / Preflight 62초 / Cutover 192초 / Write Freeze 129초 / 자동화 SUCCESS / JWT 인증 오류 발생 / 서비스 전체 가용성 및 최종 데이터 정합성 판정 보류
이번 5차 리허설을 통해 Production 마이그레이션 자동화 및 쓰기 제한 시간 측정을 검증했으며, JWT 인증 호환성과 Cutover 이후 서비스 기능 검증을 강화해야 한다는 개선 사항을 도출했다.