NeedU V1 → V2 마이그레이션 1~6차 비교 및 개선 결과 - 100-hours-a-week/KTB4-4th-wiki GitHub Wiki

목차

  1. 개요
  2. 회차별 개선 결과
  3. 최종 Production Cutover 실행 결과
  4. V1 → V2 트래픽 전환 검증
  5. Grafana 모니터링 결과
  6. 데이터 검증 결과
  7. 복구 절차
  8. 핵심 개선 성과
  9. 결론

1. 개요

2026년 10월 17일부터 19일까지 총 6차례의 마이그레이션 리허설 및 Production Cutover를 수행했다.

V1 EC2 환경에서 V2 ECS·RDS 환경으로 전환하는 과정에서 다음 항목을 순차적으로 개선했다.

  • DNS 기반 전환을 ALB Listener Rule 기반 전환으로 변경
  • Nginx Write Freeze를 ALB Write Gate로 변경
  • PostgreSQL 데이터 사전 적재
  • V2 ECS 및 ALB Target 사전 기동·검증
  • DMS 중지, 데이터 검증, ALB 전환 및 Gate 해제 자동화
  • GitHub Actions 기반 Preflight 및 Cutover Workflow 구축
  • CloudWatch, CloudTrail, ECS Container Insights 및 Grafana 기반 검증

1.1 최종 Production 결과

항목 결과
Production Preflight 20/20 PASS
Production Cutover SUCCESS
Preflight + Cutover 전체 Workflow 281초
Cutover Job 157초
일반 쓰기 Gate Rule 유지 시간 102초
인증 Callback Gate Rule 유지 시간 103초
Backend ALB 전환 15:55:04 KST
Frontend ALB 전환 15:55:06 KST
DMS Full Load 100%
DMS Validation Pending/Failed 0건
PostgreSQL Catalog 검증 PASS
1분 단위 ALB 요청 공백 0구간
V1·V2 Unhealthy Target 0개
V1·V2 Target 5xx 관측되지 않음
Target 연결 오류 관측되지 않음
ALB 연결 거부 관측되지 않음

1.2 측정 기준

용어 기준
Cutover Write Gate 생성, DMS 중지, 데이터 검증·변환, ALB 전환 및 Gate 해제를 포함한 절차
트래픽 전환 ALB Listener Rule의 Target Weight를 V1=0, V2=100으로 변경한 작업
쓰기 제한 시간 CloudTrail의 Write Gate Rule 생성부터 삭제까지의 시간
Workflow 실행 시간 GitHub Actions Run 및 Job 기록의 시작부터 종료까지의 시간
관측 구간 2026-10-19 15:48~16:01 KST

1.3 V2 설계 기준과 Cutover 방식 선정

1.3.1 V2 목표 사용자 및 트래픽

V2는 서비스 출시 약 14개월 후의 성장 규모를 다음과 같이 설정했다.

항목 V2 설계값
목표 시점 서비스 출시 약 14개월 후
MAU 약 291,900명
DAU 약 72,975명
Peak API Traffic 약 101~122 RPS
Peak Write 약 49 QPS
AI Inference Traffic 약 4.87 RPS
서비스 가용성 목표 월간 99% 이상

이에 맞춰 ECS 다중 Task, ALB, Rolling Deployment 및 Auto Scaling 구조를 설계했다. Production Cutover에서는 실제 요청 흐름, Target Health, 오류 지표와 Write Gate 시간을 확인했다.

1.3.2 평가 기준

V2의 월간 가용성 SLO는 99% 이상이다. Cutover에서는 이를 다음 운영 지표로 확인했다.

구분 기준
읽기 연속성 전환 전후 ALB 요청 유입 및 V1 → V2 처리 대상 이동
처리 용량 Healthy Target 유지 및 서비스별 Running Task 2개
오류 Target 5xx, Target 연결 오류, ALB 연결 거부
쓰기 제한 Write Gate 120초 이하
데이터 DMS Validation Pending/Failed 0건 및 DB 검증 PASS

1.3.3 SLO와 이번 Cutover 결과

30일을 720시간으로 계산하면 99% SLO의 월간 오류 예산은 다음과 같다.

720시간 × 1%
= 7.2시간
= 7시간 12분
= 25,920초

