콘텐츠로 이동

ADR-0005: DB를 단일 계약으로 · 확장-수축 마이그레이션

  • 상태: 승인됨
  • 날짜: 2026-06-21

맥락

여러 서비스(JVM·Python)가 같은 데이터베이스를 공유한다. 따라서 DB 스키마는 사실상 서비스 간 계약이다 — 한 서비스가 스키마를 깨면 다른 서비스가 깨진다. 게다가 머지 ≠ 배포다. PR이 머지돼도 각 서비스의 롤아웃에는 시차가 있어, 한순간 구버전 코드와 신버전 코드가 같은 DB를 동시에 바라본다. 이 지점이 시스템에서 실수가 가장 잦은 곳이다.

결정

  • libs/schema를 DB 스키마의 단일 출처(SSOT)로 둔다 — 마이그레이션(migrations/)과 각 언어 생성 모델(generated/)을 한곳에서 관리한다. 스키마 변경과 생성 모델 갱신은 함께 커밋한다.
  • 스키마 변경은 확장-수축(expand-contract) 3단계로 나눈다:
  • 확장 — 새 컬럼/테이블 추가(기존과 후방 호환, 옛것 유지).
  • 전환 — 모든 읽기/쓰기 코드를 새 구조로 옮기고 배포 완료까지 기다린다.
  • 수축 — 더 이상 참조되지 않는 옛 컬럼/테이블 제거.
  • 코드 변경은 PR 단위로 원자적이되, DB 계약 자체는 위 단계로 분리해 롤아웃 시차를 견딘다.

이 절차의 운영 디테일(테이블 소유권 포함)은 implementation.md §4가 SSOT (구 schema.md에서 이동).

대안

  • 파괴적 마이그레이션(컬럼 rename/drop을 한 번에) — 롤아웃 도중 구버전 서비스가 즉시 깨진다.
  • 서비스별 개별 스키마/DB — 공유 데이터의 중복과 드리프트를 부른다. 분석·집계가 어려워진다.

결과

  • 무중단 롤아웃이 가능하다 — 어느 순간에도 구·신 코드가 같은 스키마에서 동작한다.
  • 변경 한 건이 여러 PR(확장 → 전환 → 수축)로 늘어난다. 의도된 비용이다.
  • schema 변경은 generated 갱신과 함께 가고, [[0001-monorepo-structure]] 덕분에 한 저장소에서 원자적으로 처리된다.
  • 가장 실수 잦은 지점이므로 이 절차를 문서로 강제하고 리뷰에서 확인한다(향후 libs/schema CODEOWNERS 양쪽 리뷰).