학습 목표
point·contextual·collective 이상을 구분하고 메트릭에 맞출 수 있다.
rolling baseline·z-score·MAD로 단변량 이상탐지를 구성할 수 있다.
seasonality를 분해해 요일·시간 패턴의 false positive를 줄일 수 있다.
isolation forest로 다변량·unsupervised 이상탐지를 설명할 수 있다.
score → threshold → alert 연결과 precision·recall 트레이드오프를 판단할 수 있다.
문제 상황
cpu > 80%static rule — 매일 점심 피크에 false positive, on-call 무시 습관- 야간 배치 시간 정상 스파이크를 매번 page — contextual 개념 없음
- error rate가 천천히 상승해 threshold 밑에서 장애 — trend·collective 미탐
- CPU·latency·queue 각각은 정상인데 조합이 이상 — 단변량 rule로 못 잡음
- z-score 도입했더니 분산 큰 서비스에서 전부 alert — robust 통계 미사용
- “이상탐지 모델 붙였다”는데 precision 5% — threshold·평가 없이 배포
2편에서 rule vs ML과 파이프라인 detect 단계를 봤다. 이번 편은 그 detect를 어떻게 만드는지 — baseline → seasonality → multivariate 순서다. 여러 alert를 하나로 묶는 correlation은 5편.
1. 이상(anomaly)의 종류
“이상”은 하나가 아니다. 어떤 종류인지에 따라 탐지 방법이 갈린다.

| 종류 | 정의 | 예 |
|---|---|---|
| Point | 단일 값이 정상 범위 밖 | latency 1건 10s spike |
| Contextual | 값 자체는 정상, 맥락에서 이상 | 새벽 3시 트래픽 급증 |
| Collective | 개별은 정상, 연속 패턴이 이상 | error rate 완만한 우상향 |
- Point — static threshold·z-score로 대부분 처리
- Contextual — 시간·요일·deploy 등 context 필요 (seasonality, §3)
- Collective — window·trend·change-point — 한 점이 아니라 구간을 봄
- 메트릭마다 주된 이상 종류가 다름 — latency는 point·tail, 전환율은 collective가 흔함
2. Statistical baseline
가장 먼저 시도할 것은 모델이 아니라 통계다. 기대 범위를 만들고 벗어나면 flag.

| 방법 | 정의 | 주의 |
|---|---|---|
| Z-score | (x - mean) / std |
outlier가 mean·std 오염 |
| Rolling window | 최근 N개 평균·표준편차 | window 크기 = 반응성 vs 안정성 |
| MAD (robust) | median 기반 편차 | 분산 큰·스파이크 많은 신호에 강함 |
| EWMA | 지수 가중 이동평균 | 최근값 가중, trend 추종 |
# code/baseline_zscore.py (발췌)
import numpy as np
def rolling_mad_zscore(x, window=60, k=3.5):
"""Robust z-score with median absolute deviation."""
med = np.median(x[-window:])
mad = np.median(np.abs(x[-window:] - med)) + 1e-9
robust_z = 0.6745 * (x[-1] - med) / mad # 0.6745: normal-consistency
return robust_z, abs(robust_z) > k
- Robust 먼저 — 운영 메트릭은 스파이크·꼬리가 흔해 MAD·median이 mean·std보다 안전
- Window 크기 — 짧으면 민감(노이즈), 길면 둔감(느린 이상 미탐)
- 양측 vs 단측 — latency는 위쪽만, 처리량은 아래쪽(급감)이 문제인 경우
- 여기까지는 단변량·정상 상태 가정 — 계절성이 있으면 다음 단계
3. Seasonality
운영 메트릭 대부분은 요일·시간 주기가 있다. baseline이 이를 모르면 매 피크가 이상이 된다.

분해 — 관측값을 trend + seasonal + residual로 나눈다 (STL 등).
observed = trend + seasonal + residual
└── 이상탐지는 여기(residual)에 baseline 적용
| 성분 | 의미 | 이상탐지 활용 |
|---|---|---|
| Trend | 장기 추세 | 용량 계획, 완만한 상승 감지 |
| Seasonal | 주기 패턴(일·주) | 기대값으로 빼서 정규화 |
| Residual | 나머지 | 여기에 z-score·MAD 적용 |
- Deseasonalize — 관측에서 seasonal을 빼면 평평해져 threshold가 단순
- Multiple seasonality — 하루 + 주간 이중 주기 (예: 평일 vs 주말)
- Holiday·이벤트 — 프로모션·배포는 seasonal이 아닌 known event — enrich로 표시 (2편)
- Prophet·STL 같은 도구가 있지만 — 원리는 “기대 패턴 제거 후 잔차 감시”
4. Isolation Forest (다변량)
단변량으로 안 잡히는 조합 이상. CPU, latency, queue가 각각은 정상인데 함께는 드문 경우.