이번 Production Cutover의 AWS Rule 유지 시간은 일반 쓰기 102초, 인증 Callback 103초였다. 103초를 전체 서비스 비가용 시간으로 보수적으로 환산하면 다음과 같다.

월간 시간 기반 가용성
= (2,592,000초 - 103초) ÷ 2,592,000초 × 100
= 약 99.996%

99% 월간 오류 예산 사용률
= 103초 ÷ 25,920초 × 100
= 약 0.4%

실제 전환에서는 읽기 요청을 계속 처리하고 쓰기와 인증만 제한했다. 따라서 103초를 전체 중단으로 보는 위 계산은 실제 영향보다 보수적인 값이며, V2의 99% SLO 오류 예산 중 약 0.4%에 해당한다.

1.3.4 방식 선정과 중단 시간 개선

Application은 V1과 V2를 ALB에 함께 준비한 뒤 트래픽을 전환했고, 데이터 정합성 확보를 위해 전환 전에 짧은 Write Gate를 적용했다.

V1·V2 Target 사전 연결
→ V1 100 / V2 0
→ Write Gate ON
→ DMS 중지 및 데이터 검증
→ V1 0 / V2 100
→ V2 Target Health 확인
→ Write Gate OFF

전환 구간의 쓰기 처리 방식으로 다음 대안을 검토했다.

방식 전환 중 쓰기 처리 고려사항
Write Freeze 짧은 시간 쓰기를 503으로 차단 구현이 단순하고 데이터 기준점을 명확히 만들 수 있음
Queue 요청을 Queue에 저장하고 전환 후 V2 DB에 반영 비동기 응답, 순서·중복·재시도·DLQ 및 멱등성 처리 필요
Dual Write V1·V2 DB에 동시에 저장 한쪽만 성공할 때 데이터 불일치와 복구 처리 필요
ProxySQL Query Rule로 쓰기 DB를 V1에서 V2로 변경 라우팅 도구이며 두 DB의 동기화와 트랜잭션 정합성을 해결하지 않음
Transactional Outbox DB 변경과 Outbox Event를 같은 Transaction으로 저장한 뒤 V2에 전달 모든 쓰기 경로에 Outbox·Relay·Consumer와 중복 처리 로직 필요

Queue 방식은 Write Gate 동안 요청을 잃지 않고 전환 후 처리할 수 있지만 즉시 처리 API를 비동기 방식으로 바꿔야 한다. Amazon SQS Standard Queue는 메시지를 한 번 이상 전달할 수 있으므로 Consumer의 멱등성 처리도 필요하다.

ProxySQL은 Query Rule과 Hostgroup으로 쓰기 대상을 바꿀 수 있지만, 진행 중인 Transaction과 V1·V2 데이터 동기화는 별도로 처리해야 한다. 따라서 DMS CDC나 Dual Write를 대체하지 않는다.

Transactional Outbox는 하나의 DB 변경과 Event 발행을 원자적으로 묶는 방식이다. 이번 마이그레이션에 적용하려면 V1의 모든 쓰기 경로를 변경하고 Relay와 V2 Consumer를 새로 운영해야 하므로, 한 번의 Cutover를 위해 도입하지 않았다.

NeedU는 V2의 99% SLO와 데이터 정합성을 기준으로 DMS CDC + 120초 이내 Write Freeze를 선택했다.

동시에 쓰기 제한을 최소화하기 위해 PostgreSQL 사전 적재, V2 ECS 사전 기동, Health Check, DMS 중지, 데이터 검증, ALB 전환 및 Gate 해제를 반복적으로 개선하고 자동화했다. 그 결과 쓰기 제한 시간은 1차 최소 46분 35초에서 최종 Production 일반 쓰기 102초, 인증 Callback 103초로 단축됐다.


2. 회차별 개선 결과

2.1 전체 비교

항목 1차 2차 3차 4차 5차 6차
일자 10/17 10/17 10/18 10/18 10/19 10/19
환경 Staging Staging Staging Staging Production Production
트래픽 전환 DNS ALB ALB ALB ALB ALB
실행 방식 수동 수동 수동 자동 자동 자동
쓰기 제어 Nginx Freeze ALB Gate ALB Gate ALB Gate ALB Gate ALB Gate
사전 검증 수동 수동 Smoke 7/7 자동 검증 20/20 PASS 20/20 PASS
기록된 쓰기 제한 시간 46분 35초 이상 630초 327~349초 59초 129초 93초
Cutover Job - - - - 192초 157초
전체 Workflow - - - - 261초 281초
결과 DNS 전환 ALB 전환 절차 단축 자동화 Production 적용 Production 전환 성공

