MMX Beta Project Documents 계획, 근거, 댓글이 같은 기록으로 남는 작업 저장소

ALEMBIC_MIGRATION_DRIFT_resolution_20260523

  • 문서 작성자: 덱스PM
  • 문서 오너: 덱스PM
  • 작성일: 2026-05-23
  • 연관 이슈: ALEMBIC_MIGRATION_DRIFT_20260523
  • 상태: Draft

개요

MMX api의 Alembic 상태를 정밀 점검한 결과, 최초 장애는 Cloud Run startup 시 alembic upgrade head가 multiple heads 때문에 실패한 것이었고, 그 뒤에도 모델 메타데이터와 실제 DB 스키마 사이에 drift가 남아 있었다. 본 문서는 그 drift를 어떻게 분류하고, 어떤 판단으로 수정했는지 상세히 기록한다.

1. 최초 장애 원인

Cloud Run mmx-api 컨테이너는 entrypoint에서 아래 순서로 동작한다.

  1. alembic upgrade head
  2. uvicorn main:app

문제는 head가 1개가 아니라 2개였다는 점이다.

  • 9d04ce19b61e
  • b7c9d1e2f3a4

이 상태에서는 Alembic이 단일 upgrade 경로를 확정하지 못해 startup migration에서 중단되었고, 결과적으로 Cloud Run revision이 healthy 상태로 올라오지 못했다.

조치

  • merge migration 추가
    • c1d2e3f4a5b6_merge_project_document_release_head.py
  • 이후 mmx-api-00076-npw 배포 성공 확인

2. 후속 정밀 점검에서 확인된 drift

head 충돌을 해소한 뒤 alembic check를 실행하자 다수의 new upgrade operations가 검출되었다. 이 시점에서 문제는 단순한 head 충돌이 아니라, 장기간 누적된 모델-스키마 drift라는 것이 명확해졌다.

주요 범주는 아래와 같았다.

2.1 과거 임시 테이블 / 잔재성 스키마

  • deep_temp_tbl

DB에는 존재하지만 ORM 메타데이터에는 없어 Alembic이 제거 대상으로 인식했다.

2.2 모델 누락

  • scenarios.thumbnail_id
  • scenarios.shortcut_vid_id
  • scenarios.trailer_id

과거 migration에는 존재했지만 현재 Scenario 모델 정의에는 빠져 있어, Alembic이 삭제 대상으로 인식했다.

2.3 nullable / default 정합성 차이

  • users.google_sub
  • users.email
  • users.name
  • users.last_login_at
  • users.is_tester
  • users.tokens
  • game_status.genre_tags
  • game_status.created_at
  • game_status.updated_at
  • media.created_at

초기/복구 migration에서 만들어진 nullable/default와 현재 모델 정책이 완전히 일치하지 않았다.

2.4 인덱스 / 제약조건 naming drift

  • game_status
  • project_document_comments
  • project_document_releases
  • studio_scenarios
  • users.username

기존 migration은 수동 index name을 사용했고, ORM은 기본 naming 또는 다른 선언 방식을 기대해 drift가 발생했다.

3. 분류와 판단

3.1 deep_temp_tbl

즉시 제거하지 않았다.

이유:

  • 별도 작업 흔적(deepSeek_20260521_job.md)이 존재했다.
  • migration 그래프 안에 이미 공식 revision으로 편입되어 있었다.
  • 운영 DB에 존재하는 테이블을 의미 확인 없이 제거하면 2차 장애 위험이 있다.

조치:

  • DeepTemp ORM 모델을 추가해 Alembic 메타데이터에 포함시켰다.

3.2 scenarios.*_id

즉시 삭제하지 않았다.

이유:

  • 과거 migration c4a8e1f02b3d_alpha_schema_complete.py에서 명시적으로 도입되었다.
  • game_status, schemas_game.py 쪽에서도 미디어 관련 구조가 이미 사용 흔적을 남기고 있었다.

