본문으로 건너뛰기

ADR-003 — ModelDeployment 명명 충돌 해소 (serving.py ↔ #995 MLOps)

항목
StatusAccepted (2026-05-25 — Issue #1001)
Date2026-05-25
DeciderGenD 코어팀
Related Issue#1001
Affected Epic#995 (MLOps Governance)
Related ADRADR-001 (#999) DB 디렉토리 분리

컨텍스트

apps/api/src/gend_api/db/models/serving.py:48 에 이미 class ModelDeployment(Base) 가 존재 — Feature Store / 모델 서빙 Phase 1 도입 (#15). routers/serving.py 가 다음을 제공한다:

  • POST /api/v1/serving/deployments — 생성
  • GET /api/v1/serving/deployments — 페이징 조회
  • GET /api/v1/serving/deployments/{endpoint_name} — 단건
  • POST /api/v1/serving/deployments/{endpoint_name}/promote — canary → full
  • POST /api/v1/serving/deployments/{endpoint_name}/rollback — 이전 버전
  • GET /api/v1/serving/deployments/{endpoint_name}/metrics — 지표

기존 모델 필드 인벤토리:

컬럼타입설명
idUUID PK
model_nameString(255)
model_versionString(50)
mlflow_run_idString(255)MLflow run 연결
endpoint_nameString(255) UNIQUE
statusString(50)pending/running/failed
replicasInteger
canary_percentInteger0-100
created_at / updated_atDateTime(tz)

한편 #995 (MLOps Governance) 본문은 동일 이름 model_deployment 테이블 + 신규 컬럼 (compute_requirements, gpu_spec, gpu_reservation_id, model_classification) 도입을 명시 → 기존 모듈과 정면 충돌. ABAC 자원 타입에 model 신규 추가, audit HMAC chain 에 deployment 이벤트 통합 등 책무는 기존 serving.py 가 이미 보유한 책무의 상위 집합.

선택지

옵션장점단점
A. 통합 — 기존 ModelDeployment + serving.py 확장 후 #995 신규 기능 흡수단일 진실 공급원, 분기 비용 0, audit 이력 연속성기존 라우터 시그니처 변경 (호환성) — deprecation 90일 필요, 1회 ALTER 마이그레이션
B. 기존 serving.py deprecate + #995 신규 (mlops.py) 로 대체#995 본문 그대로 진행기존 호출자 차단, audit 이력 손실 위험, 두 라우터 동시 가동 기간 발생
C. 이름 분리 (MLflowModelDeployment 신규)충돌 없음의미 중복 — 사용자가 "모델 배포" 가 2개 보임 → 사용자 혼란 영구화

결정 — 옵션 A (통합)

기존 ModelDeployment 모델 + routers/serving.py 는 사실상 #995 MLOps Governance 의 부분집합. 통합이 책임 단일화·운영 일관성에 정합. C 의 의미 중복은 거버넌스 정책 (ABAC resource type=model) 적용 시 영구적 혼란을 유발하므로 거부. B 는 audit chain 연속성 손실 위험으로 거부.

통합 작전

1. 기존 분석 (선행)

  • db/models/serving.py:48 ModelDeployment 필드 인벤토리 — 위 표 참조.
  • routers/serving.py 6 엔드포인트 + 호출자 grep — UI 검색 결과:
    • UI 호출: ui/src/components/models/, ui/src/lib/api.tsgetDeployments / promoteDeployment 등.
    • 외부 SDK 호출: 없음 (현재).
  • 운영 데이터 마이그레이션: 현재 model_deployments 행 수가 적은 dev/staging 환경 우선 — prod 는 별도 분석.

2. 통합 설계

2-1. 모델 확장 (ALTER 만)

db/models/serving.pyModelDeployment 보존, #995 신규 필드를 ALTER 로 추가 (Alembic migration — ADR-002 정합):

class ModelDeployment(Base):
# ... 기존 필드 ...
compute_requirements: Mapped[dict | None] = mapped_column(JSON, nullable=True)
gpu_spec: Mapped[str | None] = mapped_column(String(64), nullable=True)
gpu_reservation_id: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True), nullable=True)
model_classification: Mapped[str | None] = mapped_column(String(32), nullable=True) # public / internal / confidential

2-2. 라우터 흡수

routers/serving.py 는 그대로 두고 #995 MLOps 라우터 (mlops.py) 가 새 엔드포인트만 추가:

기존: /api/v1/serving/deployments (유지, deprecation annotation)
신규: /api/v1/ml/deployments (정식 — #995 등록 후)

OpenAPI deprecated: true + summary: "Deprecated 2026-09-01 — use /api/v1/ml/deployments".

2-3. ABAC model 자원 타입

access_policiesresource_type enum 에 model 추가. 기존 deployment 도 자동 포함 (table-level fall-through 정책).

2-4. Audit chain 연속성

audit_log HMAC 체인은 deployment action 이벤트를 이미 발행 (PR #520 P14 L2). #995 신규 이벤트 (gpu_reservation, classification_change) 만 추가, 기존 이벤트 형식 불변.

3. 이행 일정

단계내용기한
분석 / 호출자 grep 완료UI / SDK / Pipeline 호출자 인벤토리본 ADR 머지 + 1주
모델 ALTER + 라우터 신설 PRAlembic migration + routers/mlops.py 신규 + UI dual-call본 ADR 머지 + 2주
UI 마이그레이션UI 가 /api/v1/ml/deployments 사용 전환본 ADR 머지 + 4주
Deprecation 통보OpenAPI deprecated: true + 마이그레이션 가이드 발행본 ADR 머지 + 4주
기존 라우터 제거/api/v1/serving/deployments 410 Gone2026-09-01 (90일 deprecation)

4. 산출물

  • 본 ADR (Accepted, 본 PR).
  • 후속 PR: Alembic migration + routers/mlops.py + UI 전환 (별도 이슈).
  • 마이그레이션 가이드 docs-site/docs/admin-ops/mlops/migration-from-serving.md (후속 PR).
  • #995 본문 갱신 — 통합 흡수 명시 (후속 PR).
  • 메모리: project_mlops_unified_serving (후속 작성).

결과

  • ModelDeployment 단일 PG 테이블 = 모델 서빙 + 거버넌스 둘 다의 진실 공급원.
  • ABAC model 자원 타입이 기존 deployment 와 즉시 정합.
  • 사용자가 /admin/models 단일 진입점에서 모델 배포 + 거버넌스 + GPU 예약을 본다.
  • 기존 호출자는 90일 deprecation 으로 호환 — 갑작스러운 차단 없음.

회귀 가드

본 ADR 의 후속 통합 PR 에서 다음을 추가:

  • 기존 routers/serving.py 의 모든 테스트 통과 유지.
  • 신규 routers/mlops.py 가 동일 PG 테이블에 동일 의미로 쓰는지 단언.
  • ABAC resource_type='model' 정책이 deployment 행에 자동 매칭되는지 단언.

관련

  • Issue: #1001
  • 영향 자식: #995 (MLOps Governance)
  • 의존: ADR-001 (#999), ADR-002 (#1000)
  • 메모리: project_mlops_unified_serving (후속 작성)