6차의 93초는 Workflow가 Gate의 HTTP 503을 확인한 시점부터 Gate OFF를 확인한 시점까지의 시간이다. CloudTrail의 AWS Rule 생성·삭제 시각으로 계산한 실제 Rule 유지 시간은 일반 쓰기 102초, 인증 Callback 103초다.

2.2 1차 → 2차: DNS에서 ALB로 전환

1차에서는 Nginx Write Freeze 이후 PostgreSQL Dump/Restore, DMS 중지, ECS 기동, Smoke Test 및 DNS 전환을 순서대로 수행했다.

단계 시각(KST)
Write Freeze ON 16:58:25
PostgreSQL 최종 Dump 완료 17:03:22
DMS 중지 17:06:20
ECS Health Check 완료 약 17:16
DNS 전환 완료 약 17:22
Smoke Test 완료 약 17:24
완료 보고 17:45

2차부터 다음 구조를 적용했다.

  • ALB Listener Rule Target Weight로 V1/V2 전환
  • ALB Write Gate로 쓰기 요청 제어
  • 트래픽 전환과 쓰기 제어 분리
  • DMS 중지와 데이터 확인 순서 정리

2차 Write Gate는 22:41:30부터 22:52:00까지 630초 유지됐다. Gate 해제 시점에 ALB V1=0/V2=100, Backend Target 2/2 Healthy, FE·BE·AI ECS 각각 2/2 Running이 확인됐다.

2.3 2차 → 3차: 수동 절차 단축

3차에서는 PostgreSQL 사전 복원, ECS 사전 기동, Target Health 확인 및 Cutover 이전 Smoke Test를 적용했다.

단계 시각(KST)
Write Gate ON 13:19:00~13:19:22
PostgreSQL 활성 트랜잭션 0 확인 13:19:22
DMS 중지 13:20:05
MySQL 활성 트랜잭션 0 확인 13:20:27
MySQL 정책 변경 완료 13:21:22
ALB 전환 완료 13:22:30
Write Gate OFF 13:24:49
HTTP 200 확인 13:26:17~13:26:23

결과:

  • Write Gate 327~349초
  • DMS 중지부터 ALB 전환 완료까지 145초
  • ALB 전환 완료부터 Gate OFF까지 139초
  • Smoke Test 7/7 PASS

2.4 3차 → 4차: GitHub Actions 자동화

4차에서는 다음 작업을 GitHub Actions로 자동화했다.

  • DMS 중지
  • 데이터 확인
  • ALB Listener Rule 변경
  • ECS 및 Target Health 확인
  • Write Gate 해제

결과:

  • Write Gate 59초
  • Cutover 전 k6 3,001회 반복에서 HTTP 실패 0건
  • Cutover 후 읽기 검증 8/8 확인

2.5 5차 Production 적용

항목 결과
Preflight 20/20 PASS
Preflight Job 62초
Cutover Job 192초
전체 Workflow 261초
Write Gate 129초

5차에서 V1/V2 JWT 서명 키 불일치로 HTTP 401이 발생했고, 이후 V2 Production JWT 설정을 V1과 일치시켰다.

2.6 6차 Production Cutover

  • Preflight 완료: 2026-10-19 15:52:28 KST

  • Preflight: 20 PASS / 0 FAIL

  • Cutover: SUCCESS

  • Cutover Job: 157초

  • 전체 Workflow: 281초

  • Workflow Gate 측정값: 93초

  • AWS Rule 기준 최대 Gate 유지 시간: 103초

  • 6차 GitHub Actions 실행 기록


3. 최종 Production Cutover 실행 결과

3.1 Preflight 검증