아이디어 — 랜덤 분할로 트리를 만들면 이상치는 더 빨리 고립된다. 평균 분할 깊이가 짧을수록 anomaly score↑.
# code/isoforest_multivariate.py (발췌)
from sklearn.ensemble import IsolationForest
clf = IsolationForest(
n_estimators=200,
contamination=0.01, # 기대 이상 비율(사전지식)
random_state=42,
)
clf.fit(train_X) # [cpu, latency, queue, rps]
score = -clf.score_samples(live_X) # 높을수록 이상
is_anomaly = clf.predict(live_X) == -1
| 특성 | 내용 |
|---|---|
| Unsupervised | 라벨 없이 학습 — 이상은 드물다는 가정 |
| 다변량 | feature 조합의 희소성 탐지 |
contamination |
기대 이상 비율 — threshold에 직접 영향 |
| 한계 | 해석 어려움, feature scaling·drift에 민감 |
- 왜 tree — 밀집 영역은 많이 쪼개야 분리, 이상치는 한두 번에 고립
- Feature — deploy·시간대 등 context를 넣으면 contextual 이상도 일부 포착
- 대안 — LOF, one-class SVM, autoencoder(재구성 오차) — 데이터·차원에 따라 선택
- 주의 — unsupervised는 “드묾 = 나쁨”이 아님 — 정상적 희귀 이벤트를 오탐할 수 있음
5. Score에서 Alert로
이상 점수를 뽑는 것과 page하는 것은 다르다. threshold·지속·평가가 붙어야 운영 가능.

| 단계 | 역할 |
|---|---|
| Score | baseline·model이 anomaly score 산출 |
| Threshold | score → boolean (contamination·percentile) |
| Debounce | for: N min·연속 M회 — flapping 방지 |
| Route | severity·service label → page·ticket (2편) |
- Precision vs recall — threshold를 높이면 precision↑ recall↓, 낮추면 반대
- 운영 우선순위 — page는 high precision, early-warning ticket은 recall 허용
- Hysteresis — 켜짐/꺼짐 threshold를 다르게 (예: on 3.5, off 2.5) — 진동 억제
- 평가 — 과거 incident로 backtest, F1·alert/day·MTTD로 threshold 튜닝
- 피드백 루프 — on-call의 “useful/not” 라벨을 모아 threshold·feature 개선 (closed loop, 2편)
# code/anomaly-detector.yaml (발췌)
detector:
metric: order_api_latency_p99
method: mad_zscore
window: 60
deseasonalize: daily
threshold:
warn: 3.0
page: 4.0
debounce: "3 consecutive intervals"
route:
page: { severity: page, team: order }
warn: { severity: ticket, team: order }
6. 방법 선택 가이드
| 상황 | 1차 선택 |
|---|---|
| 단변량·정상 상태·명확 임계 | static rule / z-score |
| 강한 요일·시간 주기 | deseasonalize + residual z |
| 스파이크·꼬리 많은 신호 | MAD (robust) |
| 여러 지표 조합 이상 | isolation forest 등 다변량 |
| 완만한 상승·구간 이상 | trend·change-point |
| 라벨 있는 과거 incident | supervised 검토 (다음 편들 맥락) |
- 단순한 것부터 — rule·z-score로 충분하면 모델을 추가하지 않음
- 설명 가능성 — page 경로는 “왜 울렸는지” 말할 수 있어야 함
- 데이터 품질 — 결측·단위 변화·재시작 gap이 모델보다 먼저 문제
7. 실무 체크리스트
| # | 질문 |
|---|---|
| 1 | 이 메트릭의 주된 이상은 point·contextual·collective 중 무엇인가 |
| 2 | baseline이 robust(MAD·median)한가 |
| 3 | 요일·시간 주기를 제거했는가 |
| 4 | 다변량이 필요한가, 단변량으로 충분한가 |
| 5 | threshold를 과거 incident로 backtest했는가 |
| 6 | page 경로가 high precision·설명 가능인가 |
정리
- 이상 종류(point·contextual·collective)에 따라 방법이 다름
- statistical baseline — robust(MAD)·rolling window부터, 모델은 그 다음
- seasonality 제거 후 residual에 탐지를 걸면 false positive 급감
- isolation forest — 라벨 없이 다변량 조합 이상 탐지
- score ≠ alert — threshold·debounce·평가로 precision을 확보
다음에 다룰 것
- 메트릭·로그 intelligence
- log classification, metric correlation, embedding search 개요
해당 내용은 Google SRE Workbook (Alerting on SLOs), scikit-learn Isolation Forest, STL decomposition 개념을 기반으로 합니다.
'AIOps & MLOps' 카테고리의 다른 글
| 메트릭·로그 intelligence (0) | 2026.07.06 |
|---|---|
| AIOps 개요 (0) | 2026.07.02 |
| AIOps · MLOps 오리엔테이션 (0) | 2026.07.01 |