ADR-002 — Alembic 정식 도입 vs _COLUMN_MIGRATIONS 수동
| 항목 | 값 |
|---|---|
| Status | Accepted (2026-05-24 — Epic #1000) |
| Date | 2026-05-24 |
| Decider | GenD 코어팀 |
| Related Epic | #1000 (ADR-002) |
| Related ADR | ADR-001 (#999) — DB 모델 디렉토리 분리 |
컨텍스트
현재 GenD 의 schema migration 은 apps/api/src/gend_api/db/init_db.py 의 _COLUMN_MIGRATIONS 리스트로 수동 관리:
_COLUMN_MIGRATIONS: list[tuple[str, str, str]] = [
("access_policies", "group_name",
"ALTER TABLE access_policies ADD COLUMN group_name VARCHAR(255)"),
# ... 16 entries (2026-05-24 기준)
]
각 entry 는 (table, column, DDL) 튜플로, 부팅 시 init_db() 가 column 존재 여부를 확인하고 없으면 실행. feedback_db_migration_drift 메모리에 따르면 이 방식은:
- 장점: 단순, 추가 의존성 없음, idempotent (column 존재하면 skip)
- 단점: 단방향 (downgrade 없음), 의존성 그래프 없음, 동시 컬럼 변경 추적 어려움, dialect 차이 (SQLite/PG) 수동 처리, autogenerate 부재
신규 cross-cutting Epic (#1018 Workspace, #993 Ontology) 이 다수 모델에 FK 전파 + 백필 + NOT NULL 전환 같은 다단계 migration 을 요구하면서 _COLUMN_MIGRATIONS 의 한계가 명확해졌다.
결정
Alembic 정식 도입, 점진적 마이그레이션 — _COLUMN_MIGRATIONS 와 공존.
단계
| 단계 | 범위 | 상태 |
|---|---|---|
| M1 골격 (본 PR) | alembic 의존성 + alembic.ini + env.py + script.py.mako. versions/ 빈 디렉토리. _COLUMN_MIGRATIONS 유지. | ✅ |
| M1 baseline | alembic revision --autogenerate -m "baseline" 로 현재 schema 캡처. 신규 column/table 은 점차 Alembic 으로 이전. | 별도 PR |
| M2 신규 변경 → Alembic | 모든 신규 ALTER 는 Alembic migration 생성. _COLUMN_MIGRATIONS 는 read-only freeze. | |
M3 _COLUMN_MIGRATIONS deprecation | 기존 16 entries 를 Alembic versions 로 점진 이전 후 _COLUMN_MIGRATIONS 제거. | 장기 |
운영 규칙
# 신규 migration 생성
cd apps/api
GEND_DB_URL=postgresql+psycopg://... .venv/bin/alembic revision \
--autogenerate -m "feat: add ontology_packs FK"
# 적용 (운영자)
.venv/bin/alembic upgrade head
# 다운그레이드 (rollback)
.venv/bin/alembic downgrade -1
CI 에서는 alembic upgrade head + downgrade -1 + upgrade head 왕복으로 reversibility 검증 (별도 PR).
env.py 보안 정책
alembic.ini 의 sqlalchemy.url 은 반드시 빈 문자열. DB URL 은 GEND_DB_URL 환경변수에서만 읽음 — ini 에 시크릿 commit 사고 방지 (feedback_secret_single_source).
alembic/env.py 가 asyncpg:// → psycopg:// 자동 변환 (Alembic 은 동기 드라이버).
거부된 대안
(a) _COLUMN_MIGRATIONS 무한 확장
- 거부 사유: rollback 불가, 의존성 추적 불가, autogenerate 부재 → cross-cutting Epic 규모에서 누락/충돌 위험 폭증.
(b) Alembic 일괄 도입 + _COLUMN_MIGRATIONS 즉시 제거
- 거부 사유: 운영 DB 에 16 entries 가 이미 적용된 상태 — Alembic baseline 과 drift 발생 가능. 점진 이전이 안전.
(c) Atlas / Sqitch / dbmate 등 외부 도구
- 거부 사유: GenD 의 SQLAlchemy 의존성과 정합성 떨어짐, Python ORM 의
Base.metadata와 autogenerate 통합이 Alembic 만 깔끔.
영향
의존성
apps/api/pyproject.toml에alembic>=1.13.0추가
신규 파일
apps/api/alembic.iniapps/api/alembic/env.pyapps/api/alembic/script.py.makoapps/api/alembic/versions/.gitkeep
Docs
docs-site/docs/adr/0002-alembic.md(본 ADR)- (별도) admin-ops migration 가이드
CI (별도 PR)
alembic upgrade head+downgrade -1왕복 검증Base.metadata와 latest migration 의 drift 차단 (alembic check)
회귀 가드 (별도 PR — baseline 생성 후)
test_alembic_history_linearity— branching 차단test_alembic_metadata_drift—Base.metadata와 latest revision 일치test_alembic_versions_directory_layout— naming convention
관련
- Epic: #1000 (본 ADR)
- 자매: ADR-001 DB 모델 디렉토리, ADR-004 _protected_routers, ADR-006 Ontology Packaging
- 메모리:
feedback_db_migration_drift— 본 ADR 동기,feedback_secret_single_source— env.py 보안 정책