본문 바로가기

소프트웨어-이야기/인프라

프로메테우스로 이상 트래픽 감지하기 - 이동평균선, Z-Score, 표준편차

서비스를 운영하다 보면 API 트래픽이 갑자기 튀거나 급감하는 상황을 종종 만나게 된다.

하지만 단순히 “현재 트래픽이 어느 기준보다 크다/작다”로만 알림을 울리면, 서비스는 노이즈성 알럿에 시달리게 되고 운영자는 금세 피로에 빠진다.

이 문제를 해결하기 위한 대표적인 방법이 바로 이동평균선(Moving Average)과 표준편차 기반 (Z-Score 방식) 을 활용한 알럿 설정이다. 

 

1. 트래픽은 “요동치는 값”

API 요청 수, 초당 호출 수(rate), 에러율 등은 초 단위로 흐름이 급격히 변한다.
예를 들어 어떤 순간에는 갑자기 요청이 쏟아지고, 어떤 때는 잠깐 줄어든다.

이런 “순간값”에 바로 알럿을 걸면 아래 문제가 생긴다.

  • 순간 피크 → 불필요한 알럿 폭탄
  • 순간 감소 → 실제 장애가 아닌데 알럿 발생
  • 일시적 스파이크 → 운영자 피로도 증가

그래서 필요한 것이 바로 평균화(smoothing) 이다.
불규칙한 단기 변화는 걸러내고, “최근의 전체 흐름”을 보고 판단하는 것을 말한다. 

 

2. 이동평균선(Moving Average)이란?

“최근 일정 기간 동안의 값들을 모아서 평균낸 값”이다. 

예를 들어, 최근 1시간 데이터를 5분 단위로 잘라서 -> 각 5분의 평균값을 구하고 -> 그 12개의 평균을 다시 평균내면 → “지난 1시간의 대표 값”이 된다.

이게 이동평균선이다.

이 선은 트래픽의 전체적인 방향성(추세) 을 부드럽게 보여준다. 그래서 단기적인 튐(spike)과 진짜 이상 상황을 구분할 수 있다.

 

3. 왜 알럿에 이동평균선을 써야 하나?

 3-1. 순간 스파이크(노이즈)를 제거

트래픽이 순간적으로 증가해도, 평소 평균치가 크게 변하지 않는다면 알럿을 보내지 않는다.

 3-2. 진짜로 “비정상적인 증가/감소”를 감지

단기 rate(예: 최근 5분)와 장기 평균(예: 최근 1시간 이동평균)을 비교했을 때

  • 단기 rate ≫ 장기 평균 → 진짜 급증
  • 단기 rate ≪ 장기 평균 → 장애·트래픽 급감 가능성

이런 “평소 패턴 대비 이상치”를 정확히 잡을 수 있다.

 3-3. 서비스별 피크 시간대에도 안정적

일부 서비스는 이벤트 시간대에 트래픽이 평소보다 2~3배 오르는 경우가 있다.
이때 하드코딩된 임계값(threshold)을 쓰면 매일 알럿이 울린다.

하지만 이동평균선을 쓰면, “평소 그 시간대의 평균 대비 이상한지”를 기준으로 판단하기 때문에 자연스럽게 적응(adaptive)한다.

 

4. PromQL으로 이동평균선 구하기 

Prometheus에서는 아래 두 함수 조합으로 이동평균선을 구할 수 있다. 

avg_over_time(rate(api_calls_total[5m])[1h])

4-1. 각 함수 의미 이해하기 

rate(api_calls_total[5m]) 최근 5분 동안 초당 API가 몇 번 호출되었는지 5분 동안 30,000번 호출 → rate = 100 req/sec
rate(...)[1h] 이 rate 값을 1시간 동안 모아놓은 시계열(Time Series) 1시간 동안 5분 단위로 계산된 rate 값(12개)을 모은 것.
avg_over_time( … ) 이 12개의 rate 값을 평균낸다. 지난 1시간 동안의 평균 트래픽. 
즉, 이동평균선(baseline)이 된다. 

 

4-2. 실제 예시 데이터로 이해하기

아래는 1시간 동안 5분마다 API 호출수를 측정한 값이다.

구간 호출수 초당 rate
00~05 24,000 80
05~10 30,000 100
10~15 27,000 90
15~20 33,000 110
20~25 36,000 120
25~30 29,000 96.67
30~35 26,000 86.67
35~40 32,000 106.67
40~45 34,000 113.33
45~50 31,000 103.33
50~55 35,000 116.67
55~60 30,000 100
이동평균선 약 102 req/sec (12개의 평균 초당 rate)

