이전 글인 API Latency Postmortem-2 게시글에서 클라이언트로 이미지 업로드 작업을 이관했습니다.
이제 마지막 작업으로 프로덕션 환경에 DB 마이그레이션을 적용해야 했습니다.
하지만 실 사용자 데이터가 있는 프로덕션 환경에서 DB 구조를 변경하는 것은 고려해야 할 부분이 많았습니다.
문제상황
1. Flyway 마이그레이션 스크립트 문제
클라이언트로 이미지 업로드 작업을 이관했던 이전 작업에서 프로덕션 마이그레이션까지 깊이 고려하지 못했습니다.
Flyway 마이그레이션 V7에서 DROP COLUMN을 사용해 이미지 키를 삭제하고 새로운 테이블에 seed 데이터를 넣는 방식으로 개발 서버에 배포된 상태였습니다.
문제는 프로덕션 환경에는 이미 실 사용자 데이터가 존재한다는 점이었습니다. 현재 프로덕션은 V3까지만 적용된 상태인데, 개발 환경의 V7 스크립트가 그대로 배포되면 사용자의 이미지 키 데이터가 모두 삭제되는 위험한 상황이었습니다.

2. 마이그레이션 안정성 보장 부족
Flyway 스크립트를 수정한다고 해도 안전한 마이그레이션을 보장할 수 없었습니다. RDS 자동 스냅샷 기능을 사용하고 있지만, 실제로 데이터가 문제없이 옮길수 있을지, 장애 상황에서 복구가 완벽하게 될지 확신할 수 없었습니다.
실 서비스 데이터가 손실된다면 복구 불가능한 상황이 될 수 있기 때문에, 더 안전한 검증 방법이 필요했습니다.
3. S3 이미지 파일 구조 개선
기존 이미지 저장 방식은 해시.확장자 형태로 각 도메인별 하위 경로에 무작위로 저장되어 있었습니다. 이로 인해 어떤 이미지가 어떤 게시글과 연결되어 있는지 추적이 불가능한 상태였습니다.
새로운 업로드 방식에서는 /temp 경로에 임시 저장 후, 최종 등록 시 도메인/도메인ID/ 하위로 이동하는 구조로 변경되었습니다. 따라서 기존 데이터도 새로운 경로 구조에 맞게 모두 이동시켜야 했습니다.
4. 추가된 메타데이터 보완
기존에는 이미지 관련 정보가 이미지 키 하나뿐이었지만, 새로운 테이블 구조에서는 파일 사이즈, 콘텐츠 타입, 업로드 시간 등의 메타데이터가 추가되었습니다.
기존 파일들에는 이런 정보가 없기 때문에 S3에서 직접 읽어와 데이터를 보완하는 작업이 필요했습니다.
목표
안전한 마이그레이션을 위해 다음과 같은 목표를 설정했습니다.
- 완전 격리된 테스트 환경 구축 - 프로덕션과 동일한 환경을 독립적으로 복제하여 마이그레이션을 사전 검증
- 수동 승인 단계 도입 - 테스트 완료 후 실제 배포 시 개발자의 명시적 승인 과정 추가
- 롤백 전략 수립 - 각 단계별 문제 발생 시 즉시 복구할 수 있는 계획과 런북 준비
- 최대한의 자동화 - 인적 오류를 줄이기 위해 가능한 모든 과정을 자동화
- 재사용 가능한 시스템 - 향후 마이그레이션에서도 활용할 수 있고, 팀원 누구나 사용할 수 있는 구조
마이그레이션 작업에서 자동화는 안전성을 보장하기에 꼭 필요하다고 생각했습니다.
수동 작업은 담당자에 따라 결과가 달라질 수 있고, 중요한 단계를 누락할 위험이 있어 테스트 자체의 의미가 없어질 수 있습니다.
또한, DB 스키마 변경은 지속적으로 발생하는 작업입니다.
매번 인프라를 수동으로 구성하고 스크립트를 개별적으로 작성한다면
- 개발 효율성이 크게 떨어집니다.
- 새로운 팀원이 모든 히스토리를 파악해야 하는 부담이 생깁니다.
- 일관성 있는 마이그레이션 프로세스를 보장하기 어렵습니다.
따라서 누구나 쉽게 수정하고 재사용할 수 있는 시스템을 만드는 것이 중요했습니다.
설계
전체 플로우
테스트 단계 (완전 자동화)
프로덕션 복제 인프라 생성 → S3 데이터 복사 (전처리 스크립트) → develop 브랜치 기준 애플리케이션 빌드 및 ECS 태스크 실행 → 이미지 파일 이동 (후처리 스크립트)
실제 마이그레이션 단계
기존 CI/CD 파이프라인을 통한 애플리케이션 배포 → 애플리케이션 기동 및 RDS 상태 확인 → 후처리 스크립트 수동 실행 → 최종 검증