최종 Cutover 전에 다음 항목이 모두 통과했다.

  • DNS 및 Route53 레코드
  • ALB V1=100, V2=0
  • V1 Healthy Target
  • Write Gate Disabled
  • ECS FE·BE·AI Running Task 각각 2개 이상
  • V2 FE·BE ALB Target Healthy
  • RDS MySQL 및 PostgreSQL Available
  • DMS Running 및 Full Load 100%
  • DMS Validation Pending/Failed 0건
  • MySQL 테이블 및 주요 데이터 행 수
  • PostgreSQL Catalog 행 수, vector 타입 및 HNSW Index

3.2 초 단위 타임라인

시각(KST) 이벤트 근거
15:53:37 POST·PUT·PATCH·DELETE Gate Rule 생성 CloudTrail CreateRule
15:53:38 인증 Callback Gate Rule 생성 CloudTrail CreateRule
15:53:49 Gate HTTP 503 검증 완료 GitHub Actions
15:54:12~15:54:34 DMS 중지 및 stopped 확인 GitHub Actions
15:54:34~15:54:46 DMS 중지 후 DB 재검증 GitHub Actions
15:54:46~15:54:51 V2 데이터 변환 GitHub Actions
15:55:04 Backend API V1=0, V2=100 CloudTrail ModifyRule
15:55:06 Frontend V1=0, V2=100 CloudTrail ModifyRule
15:55:08~15:55:12 V2 FE·BE Target Health 검증 GitHub Actions
15:55:19 일반 쓰기 Gate Rule 삭제 CloudTrail DeleteRule
15:55:21 인증 Callback Gate Rule 삭제 CloudTrail DeleteRule
15:55:22 Gate OFF 확인 GitHub Actions

3.3 Write Gate 시간

대상 시작 종료 유지 시간
POST·PUT·PATCH·DELETE 15:53:37 15:55:19 102초
인증 Callback 15:53:38 15:55:21 103초
Workflow 확인 구간 15:53:49 15:55:22 93초

4. V1 → V2 트래픽 전환 검증

4.1 ALB Listener Rule 변경

CloudTrail에서 다음 ModifyRule 이벤트를 확인했다.

대상 시각(KST) 변경 결과 CloudTrail Event ID
Backend API 15:55:04 V1=0, V2 Backend=100 e71f1f9d-1d65-43e6-af69-b5d7829cc88a
Frontend 15:55:06 V1=0, V2 Frontend=100 4499ad53-e7cc-40b5-a3c3-ff5e54b3653e

두 이벤트의 responseElements에 변경된 Target Weight가 기록됐다.

4.2 ALB 요청 유입

CloudWatch AWS/ApplicationELB RequestCount, Period 60초, Statistic Sum 조회 결과다.

시각(KST) 요청 수
15:48 2
15:49 2
15:50 17
15:51 65
15:52 242
15:53 247
15:54 242
15:55 265
15:56 301
15:57 368
15:58 252
15:59 302
16:00 243
16:01 179
  • 전체 요청: 2,727건
  • 요청 수가 0인 1분 구간: 0개
  • Backend와 Frontend가 전환된 15:55 요청: 265건

4.3 요청 처리 대상 이동

CloudWatch RequestCountPerTarget 조회 결과다.

시각(KST) V1 V2 Frontend V2 Backend
15:54 242 0 0
15:55 67 12 87
15:56 0 20.5 130
15:57 0 37 147

15:54에는 V1에서 요청이 처리됐고, 전환 시각이 포함된 15:55에는 V1과 V2 양쪽에서 요청이 처리됐다. 15:56부터 V1 지표는 0이고 V2 Frontend와 Backend에서 요청이 처리됐다.

RequestCountPerTarget은 Target Group의 요청 수를 Healthy Target 수로 나눈 값이므로 세 값을 합산하지 않는다.

4.4 Target Health

CloudWatch HealthyHostCount Minimum과 UnHealthyHostCount Maximum 조회 결과다.

Target Group Healthy 최솟값 Unhealthy 최댓값
V1 1 0
V2 Frontend 2 0
V2 Backend 2 0

V1 요청 처리 구간에는 V1 Healthy Target이 유지됐고, V2 전환 전후에는 V2 Frontend와 Backend Target이 각각 2개씩 Healthy 상태를 유지했다.

4.5 ECS 실행 용량

ECS Container Insights RunningTaskCount Minimum 조회 결과다.

ECS 서비스 최소 Running Task
Frontend 2
Backend 2
AI 2

