| 항목 | 기록 |
|---|---|
| 문제 | DB 마이그레이션이 batch 앱 부팅 시 자동 적용되는 구조라 실패하면 앱이 무한 재시도하며 뜨지 않았고, MySQL DDL은 트랜잭션이 없어 반쯤 적용된 채 멈췄다. 과거 수동으로 스키마를 맞춘 이력 때문에 dev·staging·prod 가 저장소 마이그레이션의 결과와 어긋나 있어, 코드에서 잘 되던 마이그레이션이 특정 환경에서만 실패하는 일이 반복됐다. |
| 기존 방식과 비용 | 마이그레이션 성공 여부를 배포 전에 확인하는 단계가 없었다. 배포 워크플로는 zip 업로드까지만 책임져서 실행 183회 중 실패 6회로 보였지만, 마이그레이션 실패는 그 뒤 서버에서 일어나 CI 에 잡히지 않았다. 원인 추적은 서버 로그와 수동 DB 조회로 했고, 이미 적용된 마이그레이션 파일을 나중에 고치는 수정이 30/249 (12.0%) 누적돼 환경 간 차이를 키웠다. |
| 제안/판단 | Terraform 의 plan → 확인 → apply 처럼 마이그레이션도 “실제 환경 스키마 위에서 먼저 돌려 보고 배포”하는 게이트가 필요하다고 판단했다. 환경을 재생성하는 방식은 prod 에 쓸 수 없어 배제하고, 현재 상태를 기준선으로 받아들여 새 드리프트만 막으면서 기존 차이는 멱등 마이그레이션으로 하나씩 수렴하는 방식을 택했다. 검증 도구로 Atlas 도 검토했으나 실데이터 검증이 유료 기능이고 마이그레이션 실행기 교체 비용이 커서 자체 도구로 갔다. |
| 기술 선택 | 환경 스키마는 SHOW CREATE TABLE 로 DDL 만 추출해(데이터 없음, 수백 KB) 로컬 MySQL 8.0.32 컨테이너에 복원하고, 같은 지점까지의 마이그레이션 기준 스키마와 information_schema 단위로 대조한다. 그 복제본 위에 아직 적용되지 않은 마이그레이션을 실제로 실행해 실패를 재현한다. GitHub 호스팅 runner 는 VPC 안 DB 에 닿지 않아, 검사 도구를 zip 으로 올리고 기존 SourceDeploy 배포 경로로 대상 서버에서 실행하도록 했다. 실 DB 계정은 REFERENCES 와 마이그레이션 기록 테이블 SELECT 만 가져 데이터를 읽을 수 없다. PR 코드는 서버에서 실행하지 않고 lint 만 돈다. |
| 구현 범위 | 대조·리허설·정적 lint·기준선 등록을 갖춘 CLI, 서버 실행 스크립트, GitHub Actions 워크플로(PR·dev push·schedule·수동), test·prod 배포 워크플로의 needs 게이트와 비상 우회 입력, 사유·만료·상태 고정(expect)을 갖는 예외 목록, 수렴 마이그레이션 6개(작성·리허설 완료, prod 실측 후 별도 적용), dev 정리 SQL 이력. 기존 배포 스크립트의 Object Storage 클라이언트에 다운로드를 추가했다. |
| 내 기여 | 문제 진단(환경별 드리프트 실측, 유령 마이그레이션 원인 특정), 접근 방식 결정(bastion·self-hosted runner·릴레이 대안 비교 후 SourceDeploy 경유 채택), 도구·워크플로·예외 정책 설계, 구현 검증과 리뷰 반영, dev 정리 SQL 작성, 팀 공유용 동작 안내 문서. |
| 정량 결과 | 최초 실측 드리프트 staging 20건 (실패 20), dev 65건 (실패 36, 경고 29). 정리 후 실패 기준 dev 실패 0건 (예외 13, 경고 9), staging 실패 0건 (예외 18, 경고 2). 새 마이그레이션 6/6 리허설 성공, 실패 재현 1건. 2026-09-03 기준이며 prod 는 미측정. |
| 연결 데이터 | 환경 스키마 드리프트 (DATA-IMPROVEMENT-SCHEMA-DRIFT) · 마이그레이션 규모 (DATA-SCALE-MIGRATIONS) · 리허설 성공 (DATA-QUALITY-REHEARSAL) · prod 드리프트 (DATA-PENDING-PROD-DRIFT) |
| 공개 주의사항 | 테이블·컬럼·마이그레이션 클래스명, 호스트·계정·시나리오 ID, 예외 목록 원문은 공개하지 않는다. 공개 자료에는 분류별 건수와 추상화한 흐름만 사용한다. |
| 남은 검증 | prod 실측과 게이트 실행 검증이 남아 있다. 예외 목록은 부채이며 만료(2026-10-31, 2026-11-02) 전에 수렴해야 한다. 복제본에는 데이터가 없어 데이터 의존 실패(NOT NULL, UNIQUE, 고아 FK)와 대형 테이블 ALTER 시간은 검증 범위 밖이다. 마이그레이션 적용 자체를 배포 단계로 옮기는 작업은 후속이다. |
왜 필요했는지: 실측 근거
| 근거 | 값 | 산출 방법 | 의미 |
|---|---|---|---|
| 마이그레이션 파일 | 249개 (2024-08~2026-09) | 배포 기준 브랜치 파일 수 | 검증 없이 누적된 변경의 규모 |
| 적용 후 수정된 파일 | 30/249 (12.0%) | 파일별 커밋 수 2 이상, 최다 11회 | 환경과 파일이 어긋나는 직접 원인 |
| 마이그레이션 관련 fix 커밋 | 8건 | 메시지 기준, 2024-08~2026-08 | 반복된 사후 대응. 2건은 부팅 시 경합·락·재시도 수정 |
| CI 에 보인 배포 실패 | 6/183 | 배포 워크플로 실행 상태 | 마이그레이션 실패가 CI 밖에서 일어났다는 근거 |
| 파일 규칙 위반 | 파일명 위반 23/241 · timestamp 중복 7그룹 · name 공백 4 | 파일명 정규식, timestamp 중복, name 공백 | 정적 lint 가 필요한 이유 |
| staging 드리프트 | 20건 (실패 20) | DDL 복제본 vs 마이그레이션 기준 스키마와 대조 | 환경에만 6 · 없음 1 · 다름 6 · 기록에 파일 없음 7 |
| dev 드리프트 | 65건 (실패 36, 경고 29) | 같은 방법 | 실패 36 · 경고 29, 기록 268 vs 파일 249 |
| 유령 마이그레이션 | 20건 | 기록은 있으나 원격 어느 브랜치에도 파일 없음 | 피처 브랜치에서 개발 앱 부팅 시 공용 DB 에 자동 적용된 흔적 |
동작 흐름
- GitHub Actions 가 새 마이그레이션 파일만 lint 하고 검사 도구를 zip 으로 Object Storage 에 올린 뒤 SourceDeploy 시나리오를 실행한다.
- 대상 서버가 실 DB 에서 DDL 스냅샷을 뜨고, 로컬 MySQL 컨테이너에 복원한다.
- 빈 DB 에 저장소 마이그레이션을 환경의 최신 적용 지점까지 돌려 마이그레이션 기준 스키마를 만든다.
- 두 스키마를 컬럼·인덱스·FK·테이블 옵션 단위로 대조하고, 예외 목록을 적용해 남은 차이가 있으면 실패한다.
- 복제본 위에 아직 적용되지 않은 마이그레이션을 실제로 실행한다. 실패하면 이름·오류·소요시간을 남기고 실패한다.
- 리포트를 Object Storage 로 돌려보내고, GitHub 이 요약·아티팩트·Slack 으로 게시한다. test·main 배포는 이 결과가 성공일 때만 진행된다.
근거
지표는 포트폴리오 정본 data/metrics.yml(2026-08-31 기준)의 DATA-* 항목이다. 원본 응답·행 데이터는 저장하지 않는다.
- DATA-QUALITY-CI-VISIBLE-FAILURE · CI 에 보인 배포 실패: 6/183
- DATA-SCALE-MIGRATIONS-MODIFIED · 적용 후 수정된 마이그레이션 파일: 30/249 (12.0%)
- DATA-SCALE-CONVERGENCE · 수렴 마이그레이션 (작성·리허설, 미적용): 6개
- DATA-IMPROVEMENT-SCHEMA-DRIFT · staging 스키마 드리프트: 20건 (실패 20) → 실패 0건 (예외 18, 경고 2)
- DATA-IMPROVEMENT-SCHEMA-DRIFT-DEV · dev 스키마 드리프트: 65건 (실패 36, 경고 29) → 실패 0건 (예외 13, 경고 9)
- DATA-QUALITY-REHEARSAL · 리허설 성공: 6/6
- DATA-SCALE-MIGRATIONS · 마이그레이션 파일: 249개
- DATA-SCALE-MIGRATION-FIXES · 마이그레이션 관련 fix 커밋: 8
- DATA-SCALE-MIGRATION-NAMING · 마이그레이션 파일 규칙 위반: 파일명 위반 23/241 · timestamp 중복 7그룹 · name 공백 4
검증 대기
기존 기록에서 찾았지만 같은 조건의 실행 기록을 다시 확인하지 못한 값이다. 확정 지표와 섞지 않는다.
- DATA-PENDING-PROD-DRIFT · prod 스키마 드리프트: 미측정 — 검증 대기. 필요한 것: prod 시나리오·읽기 전용 계정 준비 후 같은 방법으로 실측
측정값
| 항목 | 이전 | 이후 | 비고 |
|---|---|---|---|
| staging 스키마 드리프트 | 20건 (실패 20) | 실패 0건 (예외 18, 경고 2) | 실패 20 → 0, 기준선 20건 등록 |
| dev 스키마 드리프트 | 65건 (실패 36, 경고 29) | 실패 0건 (예외 13, 경고 9) | 실패 36 → 0 |
예외 등록이며 스키마 해소가 아니다. 수렴 마이그레이션 6개 배포 후 재측정 필요. 정리 SQL 로 43건 해소, 13건은 기준선 예외(만료 2026-11-02), 경고 9건은 새 마이그레이션 적용 시 소멸. 측정일 2026-09-03 기준. 정본: 포트폴리오 data/metrics.yml.
공개 범위
이 글은 포트폴리오 정본의 공개 요약이다. 원본 업무 데이터와 회사·약국·서버·공급사 식별정보는 뺐다. 테이블·컬럼·마이그레이션 클래스명, 호스트·계정·시나리오 ID, 예외 목록 원문은 공개하지 않는다. 공개 자료에는 분류별 건수와 추상화한 흐름만 사용한다.