[MLOps 실전] Day 4: 모니터링과 드리프트 - 모델은 배포 후에 조용히 나빠진다
[MLOps 실전] Day 4: 모니터링과 드리프트 - 모델은 배포 후에 조용히 나빠진다
이 글은 AI(Claude)의 도움을 받아 작성하고, 작성자가 검토·편집했습니다.
서론: 배포는 끝이 아니라 시작이다
일반 소프트웨어는 배포 후 코드를 안 바꾸면 동작이 그대로다. ML 모델은 다르다. 코드가 그대로여도, 세상이 변하면 모델이 조용히 틀려간다. 사용자 행동이 바뀌고, 시장이 변하고, 새로운 패턴이 등장한다. 모델은 에러를 던지지 않고 그냥 점점 나쁜 예측을 낸다. 이 “조용한 실패”를 감지하는 것이 ML 모니터링의 핵심이다.
1. ML 모니터링의 두 층위
1
2
3
4
5
6
7
8
9
10
1. 운영 모니터링 (일반 서비스와 동일 — 대규모 시스템 Day 5):
지연(p99), 처리량, 에러율, 자원 사용량
→ "서비스가 살아있나"
2. 모델 품질 모니터링 (ML 고유):
예측 분포, 입력 데이터 분포, 실제 정확도, 드리프트
→ "모델이 여전히 맞나"
핵심: 운영 지표는 멀쩡한데 모델 품질만 무너지는 경우가 가장 위험
(시스템은 200 OK를 반환하지만 예측은 쓰레기)
2. 드리프트의 종류
모델이 나빠지는 원인을 구분해야 대응이 다르다.
1
2
3
4
5
6
7
8
9
10
11
12
데이터 드리프트 (Data/Covariate Drift):
입력 데이터의 분포가 변함
예: 신규 사용자층 유입으로 연령 분포가 바뀜
→ 입력이 학습 때와 달라짐
컨셉 드리프트 (Concept Drift):
입력-출력 관계 자체가 변함
예: 코로나로 "정상" 구매 패턴의 정의가 바뀜
→ 같은 입력인데 정답이 달라짐 (더 근본적)
레이블 드리프트:
타깃 분포가 변함 (예: 사기 비율이 급증)
3. 드리프트 탐지: 분포를 비교하기
학습 데이터(기준)와 현재 프로덕션 데이터의 분포를 통계적으로 비교한다.
1
2
3
4
5
방법:
- PSI (Population Stability Index): 분포 변화 정도를 수치화
PSI < 0.1 안정 / 0.1~0.25 주의 / > 0.25 심각한 드리프트
- KS 검정: 두 분포가 같은지 통계 검정
- KL 발산 / Jensen-Shannon: 분포 간 거리
1
2
3
4
5
6
7
8
9
10
def calculate_psi(baseline, current, bins=10):
# 기준 분포로 구간을 나누고, 각 구간 비율 변화를 합산
b_pct, _ = np.histogram(baseline, bins=bins)
c_pct, _ = np.histogram(current, bins=bins)
b_pct = b_pct / len(baseline) + 1e-6
c_pct = c_pct / len(current) + 1e-6
psi = np.sum((c_pct - b_pct) * np.log(c_pct / b_pct))
return psi # > 0.25 면 알림 (대규모 시스템 Day 5: 증상에 알림)
# Evidently, NannyML 같은 도구가 이를 자동화·시각화
4. 지연된 정답 문제
ML 모니터링의 가장 어려운 점: 실제 정확도를 바로 알 수 없다.
1
2
3
4
5
6
7
8
9
예: 대출 상환 예측 → 정답(상환 여부)은 6개월 뒤에야 확정
추천 클릭 예측 → 클릭은 즉시 알지만 "좋은 추천"은 장기 지표
→ "모델이 지금 정확한가"를 즉시 못 앎
대응:
- 즉시 알 수 있는 프록시 지표 모니터링 (예측 분포, 드리프트)
- 정답이 도착하는 대로 지연 평가
- 일부 샘플에 인간 레이블링으로 빠른 점검
이것이 드리프트(입력 분포)를 보는 이유다. 정답을 기다리지 않고 입력 변화로 위험을 조기 감지한다.
5. 무엇을 로깅할까
추후 디버깅·재학습·감사를 위해 추론을 기록한다.
1
2
3
4
5
6
7
8
9
10
11
def predict_and_log(features):
pred = model.predict(features)
# 추론 로그: 입력·출력·모델버전·시각 (LLM 앱 Day 5의 로깅과 같은 사고)
log_inference({
"timestamp": now(),
"model_version": model.version, # Day 3
"features": features, # 드리프트 분석용
"prediction": pred,
"request_id": request_id, # 나중에 정답과 조인 (분산 Day 5의 추적 ID)
})
return pred
이 로그가 드리프트 분석, 재학습 데이터, 그리고 “왜 그때 그런 예측을 했나”의 감사 근거가 된다.
6. 알림과 자동 대응
1
2
3
4
5
6
7
8
9
10
알림 설계 (대규모 시스템 Day 5의 원칙 재사용):
- 증상에 알림: 드리프트 임계 초과, 예측 분포 급변, 정확도(지연) 하락
- 행동 가능하게: "PSI 0.3, 재학습 검토 필요"
- 알림 피로 방지: 노이즈는 진짜 신호를 묻는다
자동 대응 단계:
1. 관찰: 대시보드·정기 리포트
2. 알림: 임계 초과 시 담당자 호출
3. 자동 재학습 트리거: 드리프트 감지 → 재학습 파이프라인 실행 (Day 5)
4. 폴백: 심각하면 이전 모델 버전으로 롤백 (Day 3)
7. Day 4 체크리스트
- 모델이 코드 변경 없이도 세상의 변화로 나빠짐을 이해했다.
- 운영 모니터링과 모델 품질 모니터링의 두 층위를 구분했다.
- 데이터 드리프트와 컨셉 드리프트의 차이를 파악했다.
- PSI 등으로 분포 변화를 탐지하고, 지연된 정답 문제에 프록시 지표로 대응했다.
- 추론 로깅과 증상 기반 알림·자동 대응 체계를 설계했다.
다음 편 예고
드리프트를 감지했다면, 모델을 다시 학습해 갱신해야 한다. 마지막 Day 5(시리즈 마무리)에서는 재학습과 CI/CD/CT — ML 시스템의 자동화 파이프라인을 완성하고 전체를 종합한다.
This post is licensed under CC BY 4.0 by the author.