조치:

  • Scenario 모델에 thumbnail_id, shortcut_vid_id, trailer_id를 다시 반영했다.

3.3 nullable / default drift

DB를 현재 모델/서비스 정책 쪽으로 정렬했다.

판단 근거:

  • 인증 코드상 User는 nullable 가능한 필드를 자연스럽게 다루고 있었다.
  • 현재 제품 구조에서 google_sub, email, name, last_login_at는 스키마 레벨에서 절대 NOT NULL이어야 한다는 강한 근거가 부족했다.
  • 반대로 is_tester, tokens, game_status 일부, media.created_at는 현재 모델 기준 NOT NULL이 더 일관적이었다.

조치:

  • 정합화 migration 추가
    • f4e5d6c7b8a9_align_alembic_schema_with_models.py

3.4 인덱스 / 제약조건 drift

운영 DB의 기존 명명 규칙을 존중하는 방향으로 ORM 선언을 맞췄다.

판단 근거:

  • 이 단계에서 DB 인덱스를 재명명하는 것보다, 모델 쪽에 명시적 Index(...) / UniqueConstraint(...)를 부여해 autogenerate drift를 없애는 편이 안전하다.
  • 사용자 요청은 “완벽한 마감”이지, 불필요한 물리 스키마 재작성 자체가 목적은 아니다.

조치:

  • ProjectDocumentCommentidx_project_document_comments_document_key 반영
  • ProjectDocumentRelease에 legacy index 3개 및 unique constraint 명시 반영
  • StudioScenario에 legacy index 2개 반영
  • GameStatus에 legacy index 3개 반영
  • User.username는 unique column 표현 대신 idx_users_username 명시 인덱스로 정렬

4. 실제 수정 파일

API / Alembic

  • api/alembic/versions/c1d2e3f4a5b6_merge_project_document_release_head.py
  • api/alembic/versions/f4e5d6c7b8a9_align_alembic_schema_with_models.py

API / Models

  • api/models/__init__.py
  • api/models/game_models.py
  • api/models/game_status.py
  • api/models/project_document_comment.py
  • api/models/project_document_release.py
  • api/models/studio_scenario.py
  • api/models/temp.py
  • api/models/user.py

Project Documents

  • www/public/project_document/issues/ALEMBIC_MIGRATION_DRIFT_20260523.md
  • www/public/project_document/issues/index.html
  • www/public/project_document/reports/ALEMBIC_MIGRATION_DRIFT_resolution_20260523.md

5. 검증 결과

정리 후 아래를 확인했다.

  1. alembic heads
    • 단일 head: f4e5d6c7b8a9
  2. alembic current
    • 현재 DB revision이 동일 head를 가리킴
  3. alembic check
    • No new upgrade operations detected.
  4. Python compile
    • 관련 model/migration 파일 컴파일 통과

6. 남은 관찰 사항

alembic check는 통과했지만, 아래 경고가 남아 있다.

  • mediascenarios 사이의 FK cycle warning

이 경고는 현재 즉시 drift를 발생시키지는 않지만, 향후 SQLAlchemy/Alembic 버전 변화에 따라 더 엄격하게 다뤄질 수 있다. 따라서 운영 규칙 문서에는 아래를 포함해야 한다.

  1. 순환 FK가 생기지 않도록 신규 모델 설계 시 주의한다.
  2. 기존 cycle은 별도 구조 개선 과제로 분리 검토한다.
  3. alembic check clean과 warning-free는 같은 의미가 아님을 명시한다.

7. 결론

이 이슈의 본질은 단순한 배포 실수가 아니라, 누적된 migration hygiene 부채였다.

최종적으로:

  • multiple heads는 해소되었고
  • drift 항목은 분류/정리되었으며
  • alembic check 기준 clean 상태를 확보했다

따라서 Alembic migration 관점에서 이번 장애의 직접 원인과 누적 drift는 모두 운영 가능한 수준으로 정리되었다.

댓글