인프라 설계
Terraform 모듈 구성
- 기존 인프라와 완전히 독립된 별도의 Terraform 루트 모듈 생성
- 마이그레이션용 EC2, RDS, S3를 조합한 격리된 테스트 환경 구성
- Lambda를 통한 외부 스크립트 실행으로 안정성 확보
마이그레이션은 빈번하지 않은 작업이면서 기존 인프라에 영향을 주면 안 되기 때문에 완전히 격리된 구조로 설계했습니다.
Flyway 스크립트 재구성
기존의 문제가 있던 V 버전들을 수정했습니다.
- 기존 이미지 키 컬럼명을 deprecated_image_key로 변경
- 새로운 이미지 테이블에 기존 데이터를 복사하여 채워 넣기
- Spring 기동 시 Flyway 체크섬 검증이 정상 통과되도록 구성
GitHub Actions 워크플로
일반적인 개발/메인 브랜치 배포 파이프라인과는 목적이 다르기 때문에 별도의 수동 실행 워크플로를 구성했습니다.
- 테스트 환경 생성 워크플로: 복제 환경 구축 및 테스트 실행
- 테스트 환경 정리 워크플로: 테스트 완료 후 리소스 정리
- 브랜치 선택 옵션: develop 외에 hotfix 브랜치에서도 빌드 가능하도록 입력 파라미터 제공
Lambda 함수
테스트 환경용
- 전처리: 프로덕션 S3 데이터를 복제 버킷으로 복사
- 후처리: 마이그레이션 후 이미지 파일을 새 경로로 이동/삭제
프로덕션 환경용
- 전처리 생략
- 후처리: 개발자 수동 승인 후 실행
애플리케이션 배포 전략
테스트 환경 특화 구성
- develop 브랜치 기준으로 새로 빌드된 이미지 사용
- 환경 변수를 테스트 환경에 맞게 오버라이드
- ECR 이미지에 테스트 날짜/시간 태그 추가
- 테스트 이미지에 라이프사이클 정책으로 7일 후 자동 삭제
- ECS 서비스 없이 태스크만 일시적 실행
롤백 계획
단계별 롤백 전략
- Spring 기동 실패: ECS 서비스 자동 롤백으로 이전 버전 태스크 복구
- RDS 마이그레이션 실패: 사전 생성한 스냅샷으로 수동 롤백
- 후처리 스크립트 실패: 수동 복구 스크립트 실행
마이그레이션 전략 및 실패 시나리오에 대한 롤백 절차를 개발팀에게 공지하고 런북으로 준비해두었습니다.
해당 작업 내용은 여기에서 확인하실 수 있습니다.

