Production ML Systems
프로덕션 ML 시스템
ML 시스템의 진짜 어려움은 모델이 아니라 인프라에 있다 — 서빙 아키텍처, 데이터 드리프트 탐지, 피드백 루프, MLOps 성숙도가 모델의 장기 가치를 결정한다.
Overview
모델을 학습하는 것과 모델이 가치를 만드는 것 사이에는 거대한 간극이 있다. 이 간극을 메우는 것이 프로덕션 ML 시스템이다. Google의 '모든 ML 코드의 95%는 인프라'라는 진단처럼, 실제 ML 시스템의 복잡도는 모델 코드가 아니라 그것을 둘러싼 파이프라인, 서빙, 모니터링 시스템에 있다.
프로덕션 ML 시스템이 모델 개발보다 어려운 이유가 몇 가지 있다. 데이터는 시간이 지나면서 변한다(Data Drift). 세상도 변한다(Concept Drift). 모델을 처음 배포할 때 성능이 좋아도, 6개월 후에는 성능이 저하될 수 있다. 이를 탐지하고 자동으로 재학습하는 시스템이 없으면 ML 시스템은 '한 번 배포하고 잊는' 레거시가 된다.
MLOps(Machine Learning Operations)는 이 도전을 체계적으로 다루는 방법론이다. CI/CD(지속적 통합/배포)를 ML에 적용하고, 데이터 파이프라인, 모델 학습, 배포, 모니터링을 자동화하는 것이 목표다. Claude Code 같은 AI가 코드를 잘 짜는 현재, AI 엔지니어에게는 이 시스템 레이어를 설계하는 능력이 더욱 중요해진다.
- 배치, 실시간, 스트리밍 서빙 아키텍처의 trade-off를 시나리오에 맞게 선택할 수 있다
- 데이터 드리프트와 컨셉 드리프트의 차이를 이해하고 탐지 방법을 설명할 수 있다
- 프로덕션 ML 시스템의 모니터링 전략을 설계할 수 있다
- MLOps 성숙도 레벨을 자신의 시스템에 적용해 개선 방향을 파악할 수 있다
Sections
모델 서빙 아키텍처의 세 패턴
배치 서빙(Batch Serving): 요청을 모아서 일괄 처리. 레이턴시 요구 없음. 예: 매일 밤 전체 사용자에게 추천 사전 계산, 다음날 제공.
적합 케이스: 레이턴시가 문제 없고 처리량이 중요할 때. 이미지 임베딩 사전 계산, 배치 리스크 스코어링, 오프라인 리포트 생성.
도구: Spark(대규모 배치), Ray(분산 Python), Apache Beam(스트림/배치 통합).
실시간 서빙(Real-time Serving): 단일 요청에 대한 즉시 응답. 레이턴시 <100ms 요구.
적합 케이스: 사용자 요청 시 즉시 추천, 실시간 사기 탐지, 이미지 검색.
도구: FastAPI + ONNX(경량 모델), Triton Inference Server(NVIDIA GPU 최적화), TorchServe, MLflow Serving.
스트리밍 서빙(Streaming Serving): 데이터 스트림에 대한 연속적 처리. Kafka 소비자 형태.
적합 케이스: 실시간 비디오 분석, 실시간 이상 탐지, 스트리밍 이벤트 처리.
실용적 아키텍처 결정: 대부분의 시스템은 배치와 실시간을 결합한 하이브리드다. '상품 임베딩은 배치로 사전 계산, 사용자 실시간 피처는 Online Feature Store에서 조회, 최종 랭킹은 실시간 추론'의 패턴이 이커머스 추천의 일반적 아키텍처다.
드리프트 탐지: 언제 모델이 낡는가
Data Drift(데이터 드리프트): 입력 데이터 분포 가 변화. 예: 코로나 이후 쇼핑 패턴 변화, 새 스마트폰 출시 후 사용자 디바이스 분포 변화.
Concept Drift(컨셉 드리프트): 입력-출력 관계 가 변화. 예: 경기 침체로 이전에 구매 신호였던 행동이 더 이상 구매로 이어지지 않음. 더 심각하고 탐지가 어렵다.
탐지 방법:
| 방법 | 탐지 대상 | 방법론 |
|---|---|---|
| Population Stability Index (PSI) | 입력 분포 변화 | 훈련 vs 서빙 분포 KL 거리 |
| KS Test | 연속 피처 분포 | Kolmogorov-Smirnov 검정 |
| Chi-square Test | 범주형 피처 분포 | 카이제곱 검정 |
| Model Performance Monitoring | 컨셉 드리프트 | 실제 레이블과 예측 비교 (느림) |
| Proxy Metrics | 컨셉 드리프트 | 레이블 없이 사용자 행동으로 추정 |
비전 데이터의 드리프트: 이미지 색상 분포, 해상도 분포, CLIP 임베딩 분포 변화를 모니터링. 의료 이미지에서 새 스캐너 도입 시 픽셀 강도 분포가 변하는 것이 전형적 케이스.
임계값 설정: PSI > 0.2이면 재학습 트리거. 단, 계절성이 있는 데이터에서는 정상적인 분포 변화와 문제적 변화를 구분해야 한다.
ML 모니터링 전략
프로덕션 ML 시스템의 모니터링은 세 레이어로 구성된다.
레이어 1: 인프라 모니터링
- CPU/GPU 사용률, 메모리, 디스크 I/O
- API 레이턴시(P50, P95, P99), 에러율
- 처리량(requests/sec)
Datadog, Prometheus+Grafana가 표준 도구.
레이어 2: 데이터 품질 모니터링
- 입력 피처 분포 변화(PSI, KS-test)
- 누락값 비율 변화
- 범위 이상 탐지(이미지 픽셀 범위가 갑자기 변하는 경우)
레이어 3: 모델 성능 모니터링
- 예측 분포 변화(모델이 평소보다 더 극단적인 값을 예측하기 시작하면 드리프트 신호)
- 실제 레이블과의 비교(레이턴시 있음 — 레이블은 늦게 들어온다)
- 비즈니스 메트릭(CTR, 전환율) 이상 감지
알림 설계 원칙:
- P99 레이턴시 > 500ms: 페이저(pager) 알림
- 예측 분포 PSI > 0.2: 경고 → 5일 내 재학습 계획
- 비즈니스 메트릭 -5% 이상 저하: 즉시 조사
알림이 너무 많으면 Alert Fatigue — 중요한 알림을 놓친다. 임계값을 신중하게 설정해야 한다.
MLOps 성숙도와 피드백 루프
Google의 MLOps 성숙도 모델은 0-2 레벨로 정의된다.
Level 0 (수동): 모델 학습/배포 모두 수동. 과학자가 노트북에서 실험하고 수동으로 모델을 업로드. 대부분의 초기 ML 프로젝트.
Level 1 (자동화된 학습): 데이터 파이프라인 + 학습 자동화. Feature Store, 자동 실험 추적(MLflow, W&B), 모델 레지스트리. 재학습은 스케줄 또는 드리프트 트리거로 자동화.
Level 2 (CI/CD): Level 1 + 자동화된 모델 배포. 새 모델이 shadow mode(트래픽 수신하되 결과 미사용) 테스트를 통과하면 자동 롤아웃. Canary 배포(5% → 20% → 100% 점진적 트래픽 전환).
피드백 루프(Feedback Loop) 설계:
프로덕션 데이터가 다시 훈련 데이터가 되는 루프. 이것이 데이터 플라이휠의 인프라 버전이다.
- 서빙: 모델이 예측을 내고 사용자에게 노출
- 수집: 사용자 행동(클릭, 구매, 스킵)을 이벤트 로그로 수집
- 레이블링: 행동을 레이블로 변환(구매 = 양성, 스킵 = 음성)
- 파이프라인: Feature Store에 새 학습 데이터 추가
- 재학습: 스케줄 또는 드리프트 트리거로 자동 재학습
- 검증: Shadow 모드에서 성능 검증 후 배포
경고: 피드백 루프 편향. 모델이 노출한 것만 사용자가 반응할 수 있다 — 모델이 특정 아이템을 노출하지 않으면 그 아이템에 대한 피드백은 수집되지 않는다. 이 Selection Bias가 재학습 데이터에 누적되면 모델이 점점 좁아진다(filter bubble). Exploration(랜덤 노출) vs Exploitation(최적 노출) 트레이드오프를 반드시 고려해야 한다.
프로덕션 ML 시스템은 자동차와 자동차 정비 시스템의 관계와 같다. 좋은 자동차 엔진(훈련된 모델)을 만드는 것은 시작일 뿐이다. 실제 도로에서 장기간 안전하게 달리려면 정비 시스템이 필요하다.
오일 경고등(모델 성능 모니터링)이 켜지면 즉시 확인해야 한다. 정기 점검(드리프트 탐지)으로 엔진 상태를 주기적으로 검사한다. 부품이 마모되면(데이터 드리프트) 교체(재학습)한다. 새 모델로 교체할 때는 시험 주행(Shadow mode, Canary 배포)을 거친다.
MLOps 성숙도는 정비 시스템의 자동화 수준이다. Level 0은 문제가 생기면 사람이 직접 정비하는 자가 정비. Level 1은 정기 점검을 자동으로 알려주는 스케줄러. Level 2는 마모를 감지하면 자동으로 부품을 주문하고 교체하는 완전 자동화 정비 시스템. 자동차가 비싸고 중요할수록(ML 시스템이 핵심 비즈니스일수록) 더 높은 수준의 정비 자동화가 필요하다.
PSI(Population Stability Index)로 입력 피처의 데이터 드리프트를 탐지하고, 재학습 트리거를 결정하는 패턴이다. 이것이 자동화된 드리프트 모니터링의 핵심 로직이다.
import numpy as np
from scipy.stats import ks_2samp
def calculate_psi(
baseline: np.ndarray,
current: np.ndarray,
n_bins: int = 10
) -> float:
"""
PSI(Population Stability Index) 계산.
PSI < 0.1: 안정적 (재학습 불필요)
0.1 <= PSI < 0.2: 경고 (모니터링 강화)
PSI >= 0.2: 드리프트 감지 (재학습 트리거)
"""
# 훈련 데이터 기준으로 구간 정의
breakpoints = np.percentile(baseline, np.linspace(0, 100, n_bins + 1))
breakpoints = np.unique(breakpoints)
baseline_counts = np.histogram(baseline, bins=breakpoints)[0]
current_counts = np.histogram(current, bins=breakpoints)[0]
# 0 방지 (Laplace smoothing)
baseline_pct = (baseline_counts + 1e-6) / len(baseline)
current_pct = (current_counts + 1e-6) / len(current)
psi = np.sum((current_pct - baseline_pct) * np.log(current_pct / baseline_pct))
return psi
# 시뮬레이션: 6개월 후 피처 분포 변화
np.random.seed(42)
baseline_feature = np.random.normal(loc=100, scale=20, size=10000) # 훈련 시 분포
# 시나리오 1: 정상 (약간의 자연 변화)
stable_feature = np.random.normal(loc=105, scale=22, size=2000)
# 시나리오 2: 드리프트 (경기 침체 영향)
drifted_feature = np.random.normal(loc=60, scale=30, size=2000)
psi_stable = calculate_psi(baseline_feature, stable_feature)
psi_drifted = calculate_psi(baseline_feature, drifted_feature)
print(f"PSI (안정적 케이스): {psi_stable:.4f} → {'재학습 불필요' if psi_stable < 0.1 else '경고'}")
print(f"PSI (드리프트 케이스): {psi_drifted:.4f} → {'재학습 트리거!' if psi_drifted >= 0.2 else '경고'}")
# KS-test로 추가 검증
ks_stat, ks_p = ks_2samp(baseline_feature, drifted_feature)
print(f"\nKS-test p-value: {ks_p:.6f} ({'드리프트 확인' if ks_p < 0.05 else '정상'})") PSI는 각 구간에서 훈련 분포와 현재 분포의 상대적 차이를 KL-divergence 방식으로 합산한다. PSI >= 0.2이면 재학습 파이프라인을 트리거한다. KS-test는 두 분포가 통계적으로 다른지 검정한다. 실제 시스템에서는 모든 피처에 대해 이 계산을 매일 실행하고, 임계값 초과 피처가 N개 이상이면 재학습을 시작한다. 비전 데이터에서는 CLIP 임베딩의 평균/분산 변화를 같은 방식으로 모니터링한다.
✅ 시니어가 보는 것
- 서빙 레이턴시 요구에 맞는 배치/실시간/스트리밍 아키텍처 선택 근거
- 데이터 드리프트와 컨셉 드리프트를 구분하고 각각에 맞는 탐지 전략 설계
- 피드백 루프에서 Selection Bias(filter bubble)를 인식하고 Exploration 전략으로 완화
- MLOps 성숙도를 현실적으로 평가하고 팀 역량에 맞는 개선 우선순위 설정
⚠️ 레드 플래그
- 모델 배포 후 모니터링 계획 없음 — '배포하고 잊는' 접근
- 재학습 주기를 '매일' 또는 '매주'로 고정 — 드리프트 기반 트리거를 고려하지 않음
- 피드백 루프의 Selection Bias를 인식하지 못함 — 필터 버블 문제 무시
🎤 예상 인터뷰 질문
- 배포 3개월 후 추천 모델의 CTR이 서서히 하락하고 있습니다. 어떻게 진단하고 해결하겠습니까?
- 비디오 스트리밍 플랫폼의 콘텐츠 추천 시스템에서 피드백 루프로 인한 filter bubble 문제를 어떻게 방지하겠습니까?
- ML 시스템에서 Canary 배포를 사용하는 이유와, 새 모델이 Canary에서 실패했을 때의 롤백 전략을 설명하세요.
Key Takeaways
95%는 인프라, 5%는 모델
Google의 진단처럼, 프로덕션 ML 시스템의 복잡도는 모델이 아니라 파이프라인, 서빙, 모니터링 시스템에 있다.
서빙 아키텍처 = 레이턴시 함수
배치(시간 여유), 실시간(<100ms), 스트리밍(연속 처리) — 레이턴시 요구가 아키텍처를 결정한다.
데이터 드리프트 vs 컨셉 드리프트
입력 분포 변화(PSI로 탐지)와 입력-출력 관계 변화(실제 레이블 필요) — 컨셉 드리프트가 더 심각하다.
피드백 루프의 Selection Bias를 경계하라
모델이 노출한 것만 피드백이 생긴다. 10-20% Exploration 없이 재학습을 반복하면 필터 버블이 강화된다.
MLOps Level 1이 현실적 목표
Level 2(완전 자동화 CI/CD)보다 Level 1(학습 자동화 + Feature Store + 모니터링)을 먼저 달성하는 것이 실용적이다.
Canary 배포로 위험을 줄여라
5% → 20% → 100% 점진적 트래픽 전환으로 새 모델의 프로덕션 위험을 최소화한다. 문제 발생 시 즉시 롤백 가능하다.