Drift Monitoring UI
GenD /admin/drift 대시보드는 등록된 MLflow 모델별 데이터 드리프트 보고서를
시각화하고, 관리자에게 다음 4 가지 운영 액션을 제공합니다.
Dashboard 진입 — 모델 선택 + 시계열 + 보고서 목록 (#1535 follow-up #1)
demo_credit_risk 모델 선택 후 prod AKS UI (gend.genon.ai) 의 실 캡쳐 — #1626 batch_predict feature sink + 분포 shift seed + drift compute 결과:

상단 — MLflow 등록 모델 picker (datalist + Apply + 새로고침).
중단 — 드리프트 점수 추이 sparkline. 5건 보고서 (좌=옛 stub, 우=신규 1.000 breach) — 분포 shift 후 실 KS 결과 가 sparkline 우측 끝으로 급상승.
하단 — 보고서 표: 최신 row drift_score=1.000 / status=breach / rows=10 / 트리거=수동 / 알림 발송: 6/2/2026 5:39 PM (notification 자동 dispatch).
리포트 상세 — DriftReportDetailSheet + KS p-value chart (#1567)
표의 "상세" (👁) 버튼 클릭 → 우측 슬라이드 sheet:

- 메타 블록: drift_score=1.0, rows=10, Reference MLflow Run
8f065881...(#1564 baseline 첨부 run), 윈도우 6/1~6/3, ML Batch Run, 알림 발송 시각, 생성일 - admin 액션: "상태 오버라이드" / "삭제" 버튼. 본 보고서는 notified → "감사 보존을 위해 이 보고서는 삭제할 수 없습니다" 안내
- 피처별 P-VALUE 차트 (#1567): KS p-value horizontal bar chart 가 실 데이터로 렌더 —
income: 1.1e-5,credit_history_len: 2.2e-4,age: 0.002모두 빨강 (p<0.01 strong drift). 하단 표 도 동일 정보 표시
M3 실 구현 검증 (#1617 — 2026-06-02)
#1565 ML-B 의 drift_service M3 실 구현 + #1618 Dagster prod 재배포 + #1617 schema/boto3 fix 가 모두 prod 에 반영된 후의 동작:

demo_credit_risk_plugin 선택 시 보고서 0건. "드리프트 계산" 트리거 시:
| reference_run 상태 | 결과 |
|---|---|
| baseline artifact 보유 + sink table 존재 | 200 OK + 의미있는 drift_score + drifted_features |
| baseline artifact 보유 + sink table 부재 | 422 DriftCurrentEmptyError — TABLE_NOT_FOUND 명시 (silent fail 금지) |
| baseline artifact 미보유 (옛 학습) | 422 DriftBaselineMissingError — tag gend.drift.baseline 부재 명시 |
본 검증에서 silent score=0 (M2 stub) 행위가 완전 제거 확인 — 의미있는 422 raise 가 router 의 새 매핑으로 UI toast 노출.
실 데이터 시드 prerequisite (#1626) — 완료 (2026-06-02)
#1626 (PR #1629 머지) 로 batch_predict_asset 가 prediction 과 함께 input feature value 도 sink. sink schema = customer_id (VARCHAR) + age/income/credit_history_len (DOUBLE) + prediction (DOUBLE) + ml_batch_run_id (VARCHAR) + predicted_at (TIMESTAMP).
운영 배포 (#1632, 2026-06-02):
- ✅ Dagster image 재빌드 (
0.2.20260602-b7009873) + rollout - ✅
DROP TABLE iceberg.gold.predictions_demo_credit_risk(옛 4-컬럼) - ✅ silver seed (10 row, 분포 shift) +
ml_batch_demo_credit_risk_job머티리얼라이즈 → 새 7-컬럼 sink - ✅
POST /api/v1/models/demo_credit_risk/drift/compute→drift_score=1.0 / status=breach / drifted_features={income: 1.1e-5, credit_history_len: 2.2e-4, age: 0.002}
→ 본 가이드의 dashboard-list + DetailSheet 캡쳐가 실 KS p-value chart 노출 완료.
Distribution Overlay (#1567 Cycle 1 — 2026-06-03)
기존 KS p-value horizontal bar (#1567 이전) + drifted_features table 아래에 distribution overlay panel 추가. 다른 솔루션 (Databricks Lakehouse Monitoring / Arize / Evidently / WhyLabs / Fiddler) 의 표준 패턴.
구성:
- 상단: feature 선택 Radix Tabs (numeric column 별)
- 본문: Recharts
<ComposedChart>overlay — reference (회색) + current (빨강) bar - 하단: summary stat 비교 table —
mean / std / p5 / p25 / p50 / p75 / p95양쪽
Backend endpoint:
GET /api/v1/models/{model_name}/drift/{report_id}/distribution
- admin only + workspace fence (
require_admin) - lazy — DetailSheet 열릴 때만 호출 → drift_report row 크기 영향 0
- 422 매핑 (silent fail 금지):
reference_run_idNULL (옛 stub) →DriftDistributionUnavailableError- MLflow baseline 부재 →
DriftBaselineMissingError - Trino sink 부재 / 윈도우 0건 →
DriftCurrentEmptyError - common numeric column 0 →
DriftDistributionEmptyError(#1626 prerequisite)
Frontend cache:
zustandin-memorydistributions: Record<report_id, DistributionProfile>- explicit
invalidate만 새로고침 (sheet 닫혀도 유지)
Cycle 2 / 3 의 후속:
- PSI / Wasserstein / JS divergence (Cycle 2)
- Categorical chi-square (Cycle 2)
- Threshold editor (Cycle 2)
- Alert rule editor + auto-dispatch (Cycle 3)
| 액션 | HTTP | 경로 | 권한 |
|---|---|---|---|
| 보고서 목록 / 단건 조회 | GET | /api/v1/models/{name}/drift[?…] / /{report_id} | user (workspace fence) |
| 수동 계산 (Compute) | POST | /api/v1/models/{name}/drift/compute | admin |
| 상태 오버라이드 | PUT | /api/v1/models/{name}/drift/{report_id} | admin |
| 소프트 삭제 | DELETE | /api/v1/models/{name}/drift/{report_id} | admin |
배경 컨텍스트:
- 백엔드 PoC: PR #1217 —
GET /drift+POST /drift/compute. - 백엔드 M2 mutation contract: PR #1225 —
PUT/DELETE+ 알림 처리 분리. - 백엔드 batch integration: ML Batch run completion 시
evaluate_drift_with_baseline()가 자동으로 보고서를 생성하고 NotificationService 로 발송합니다. - UI: PR #이슈 #1213 — 본 대시보드.
페이지 구조
/admin/drift
├── Header # 페이지 제목 + "드리프트 계산" 버튼 (admin)
├── Model picker # MLflow 등록 모델 datalist + Apply
├── Sparkline chart # 선택 모델의 drift_score 시계열 (newest-rightmost)
├── Report table # 보고서 목록 (Created · Version · Score · Status · Rows · Trigger · Notified)
├── DriftReportDetailSheet # 우측 슬라이드: 메타 + 피처별 p-value
├── DriftComputeDialog # 수동 계산 (Reference Run ID + window + 옵션 threshold/version)
├── DriftOverrideDialog # 관리자 상태 오버라이드 (사유 ≥ 3자)
└── DeleteDialog # AlertDialog — soft delete 확인
운영자 워크플로우
1) 모델 선택
- 사이드바 하단 ⚙ 관리 콘솔 → 운영 & 모니터링 → 드리프트 모니터링 클릭.
- "MLflow Registered Model" 입력란에 모델명 (예:
credit_risk) 입력 또는 datalist 드롭다운에서 선택. - Apply 버튼 클릭 →
GET /api/v1/models/{name}/drift?limit=50&offset=0호출.
만약 보고서가 없으면 빈 상태 카드가 표시됩니다. 처음 모델 등록 후 수동 계산을 한 번 수행하거나, ML Batch run 이 자동 생성하기를 기다리세요.
2) 시계열 분석
buildSparklinePoints() 헬퍼가 newest-first (created_at DESC) 응답을 뒤집어
오른쪽이 최신이 되도록 SVG polyline 을 그립니다. Y 축은 관측 범위로 normalize
하되 최소 span 0.05 를 보장하므로 평탄한 0 값 시리즈도 보입니다.
3) 보고서 상세
테이블 행의 View 를 클릭하면 우측 슬라이드 시트가 열리며 다음을 표시합니다.
- 메타: reference run id, 평가 윈도우, ml_batch_run_id, notified_at, created_at.
- 피처별 p-value 표 (
drifted_featuresdict 가 정렬되어 노출). - 관리자 액션 버튼: Override Status, Delete.
notified_at 이 NULL 이 아닌 보고서의 Delete 버튼은 자동으로 비활성화됩니다.
백엔드가 동일한 조건에서 409 를 반환하므로 라운드트립을 사전 차단합니다.
4) 수동 계산 (Compute)
상단 드리프트 계산 버튼 → 다이얼로그.
| 필드 | 필수 | 비고 |
|---|---|---|
| Reference MLflow Run ID | 필수 | drift_baseline.npz artifact 가 첨부된 학습 run 의 ID |
| Window Start / End | 필수 | datetime-local picker, 기본값은 오늘 00:00 ~ 현재 |
| Model Version | 선택 | NULL = alias 에서 자동 해석 |
| Threshold | 선택 | [0, 1] 범위, NULL = MLBatchJob.drift_threshold |
성공 시 sonner toast 로 score / status 표시 + 보고서 목록 자동 갱신.
5) 상태 오버라이드
행의 Override 또는 상세 시트의 Override Status 클릭.
- 새 상태:
ok/warn/breach. - 오버라이드 사유: 최소 3자, 감사 로그에 영구 기록.
백엔드는 AuditMiddleware 의 request-body capture + 구조화된
drift_status_override 로그라인으로 이중 기록합니다.
6) 소프트 삭제
행의 Delete 또는 상세 시트의 Delete 클릭 → AlertDialog 확인.
- 삭제 대상이
notified_at != null이면 버튼 자체가 비활성화 (감사 보존). - 백엔드는 행을 보존하되 후속 로직에서 무시합니다 (soft delete).
권한 매트릭스
| 액션 | non-admin user | admin |
|---|---|---|
| 보고서 목록 / 단건 조회 | OK (workspace fence) | OK |
| Compute | 버튼 disabled + 403 | OK |
| Override | 버튼 disabled + 403 | OK |
| Delete | 버튼 disabled + 403 | OK (notified=null 만) |
UI 가 버튼을 disabled 처리하지만 백엔드 require_admin 이 최종 진실의 원천입니다.
API 호출 흐름
operator clicks Apply
→ useDriftStore.setModelName(name)
→ useDriftStore.fetchReports(name)
→ GET /api/v1/models/{name}/drift?limit=50&offset=0
→ set reports[]
operator clicks Compute (admin)
→ DriftComputeDialog 검증 (reference_run_id + window + threshold)
→ useDriftStore.compute(name, body)
→ POST /api/v1/models/{name}/drift/compute
→ 성공 시 fetchReports(name) 재실행
→ 토스트 (score, status) 표시
operator clicks Override (admin)
→ DriftOverrideDialog 검증 (drift_status + override_reason ≥ 3)
→ useDriftStore.updateStatus(name, id, body)
→ PUT /api/v1/models/{name}/drift/{id}
→ 성공 시 reports[] in-place 갱신 (refetch 없음)
→ 토스트 (새 status) 표시
operator clicks Delete (admin, notified=null only)
→ AlertDialog 확인
→ useDriftStore.deleteReport(name, id)
→ DELETE /api/v1/models/{name}/drift/{id}
→ 성공 시 fetchReports(name) 재실행
→ 토스트 (id) 표시
트러블슈팅
| 증상 | 원인 / 조치 |
|---|---|
| Apply 후 빈 상태 | 보고서가 아직 없음 — /admin/ml-batch 의 잡이 완료됐는지 확인하거나 수동 계산 |
| Compute 시 422 "reference_run_id" | MLflow run 이 없거나 drift_baseline.npz artifact 가 첨부되지 않음 |
| Compute 시 422 "model_version" | 명시한 버전이 MLflow registry 에 없음 — NULL 로 두면 alias 자동 해석 |
| Override 시 422 "override_reason" | 사유가 3자 미만 — Pydantic min_length=3 |
| Delete 시 409 "notified report" | 알림이 이미 발송된 보고서 — 감사 보존 정책상 삭제 불가 |
| 403 모든 mutation | admin 권한 부재 — Keycloak realm role 확인 |
실 run 결과 캡쳐 SOP (#1535)
audit wonmoc13s (#1531) deferred — 기존 05-admin-drift-authenticated.png (cycle 15
캡쳐) 는 model picker idle 상태. baseline+current 데이터 보유 모델의 실 drift
결과 (drift_score / PSI / KS p-value chart) PNG 가 부재했다.
본 캡쳐를 갱신하려면 다음 seed orchestration 이 prerequisite:
prerequisite — seed orchestration 절차
-
MLflow registered model 등록
- 이미 prod 에 등록된 모델이 있는지 확인:
kubectl --context aks-genos-prod -n gend port-forward svc/mlflow 5000:5000 &curl -s http://localhost:5000/api/2.0/mlflow/registered-models/list | jq '.registered_models | length'
- 0건이면 ML Plugin train 가이드 (ml-plugin-train.md) 의 Stage 2-4 를 1회 수행해 registry 에 1개 모델 등록.
- 이미 prod 에 등록된 모델이 있는지 확인:
-
baseline + current 데이터 보유 확인
- drift
compute는 baseline run 의drift_baseline.npzartifact + 현재 데이터 window 두 개를 모두 요구. - baseline run 확인:
curl -s "http://localhost:5000/api/2.0/mlflow/runs/search?experiment_ids=<id>" \| jq '.runs[] | select(.data.tags[]?.key == "drift_baseline") | .info.run_id'
- drift
-
drift compute trigger
- GenD UI
/admin/drift→ 모델 선택 → "드리프트 계산" 버튼 → reference_run_id 입력 → Submit. - 또는 API 직접 (#1597 #1557 Minor — backend pydantic schema 정합):
WINDOW_START=$(date -u -v-24H +%Y-%m-%dT%H:%M:%SZ)WINDOW_END=$(date -u +%Y-%m-%dT%H:%M:%SZ)curl -X POST "https://gend.genon.ai/api/v1/models/<name>/drift/compute" \-H "Authorization: Bearer $ADMIN_TOKEN" \-H "Content-Type: application/json" \-d "{\"reference_run_id\":\"<run_id>\",\"current_data_window_start\":\"$WINDOW_START\",\"current_data_window_end\":\"$WINDOW_END\"}"
- GenD UI
-
결과 PNG 캡쳐
- Playwright password grant 패턴 (cli-sso.md 참고)
으로
/admin/drift접속, 모델 선택 → 보고서 row 클릭 → DriftReportDetailSheet 의 시계열 차트 + 피처별 p-value 풀 렌더 대기 (page.waitForSelector('table tbody tr')). page.screenshot({path: 'docs-site/static/img/m3-cycle/07-admin-drift-real-run.png', fullPage: true}).
- Playwright password grant 패턴 (cli-sso.md 참고)
으로
-
본 가이드 / drift-monitoring.md 의 placeholder 교체
- 기존 idle 캡쳐 (
05-admin-drift-authenticated.png) 옆에 실 run 결과 캡쳐07-admin-drift-real-run.png를 nominative 배치.
- 기존 idle 캡쳐 (
본 PR (#1535) 의 scope
SOP 가이드 문서화만 — 실 PNG 캡쳐는 prerequisite seed orchestration 완료 후 follow-up PR 에서 진행.
deferred 사유: prod MLflow registry 에 baseline+current 데이터 보유 모델이 등록 돼 있는 상태가 prerequisite. seed 작업이 단일 worktree-ship turn 의 scope 를 초과 (자체 plugin install + train 1회 + drift baseline metadata 등록 등 다단계).
관련 문서
- 백엔드 알고리즘 / Iceberg 컬럼 / Notification 계약: Drift Monitoring
- ML Batch 잡: Batch Inference UI
- 감사 로그 검색: Audit Logs