트러블슈팅
1. Spring 애플리케이션 종료 문제
문제 상황: Spring 애플리케이션은 기본적으로 한 번 기동되면 계속 실행되는 구조입니다. 하지만 테스트 환경에서는 Flyway 마이그레이션만 확인하고 종료되어야 GitHub Actions에서 후처리 스크립트를 실행할 수 있습니다. 애플리케이션이 계속 실행 중이면 워크플로가 무한 대기하게 되는 문제가 발생했습니다.
해결 방법: ECS 태스크 정의에 아래 환경 변수를 추가했습니다.
이 설정을 통해 Spring이 웹 서버를 시작하지 않고 Flyway 마이그레이션만 실행한 후 정상적으로 종료되도록 했습니다.
SPRING_MAIN_WEB_APPLICATION_TYPE: NONE
2. Flyway 체크섬 불일치 오류
문제 상황 테스트 환경에서 애플리케이션이 기동에 실패하는 문제가 발생했습니다. 원인을 분석해보니 개발 과정에서 V 타입 마이그레이션 파일을 수정하거나 파일명을 변경하면서 Flyway 체크섬이 맞지 않는 상황이었습니다.
해결 방법 프로덕션 환경의 RDS에서 flyway_schema_history 테이블을 조회하여 기존 파일명과 체크섬을 확인했습니다. 그 후 개발 환경의 마이그레이션 파일들을 프로덕션과 일치하도록 수동으로 수정하여 체크섬 검증이 정상 통과되도록 했습니다.
결과
최종 실행 런북
실제 프로덕션 마이그레이션을 위한 최종 실행 절차는 다음과 같이 정리되었습니다.
- RDS 스냅샷 생성 - 배포 직전 수동으로 백업 스냅샷 생성
- 애플리케이션 배포 - main 브랜치에 머지하여 기존 CI/CD 파이프라인으로 배포
- 마이그레이션 상태 확인 - 배포 완료 후 RDS 테이블 구조 및 데이터 검증
- 후처리 스크립트 실행 - S3 이미지 파일 이동 작업 수동 실행
- 최종 서비스 검증 - 모든 기능 정상 동작 확인
실제 배포 과정
데모 데이 전날 오후 9시 30분, 전체 개발팀이 모여 실시간으로 마이그레이션 과정을 모니터링했습니다.
복제된 환경에서 이미 여러 차례 테스트를 완료했기 때문에 자신감은 있었지만,
실 서비스 데이터를 다루는 작업이다 보니 긴장감도 함께 있었습니다.
다행히 모든 과정이 계획대로 순조롭게 진행되었습니다. Flyway 마이그레이션, S3 파일 이동, 애플리케이션 재시작까지 모든 단계에서 문제없이 완료되었고, 롤백이 필요한 상황은 발생하지 않았습니다.
마지막으로 홈 화면에서 모든 API 응답이 정상적으로 나오는 것을 확인하는 순간, 그동안의 긴장이 풀리며 짜릿함을 느낄 수 있었습니다.

향후 개선점
검증 프로세스 자동화 필요
현재 가장 큰 아쉬움은 검증 과정이 수동으로 이루어진다는 점입니다. DB 테이블 구조 확인, 데이터 정합성 검증, S3 파일 이동 결과 확인 등을 모두 개발자가 직접 수행해야 합니다.
현제 서비스 단계에서는 데이터 규모가 작아서 가능했지만, 이미지가 100개만 넘어가도 수동 검증은 현실적으로 불가능합니다. 더 중요한 문제는 검증이 마이그레이션에서 가장 중요한 단계인데도 불구하고 수동 과정이다 보니 누락되는 부분이 있을 수 있다는 점입니다.
개선방향
- DB 테이블 스키마 자동 비교 스크립트
- 데이터 정합성 검증 자동화
- S3 파일 이동 결과 자동 검증
- 검증 결과를 종합한 성공/실패 리포트 생성
워크플로 유연성 부족
재사용성을 고려했다고 하지만, 현재 GitHub Actions 워크플로는 특정 마이그레이션 시나리오에 너무 강하게 결합되어 있습니다.
현재의 제약사항
- 빌드 브랜치 선택은 가능하지만 전처리/후처리 스크립트 실행 옵션이 고정됨
- 각 스크립트를 개별적으로 실행할지, 모두 실행할지 선택 불가
- 마이그레이션 유형이 달라지면 워크플로 전체를 수정해야 하는 구조
개선 방향
- 워크플로 입력 파라미터 확장 (전처리/후처리 스크립트 선택 옵션)
- 스크립트 실행 순서와 조합을 동적으로 구성할 수 있는 구조
- 마이그레이션 타입별 템플릿 워크플로 지원
인프라 리소스 관리 최적화
테스트 환경 정리 시 Lambda 함수의 ENI 반납 지연으로 인해 테스트 인프라 정리 과정이 오래 걸리는 문제가 있습니다.
개선 방향
- Lambda 함수는 상시 유지하되, Lambda Layer를 활용한 스크립트 버전 관리
- 각 마이그레이션 테스트별로 별도 Layer 생성하여 기존 테스트 데이터 보존
- ENI 재사용을 통한 빠른 환경 구성/해제
'YAPP' 카테고리의 다른 글
| API Latency Postmortem - 3 : Batch Fetch로 인메모리 페이징 병목 60% 개선 (0) | 2025.10.11 |
|---|---|
| Datadog을 활용한 SLI/SLO 모니터링 및 Burn Rate 알람 적용기 (0) | 2025.09.18 |
| API Latency Postmortem - 2 : 이미지 업로드 아키텍처 개선으로 주요 API 레이턴시 단축 (3) | 2025.08.28 |
| Dev/Prod 환경 로그 & DB 백업 자동화 적용하기 (0) | 2025.08.13 |
| API Latency Postmortem – 1 : AWS t2.micro 환경에서의 병목 분석과 최적화 (8) | 2025.08.12 |
