ADR-003 — ModelDeployment 명명 충돌 해소 (serving.py ↔ #995 MLOps)
| 항목 | 값 |
|---|---|
| Status | Accepted (2026-05-25 — Issue #1001) |
| Date | 2026-05-25 |
| Decider | GenD 코어팀 |
| Related Issue | #1001 |
| Affected Epic | #995 (MLOps Governance) |
| Related ADR | ADR-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 → fullPOST /api/v1/serving/deployments/{endpoint_name}/rollback— 이전 버전GET /api/v1/serving/deployments/{endpoint_name}/metrics— 지표
기존 모델 필드 인벤토리:
| 컬럼 | 타입 | 설명 |
|---|---|---|
id | UUID PK | |
model_name | String(255) | |
model_version | String(50) | |
mlflow_run_id | String(255) | MLflow run 연결 |
endpoint_name | String(255) UNIQUE | |
status | String(50) | pending/running/failed |
replicas | Integer | |
canary_percent | Integer | 0-100 |
created_at / updated_at | DateTime(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:48ModelDeployment필드 인벤토리 — 위 표 참조.routers/serving.py6 엔드포인트 + 호출자 grep — UI 검색 결과:- UI 호출:
ui/src/components/models/,ui/src/lib/api.ts의getDeployments/promoteDeployment등. - 외부 SDK 호출: 없음 (현재).
- UI 호출:
- 운영 데이터 마이그레이션: 현재
model_deployments행 수가 적은 dev/staging 환경 우선 — prod 는 별도 분석.
2. 통합 설계
2-1. 모델 확장 (ALTER 만)
db/models/serving.py 의 ModelDeployment 보존, #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_policies 의 resource_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 + 라우터 신설 PR | Alembic 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 Gone | 2026-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(후속 작성)