같은 구간의 CloudTrail 조회에서 UpdateService와 StopTask 이벤트는 각각 0건이었다.

4.6 Target 및 연결 오류

15:48~16:01 KST 구간 조회 결과다.

지표 결과
V1 HTTPCode_Target_5XX_Count 오류 Datapoint 없음
V2 FE HTTPCode_Target_5XX_Count 오류 Datapoint 없음
V2 BE HTTPCode_Target_5XX_Count 오류 Datapoint 없음
V1 TargetConnectionErrorCount 오류 Datapoint 없음
V2 FE TargetConnectionErrorCount 오류 Datapoint 없음
V2 BE TargetConnectionErrorCount 오류 Datapoint 없음
ALB RejectedConnectionCount 오류 Datapoint 없음

4.7 ALB 연결 활동

시각(KST) ActiveConnectionCount NewConnectionCount
15:52 11 246
15:53 20 256
15:54 10 245
15:55 36 268
15:56 30 271
15:57 45 285

ALB Rule 변경 시각이 포함된 15:55에도 활성 연결과 신규 연결이 기록됐다.

4.8 Target 응답시간 p95

시각(KST) V1 p95 V2 FE p95 V2 BE p95
15:52 9.5ms - -
15:53 10.0ms - -
15:54 8.1ms - -
15:55 19.4ms 416.1ms 50.4ms
15:56 - 383.7ms 39.1ms
15:57 - 71.4ms 25.4ms

V2 Frontend p95는 전환 직후 416.1ms였고 15:57에는 71.4ms로 낮아졌다. 같은 구간에 V2 Target 5xx, Target 연결 오류 및 ALB 연결 거부 Datapoint는 없었다.

4.9 GitHub Actions 실행 결과

항목 결과
Workflow Prod Migration Cutover
전체 결과 success
Preflight Job success
Cutover Job success
Switch API and frontend to V2 success
Verify V2 target health before releasing gate success
Disable Write Gate success
Recover V1 and release Write Gate skipped
Restore V2 onboarding flags after service recovery skipped

전환, V2 Target Health 확인 및 Gate 해제 단계가 성공했고 V1 복구 단계는 실행되지 않았다.

4.10 DNS 변경 여부

15:48~16:01 KST CloudTrail 조회에서 ChangeResourceRecordSets 이벤트는 0건이었다. 최종 전환은 DNS 변경 없이 기존 Production ALB Listener Rule의 Target Weight를 변경하는 방식으로 수행됐다.

4.11 V2 애플리케이션 로그

15:52~15:58 KST 구간에 다음 Log Group을 검색했다.

  • /needu/prod/v2/frontend
  • /needu/prod/v2/backend
  • /needu/prod/v2/ai

검색어는 error, exception, timeout, failed, connection refused, outofmemory였으며, 검색된 27개 레코드에서 일치 항목은 0건이었다.

4.12 확인된 별도 오류 지표

시각(KST) 지표 건수 전환 시각과의 관계
15:53 HTTPCode_ELB_5XX_Count 1 ALB 전환 2분 전
15:53 HTTP_Fixed_Response_Count 1 Write Gate 생성·검증 구간
15:53 ClientTLSNegotiationErrorCount 5 ALB 전환 전
15:54 ClientTLSNegotiationErrorCount 1 ALB 전환 전

Backend 및 Frontend ALB ModifyRule은 15:55:04와 15:55:06에 실행됐다. 위 지표는 두 ModifyRule 이전에 기록됐다. 실제 전환 시각이 포함된 15:55 이후에는 V1·V2 Target 5xx, Target 연결 오류 및 ALB 연결 거부가 기록되지 않았다.

4.13 검증 결과

검증 항목 결과 근거
ALB V1=0/V2=100 전환 확인 CloudTrail ModifyRule
V1 → V2 요청 처리 대상 이동 확인 RequestCountPerTarget
1분 단위 요청 유입 공백 0구간 RequestCount
V1·V2 Healthy Target 유지 확인 HealthyHostCount
Unhealthy Target 0개 UnHealthyHostCount
FE·BE·AI Running Task 각각 최소 2개 RunningTaskCount
Target 5xx 전환 구간 미관측 HTTPCode_Target_5XX_Count
Target 연결 오류 전환 구간 미관측 TargetConnectionErrorCount
ALB 연결 거부 전환 구간 미관측 RejectedConnectionCount
ALB 연결 활동 유지 Active/NewConnectionCount
V1 자동 복구 실행 실행되지 않음 GitHub Actions skipped