마지막 값이 바로: "avg_over_time(rate(api_calls_total[5m])[1h])"의 결과이자, “지난 1시간의 평소 트래픽 패턴(baseline)”이다

 

4-3. 그림으로 이동평균선 이해하기

 
 

5. 표준편차 기반 (Z-Score 방식)을 사용하여 알럿 설정하기

5-1. 표준편차란?

숫자들이 평균에서 얼마나 벗어나 있는지를 보여주는 값이다.

  • 모두 평균 근처에 몰려 있으면 → 표준편차가 작다
  • 숫자들이 넓게 퍼져 있으면 → 표준편차가 크다

5-2. 왜 표준편차를 사용하는가? 

“평균에서 얼마나 벗어났는지를 ‘절대값이 아니라 상대적 크기’로 판단하기 위해서” 이다. 

  • 단순히 평균보다 100 증가 → 심각? 아닐 수도 있음
  • 평균보다 500 증가 → 심각? 트래픽 큰 서비스라면 정상임
  • 서비스마다, 시간대마다 데이터의 흔들림(변동성)이 다르기 때문

그래서 표준편차(흔들림의 크기) 를 기준으로 현재 값이 ‘보통 흔들림’의 몇 배나 벗어났는지를 계산한다.

그게 바로 Z-score 이다.

5-3. Z-Score이란? 

"평균에서 표준편차 몇 개만큼 떨어져 있는가"를 나타내는 값이다.
 
Z-Score = (현재값 - 평균) / 표준편차
 

통계적으로 Z 설정은 다음과 같다. 

  • Z > 2 → 상위 2.5% (이상 징후)
  • Z > 3 → 상위 0.1% (거의 확실한 이상)

이는 모니터링 업계에서 아주 널리 쓰는 기준이다.

5-4. 예시로 이해하기

평균만 보면 “얼마나 벗어났는지” 절대 크기만 알 수 있다. 표준편차를 쓰면 “그 벗어난 정도가 이 서비스에서 얼마나 비정상인지” 상대적으로 판단할 수 있다. 그래서 표준편차는 알럿의 정확도(precision)를 높여주는 핵심 지표다.

표준편차를 쓰면 “서비스 성격에 맞는 알럿”이 된다.

표준편차를 쓰지 않으면? 

  • 하드코딩된 숫자(threshold)로 판단 → 서비스별/시간대별 패턴을 반영하지 못함 
  • 일시적 트래픽 변화에도 알럿 폭탄 
  • 피크 시간대에 false positive 발생 
  • 야간 시간대에 false negative 발생 

표준편차를 쓰면? 

  • 트래픽의 “자기 자신의 평소 변동성” 기준으로 판단 
  • 서비스 고유의 리듬에 맞춰 적응하는(adaptive) 알럿이 됨 
  • 변동이 적은 서비스 → 민감하게 감지 
  • 변동이 큰 서비스 → 불필요한 알럿 억제 
  • Z-score 2~3 이상이면 → 통계적으로 이상치(Outlier)
상황 A: 트래픽이 안정적
(평소 변화 거의 없음)
  • 평균 = 100
  • 표준편차 = 5
  • 현재 rate = 120
(현재 - 평균) / 표준편차 = (120-100)/5 = 4
Z-score = 4 → “극도로 비정상”

120은 평균보다 20 높다.
20라는 숫자는 작은 것 같지만 이 서비스에서는 매우 큰 튐이다.

상황 B: 트래픽 변동이 큰 서비스
(흔들림이 심함)
  • 평균 = 1000
  • 표준편차 = 300
  • 현재 rate = 1200
(1200-1000)/300 = 0.66
Z-score = 0.66 → “전혀 문제 없음”
200 증가했다. 숫자만 보면 커 보인다.
하지만 이 서비스는 원래 하루종일 700~1300 왔다갔다 한다.

 

5-5. PromQL으로 알럿 조건 설정하기

# 지난 24시간 패턴 대비 2σ 초과
(
  rate(http_requests_total[5m])                                    # 현재값
  - avg_over_time(rate(http_requests_total[5m])[24h:5m])           # 평균
)
/ stddev_over_time(rate(http_requests_total[5m])[24h:5m])          # 표준편차
> 2                                                                # Z-Score가 2 초과하는지 확인

 

 

위 설정은 “최근 5분 트래픽이 평소(24시간) 패턴의 평균 대비 2 × 표준편차 이상 벗어났다면 알럿을 울려라.”는 것을 의미한다.