알림 규칙을 처음 만들 때는 대개 숫자 하나로 시작합니다. CPU 사용률 80% 이상, 응답시간 2초 이상, 에러율 5% 이상처럼 넘으면 안 되는 값을 정하고, 지표가 그 값을 넘으면 메신저나 전화로 담당자를 부르는 구성입니다.
몇 달 운영하면 같은 규칙이 두 방향으로 어긋납니다. 점심시간처럼 트래픽이 매일 몰리는 시간대마다 울리는 알림은 곧 아무도 열어 보지 않습니다. 반대로 트래픽이 적은 밤에는 응답시간이 평소의 세 배가 돼도 2초 아래라 아무 알림도 오지 않습니다. 고정 값 대신 과거 데이터에서 "이 시간대의 평소"를 계산해 비교하는 방식이 동적 기준선이고, 많은 모니터링 도구가 이상 탐지(anomaly detection)라는 이름으로 제공합니다.
정적 임계값(static threshold)은 사람이 미리 정한 고정 값을 지표가 넘거나 밑돌면 알림을 보내는 방식입니다.
동적 기준선(dynamic baseline)은 과거 데이터의 수준과 변동 패턴으로 기대 범위를 계산하고, 현재 값이 그 범위를 벗어나면 이상 징후로 보고 알림을 보내는 방식입니다. 시간대와 요일 패턴을 반영하는지는 구현에 따라 다릅니다. 동적 임계값(dynamic threshold), 베이스라인 알림이라고도 부릅니다.

정적 임계값의 장점은 단순함입니다. 알림이 울린 이유가 "디스크 사용률이 90%를 넘었다"로 한 줄에 설명되고, 같은 데이터를 넣으면 언제나 같은 결과가 나옵니다. 디스크 용량, 컨테이너 메모리 한도, 인증서 만료일처럼 넘으면 실제로 무언가가 멈추는 값에는 정적 임계값이 가장 잘 맞습니다.
약점은 시간이 지나면서 드러납니다. 트래픽에는 하루 주기와 요일 주기가 있는데, 고정 값 하나로는 낮 정점과 밤 저점을 함께 다룰 수 없습니다. 서비스가 성장하면 1년 전에 정한 값이 지금의 평소 수준이 되기도 합니다.
조치할 필요 없는 알림이 쌓이면 알림 피로로 이어집니다. 알림 피로는 반복되는 알림에 무뎌져 진짜 장애 알림까지 흘려보내는 상태를 말합니다. Google SRE 책도 호출 알림은 모두 사람이 조치할 수 있는 것이어야 하고, 하루에 긴급하게 반응할 수 있는 횟수에는 한계가 있다고 설명합니다.
동적 기준선을 계산하는 기본적인 방식으로 이동 평균과 표준편차 밴드가 있습니다. 최근 일정 기간의 평균을 중심선으로 두고, 평균에서 표준편차의 몇 배 이상 떨어지면 이상으로 판단합니다. 몇 배로 둘지는 정해진 답이 없습니다. 값이 정규분포를 따른다면 평균에서 표준편차 3배 안에 약 99.7%가 들어가므로 3배를 출발점으로 삼을 수 있지만, 응답시간 같은 운영 지표는 한쪽으로 치우친 분포가 많아 실제 알림 빈도를 보며 조정합니다.
응답시간처럼 대부분은 빠르고 일부만 매우 느린 지표에는 표준편차 밴드가 잘 맞지 않습니다. 느린 요청 몇 건이 표준편차를 키워 밴드가 넓어지기 때문입니다. 응답시간 같은 지표에는 과거 값의 퍼센타일(전체 값을 크기순으로 정렬했을 때 몇 % 지점에 있는 값)을 경계로 쓰는 편이 덜 흔들립니다.
계절성은 지표가 일정한 주기로 반복하는 패턴입니다. 하루 주기만 반영하면 월요일 아침 정점을 일요일 아침과 같은 기준으로 판단하게 되므로, 요일 차이가 큰 서비스는 주 주기까지 반영해야 합니다. 월말 정산처럼 한 달 주기가 있는 업무는 학습 기간이 더 길어야 합니다.
그래서 동적 기준선에는 콜드 스타트(학습할 데이터가 부족해 기준선이 아직 믿을 만하지 않은 초기 구간)가 있습니다. 주 주기를 반영하려면 최소 한 주, 가능하면 여러 주의 데이터가 필요합니다. 신규 서비스, 새로 수집하기 시작한 지표, 아키텍처를 크게 바꾼 직후에는 과거 데이터가 지금과 맞지 않습니다. 콜드 스타트 구간에는 정적 임계값을 임시로 함께 걸어 두는 편이 안전합니다.
명절 연휴나 대규모 할인 행사처럼 평소와 다른 날에는 동적 기준선에서 오탐(문제가 없는데 울리는 알림)이 납니다. 더 큰 문제는 그날의 데이터가 학습에 들어가 다음 주 기준선까지 틀어지는 경우입니다. 장애가 난 구간의 이상 지표도 같은 방식으로 기준선을 흐립니다.
이때 조정할 수 있는 동작은 세 가지입니다. 알림 전송만 잠시 멈추는 것, 이상 여부 판정을 멈추는 것, 해당 구간을 학습 데이터에서 빼는 것입니다. 도구에 따라 세 동작이 따로 설정되므로, 하나를 켰다고 나머지가 함께 처리된다고 가정하지 말고 각각 확인합니다.
행사 기간에도 사용자 영향과 가용성을 보는 알림은 그대로 두고, 예상된 패턴 변화로 불필요하게 울리는 기준선 규칙만 조정합니다. 행사나 장애가 끝난 뒤에는 그 구간을 학습에서 빼거나 기준선을 다시 학습시킵니다. 배포 시각을 그래프에 표시해 두면 기준선 이탈이 배포 때문인지 바로 구분됩니다.
동적 기준선의 가장 큰 약점은 천천히 진행되는 악화입니다. 메모리 누수로 사용량이 하루 1%씩 오르거나 응답시간이 몇 주에 걸쳐 조금씩 늘어나면, 기준선도 같은 속도로 따라 올라갑니다. 매일 보면 평소 범위 안이라 알림이 울리지 않습니다. 천천히 진행되는 악화는 동적 기준선만으로는 잡기 어려워서, 넘으면 안 되는 정적 상한을 함께 두거나 이번 주 값을 4주 전 같은 시간대와 비교하는 규칙을 따로 만들어 보완합니다.