CloudTrail과 CloudWatch 기록에서 V1 요청 처리 후 V2 요청 처리가 시작됐고, 전환 전후 1분 단위 요청 유입과 Healthy Target 및 ECS Running Task가 유지됐다. 전환 구간의 Target 5xx, Target 연결 오류 및 ALB 연결 거부는 관측되지 않았다.

따라서 AWS 관측 지표에서 V1 EC2 → V2 ECS 트래픽 전환 중 서비스 중단은 관측되지 않았다. 쓰기 및 인증 요청은 데이터 정합성 확보를 위해 각각 102초와 103초 동안 Write Gate로 제한했다.


5. Grafana 모니터링 결과

5.1 Production ALB 요청률

Production ALB HTTP RPS

시각(KST) 요청률
15:45~15:49 약 0 RPS
15:51 약 1 RPS
15:52 약 4 RPS
15:55 약 5 RPS
15:57 약 6.1 RPS
16:01 약 3 RPS

전환 시각이 포함된 15:55와 전환 이후 구간에서 Production ALB 요청률이 계속 기록됐다.

5.2 ALB HTTP 5xx

Production ALB HTTP 5xx

  • 15:53 KST ALB 5xx: 1건
  • 15:53 KST Fixed Response: 1건
  • Write Gate Rule 생성: 15:53:37~15:53:38
  • Backend 및 Frontend ALB 전환: 15:55:04~15:55:06
  • ALB 전환 시각 이후 Target 5xx: 관측되지 않음

5.3 ALB Target Response Time p95

Production ALB Target Response Time p95

  • Grafana 15:55 KST 응답시간 상승 관측
  • CloudWatch V2 FE p95: 416.1ms
  • CloudWatch V2 BE p95: 50.4ms
  • 15:57 V2 FE p95: 71.4ms
  • 15:57 V2 BE p95: 25.4ms

5.4 ECS 및 ALB Target Health

Production ECS Running Task

Production ALB Target Health

  • FE·BE·AI Running Task: 각각 최소 2개
  • V2 FE·BE Healthy Target: 각각 2개
  • Unhealthy Target: 0개
  • Cutover 전후 실행 용량 유지

5.5 DMS CDC Latency

DMS CDC Latency

DMS CDC Latency 추가 관측

  • CDC 지연이 약 4초에서 0초로 감소한 구간 확인
  • DMS Full Load 100%
  • DMS Validation Pending/Failed 0건
  • Cutover Workflow에서 DMS stopped 상태 확인

5.6 V1 Nginx 요청률

V1 Nginx Request Rate

  • V1 Nginx 요청률 약 0.2 RPS 기록
  • ALB RequestCountPerTarget에서는 15:56부터 V1 요청 처리량 0 기록
  • 15:56부터 V2 Frontend와 Backend 요청 처리량 기록

6. 데이터 검증 결과

6.1 MySQL

검증 대상 검증값 결과
전체 테이블 수 22 PASS
친구 관계 데이터 438 PASS
인증 세션 데이터 155 PASS
취향 분석 데이터 0 PASS
상품 데이터 7,969 PASS
AI 대화방 데이터 230 PASS
사용자 데이터 73 PASS
오류 보고 데이터 2 PASS

추가 확인 결과:

  • DMS Running
  • Full Load 100%
  • Validation Pending/Failed 0건
  • Preflight Data reconciliation: PASS

6.2 PostgreSQL

검증 대상 검증값 결과
임베딩 모델 메타데이터 1 PASS
상품 문서 데이터 20,289 PASS
상품 Catalog 데이터 7,969 PASS
Catalog 동기화 기록 0 PASS
전체 행 수 28,259 PASS
임베딩 타입 vector(1024) PASS
HNSW Cosine Index 1 PASS

6.3 데이터 이전 방식

데이터베이스 이전 방식 Cutover 검증
MySQL AWS DMS Full Load + CDC Full Load 100%, Validation 오류 0건, 주요 테이블 행 수 PASS
PostgreSQL Dump/Restore 및 Catalog 적재 Catalog 행 수, vector 타입, HNSW Index PASS