실무에서는 지표 성격에 따라 나눠 씁니다. 아래 표는 출발점으로 삼을 만한 기본값입니다.
응답시간 p95는 요청 100건 가운데 95번째로 빠른 요청의 응답시간입니다. 사용자가 참을 수 있는 한계는 정적 상한으로, 평소보다 느려진 변화는 동적 기준선으로 나눠 보는 것이 기본 조합입니다.
어느 방식이든 한 번 튄 값에 바로 알림을 보내면 오탐이 많아집니다. 조건이 일정 시간 이어질 때만 알림을 보내는 지속 시간 조건을 거는 것이 기본입니다. 대신 지속 시간만큼 탐지가 늦어지므로, 심각한 규칙일수록 짧게 둡니다. 트래픽이 적은 시간대에는 요청 몇 건만으로 비율과 분포가 크게 흔들리므로, 요청 수가 일정 수준 이상일 때만 판단하는 최소량 조건도 함께 둡니다. 다만 최소량을 어느 구간에서 확인할지는 판단 대상에 따라 다릅니다.
아래 예시는 정적 상한과 과거 시점 비교를 함께 쓰는 원리만 보여 주는 단순한 규칙입니다. 학습형 이상 탐지는 도구마다 구현이 다릅니다. Prometheus 알림 규칙 문법(2.x 이상)이고, 지표 이름과 service 라벨은 예시입니다.
groups:
- name: checkout-api
rules:
- alert: CheckoutLatencyHardLimit
expr: |
histogram_quantile(0.95,
sum by (le) (rate(http_request_duration_seconds_bucket{service="checkout"}[5m]))) > 2
for: 5m
labels:
severity: critical
- alert: CheckoutTrafficBelowLastWeek
expr: |
sum(rate(http_requests_total{service="checkout"}[5m]))
< 0.5 * sum(rate(http_requests_total{service="checkout"}[5m] offset 1w))
and sum(rate(http_requests_total{service="checkout"}[5m] offset 1w)) * 60 > 100
for: 15m
labels:
severity: critical
- alert: CheckoutMetricsAbsent
expr: absent(http_requests_total{service="checkout"})
for: 10m
labels:
severity: warning
CheckoutLatencyHardLimit 규칙은 checkout 서비스의 p95 응답시간이 2초를 넘는 상태가 5분 이어지면 알림을 보냅니다. CheckoutTrafficBelowLastWeek 규칙은 요청 수가 지난주 같은 시각의 절반 아래로 15분 동안 머물면 알림을 보내고, 지난주 같은 시각의 요청이 분당 100건 이하였던 시간대는 판단에서 뺍니다. 최소량 조건을 지난주 쪽에 걸었기 때문에 지금 요청이 0건으로 떨어져도 알림이 울립니다. CheckoutMetricsAbsent 규칙은 checkout 서비스의 요청 지표가 10분 동안 하나도 들어오지 않으면 알림을 보냅니다. 인스턴스 일부만 빠진 경우는 지난주 비교 규칙으로 잡습니다.
비교 기준이 지난주 한 시점이라는 점도 감안합니다. 지난주가 휴일이라 요청이 적었다면 기준도 낮아져 이번 주 하락을 놓칠 수 있고, 지난주가 대형 행사였다면 이번 주의 정상 트래픽에서 오탐이 납니다. 그래서 여러 주의 평균과 비교하도록 바꾸기도 합니다.
알림 등급은 탐지 방식이 아니라 사용자 영향과 대응 시급성으로 정합니다. 주문 수가 급감했다는 동적 기준선 알림은 바로 사람을 불러야 하고, 디스크 사용률 정적 알림은 계획된 정리 작업으로 처리할 수도 있습니다. 새로 추가한 기준선 규칙은 기존 장애 알림을 유지한 상태에서 별도 채널로 몇 주 검증한 뒤 운영 호출에 반영합니다.
알림이 울린 뒤의 흐름도 함께 설계합니다. 발생 조건의 지속 시간과 해제 조건은 별개라서, 값이 범위 경계를 오가면 알림이 반복해서 울렸다 풀립니다. 정상 범위에 일정 시간 머문 뒤에 해제하도록 두면 반복이 줄어듭니다. Prometheus에서는 2.42 버전부터 for와 별도인 keep_firing_for 설정으로 해제를 늦출 수 있습니다. 같은 원인으로 정적 알림과 동적 알림이 함께 울리면 서비스 단위로 묶어 한 건으로 받습니다. 알림 본문에는 현재 값, 기대 범위, 대상, 지속 시간, 바로 열어 볼 대시보드 링크를 담아 받은 사람이 다음에 볼 곳을 알 수 있게 합니다.
알림 규칙은 한 번 만들고 끝나지 않습니다. 한 달이나 분기에 한 번, 규칙별로 울린 횟수와 실제 조치로 이어진 비율, 알림 없이 지나간 장애를 함께 확인합니다. 아무도 조치하지 않은 알림은 지우거나 등급을 낮추고, 알림 없이 지나간 장애는 새 규칙을 만들 근거로 씁니다. 아키텍처를 크게 바꾼 뒤에는 동적 기준선을 다시 학습시킵니다.
모니터링 도구가 제공하는 이상 탐지 기능을 켜기 전에 아래를 확인하면, 켠 뒤에 알림이 쏟아지거나 지나치게 조용해지는 일을 줄일 수 있습니다.
과거 2 ~ 4주 데이터의 상위 퍼센타일 값에 여유를 더해 시작하는 방법이 있습니다. 디스크 같은 용량 지표는 증설에 필요한 시간을 기준으로 계산하는 편이 정확합니다. 하루 증가량에 증설까지 걸리는 일수를 곱해 필요한 여유 용량을 구하고, 남은 용량이 이 여유 용량보다 작아지는 사용률을 임계값으로 둡니다.
계절성 분해나 예측 모델을 쓰는 이상 탐지는 여러 주기가 겹친 지표에서 기준선을 더 정교하게 계산할 수 있습니다. 대신 알림이 울린 이유를 설명하기 어려워지고, 담당자가 이유를 납득하지 못한 알림은 무시되기 쉽습니다. 모델을 고르기 전에, 알림 하나를 받은 담당자가 다음에 무엇을 볼지 정해져 있는지부터 점검합니다.
동적 기준선은 지표가 평소와 얼마나 다른지를 기준으로 판단하고, 번레이트 알림은 SLO(서비스 수준 목표)가 허용한 에러 예산을 얼마나 빠르게 써 버리는지를 기준으로 판단합니다. 그래서 번레이트 알림은 SLO가 정해진 사용자 영향 지표(에러율, 응답시간 달성률)에 쓰고, 동적 기준선은 처리량이나 리소스 사용량처럼 SLO가 없는 지표의 이상 징후를 찾는 데 씁니다.
정적 임계값은 넘으면 실제로 무언가가 멈추는 값에, 동적 기준선은 시간대와 요일에 따라 평소 수준이 달라지는 지표에 씁니다. 동적 기준선은 학습 기간이 필요하고 서서히 나빠지는 변화를 정상 범위로 학습하므로, 정적 상한과 지속 시간 조건을 함께 둬야 알림 수와 놓치는 장애를 같이 줄일 수 있습니다.
와탭의 이상치 탐지에서 Automatic Baseline은 수집 서버가 지표별 임계값을 자동으로 계산하고, 사용자는 적용 대상과 지속 조건을 정합니다. 상승과 하락 패턴의 민감도를 직접 지정하려면 Adaptive Range를 씁니다. 지금 쓰는 알림 규칙 가운데 시간대마다 오탐이 나는 규칙이 있다면, 이상치 탐지 문서에서 Automatic Baseline과 Adaptive Range의 차이를 확인해 보세요.