이 문서의 데이터 결과는 Cutover Workflow와 Preflight가 실행한 검증 항목의 통과 결과를 기록한다.


7. 복구 절차

6차 Cutover Workflow에는 Gate 해제 전 Cutover가 실패하거나 취소될 경우 다음 순서가 정의돼 있다.

  1. ALB Listener Rule을 V1으로 복원
  2. V1 Healthy Target 최소 1개 확인
  3. Write Gate 해제
  4. V2 사용자 상태 플래그 복원 Step 실행

최종 6차 Run에서는 Cutover가 성공하여 Recover V1 and release Write Gate와 Restore V2 onboarding flags after service recovery Step이 skipped로 기록됐다.


8. 핵심 개선 성과

8.1 쓰기 제한 시간

회차 기록된 시간 방식
1차 46분 35초 이상 Nginx Write Freeze
2차 630초 수동 ALB Gate
3차 327~349초 수동 ALB Gate
4차 59초 Staging 자동 Cutover
5차 129초 Production Workflow
6차 93초 Production Workflow

기존 Workflow 기록 기준:

  • 2차 630초 → 6차 93초: 537초 단축, 85.2% 감소
  • 5차 129초 → 6차 93초: 36초 단축, 27.9% 감소

6차 CloudTrail Rule 수명 기준:

  • 일반 쓰기: 102초
  • 인증 Callback: 103초

8.2 자동화 구조

영역 초기 방식 최종 방식
트래픽 전환 Route53 DNS 변경 ALB Listener Rule Weight 변경
실행 수동 명령 GitHub Actions Workflow
사전 검증 수동 Preflight 20/20
쓰기 제어 Nginx Write Freeze ALB Write Gate
Target 검증 수동 확인 Workflow 자동 검증
데이터 검증 개별 확인 DMS·MySQL·PostgreSQL 검증
복구 수동 V1 복원 및 Gate 해제 Step
관측 운영 로그 CloudWatch·CloudTrail·Grafana

8.3 5차 대비 6차

지표 5차 6차 변화
Cutover Job 192초 157초 35초 단축
Workflow Gate 129초 93초 36초 단축
전체 Workflow 261초 281초 20초 증가
Preflight 20/20 PASS 20/20 PASS 동일
Cutover SUCCESS SUCCESS 동일

9. 결론

NeedU V1 → V2 마이그레이션은 6차례의 실행을 통해 DNS 기반 수동 전환에서 ALB 기반 자동 Cutover로 개선됐다.

최종 6차 Production Cutover에서 확인된 결과는 다음과 같다.

  • Preflight 20/20 PASS
  • Cutover Workflow SUCCESS
  • Backend ALB V1=0/V2=100 변경: 15:55:04 KST
  • Frontend ALB V1=0/V2=100 변경: 15:55:06 KST
  • 관측 구간 전체 ALB 요청: 2,727건
  • 요청 수가 0인 1분 구간: 0개
  • 전환 시각이 포함된 15:55 요청: 265건
  • V1에서 V2로 요청 처리 대상 이동 확인
  • V1·V2 Unhealthy Target: 0개
  • FE·BE·AI Running Task: 각각 최소 2개
  • 전환 구간 Target 5xx: 관측되지 않음
  • Target 연결 오류: 관측되지 않음
  • ALB 연결 거부: 관측되지 않음
  • 일반 쓰기 제한: 102초
  • 인증 Callback 제한: 103초
  • DMS Full Load 100% 및 Validation 오류 0건
  • MySQL 및 PostgreSQL 정의 검증 항목 PASS

CloudTrail과 CloudWatch 기록에서 V1 요청 처리 이후 V2 요청 처리가 시작됐고, 전환 전후 요청 유입, Healthy Target, ECS Running Task 및 ALB 연결 활동이 유지됐다.

AWS 관측 지표에서 V1 EC2 → V2 ECS 트래픽 전환 중 서비스 중단은 관측되지 않았다. 데이터 정합성 확보를 위한 쓰기 및 인증 요청은 Write Gate를 통해 제한한 뒤 V2 Target Health를 확인하고 해제했다.