Page는 무엇을 요청하는 알림인가

새벽 3시에 울리는 Page는 "시스템에서 이상을 발견했다"는 통지가 아닙니다. 지금 사람이 개입하지 않으면 사용자 피해가 커지고 호출받은 사람이 실제로 상황을 개선할 수 있다는 요청이어야 합니다.

그래서 CPU 사용률 80%, 메모리 90% 같은 숫자만으로 Page를 설계하면 문제가 생깁니다. 같은 CPU 90%라도 충분한 여유 용량과 자동 확장이 작동하고 사용자는 아무 문제를 겪지 않을 수 있습니다. 반대로 CPU는 평범해 보여도 결제나 로그인 같은 중요한 사용자 흐름이 실패하고 있을 수 있습니다.

사람에게 알릴지를 결정하려면 먼저 "얼마나 이상한가"가 아니라 세 가지를 물어야 합니다. 사용자가 실제로 피해를 받고 있는가. 그 피해는 얼마나 빨리 커지는가. 지금 사람이 할 수 있는 일이 있는가. Google SRE도 Pager를 사람의 시간을 비싸게 쓰는 수단으로 보고, 긴급하고 행동 가능하며 현재 또는 임박한 사용자 영향이 있는지를 Page 설계의 주요 질문으로 제시합니다.[1]

Page·Ticket·Dashboard는 우선순위인가

경보를 critical, warning, info로 나누는 것만으로는 실제 운영 방식이 정해지지 않습니다. 더 유용한 구분은 사람이 언제 행동해야 하는가입니다. Google SRE가 제시하는 구분도 이와 가깝습니다. 어떤 상황은 사람이 즉시 행동해야 하고 어떤 상황은 사람이 처리해야 하지만 며칠의 여유가 있으며 나머지는 나중의 진단을 위해 기록만 하면 됩니다.[1] 이 글에서는 이를 위 표의 세 가지 운영 경로로 정리합니다.

여기서 중요한 것은 Severity와 Route를 구분하는 것입니다. 문제가 기술적으로 심각해 보여도 사람이 지금 할 수 있는 일이 없다면 무조건 Page가 되는 것은 아닙니다. 반대로 현재 피해 규모가 작아도 시간이 지나면 빠르게 복구 불가능한 상태가 되고 지금만 취할 수 있는 완화 조치가 있다면 Page가 될 수 있습니다.

경로
의미
사람에게 요구하는 것
Page현재 또는 임박한 피해를 줄이려면 즉시 개입 필요하던 일을 중단하고 대응
Ticket / Work Queue사람이 해결해야 하지만 즉시 개입할 필요는 없음정해진 업무 시간·기한 안에 처리
Dashboard / Record Only현재 별도의 인간 행동을 요구하지 않음조사나 추세 분석 때 참고
Page·Ticket·Dashboard 세 운영 경로 — 사람이 언제 행동해야 하는가로 나눈 구분(Google SRE의 즉시 행동·며칠 여유·기록만 구분에 대응)
서비스 작동 방식

관측에서 복구와 개선까지 이어지는 운영서비스 지표와 경보를 기준으로 대응하고 변경 이력과 사후 보고를 다음 개선에 연결합니다.

Decision Matrix는 무엇을 보는가

Page 여부는 한 개의 Metric으로 결정하기보다 위 표의 조건을 함께 봐야 합니다. 이 Matrix에서 Page는 사실상 AND 조건에 가깝습니다. 사용자 영향 또는 임박한 피해, 짧은 Time to Harm, 자동 복구만으로 충분하지 않음, 지금 가능한 인간의 행동, 명확한 Owner, Page 비용을 감수할 만큼 믿을 수 있는 신호입니다. 몇 개 조건이 빠졌다면 Page보다 Ticket이나 Dashboard가 더 적절할 가능성이 높습니다.

판단 축
Page
Ticket / Work Queue
Dashboard / Record Only
User Impact중요한 사용자 기능에 실제 피해가 있거나 강하게 임박함아직 직접 피해는 작지만 방치하면 품질·안정성 문제가 됨사용자 결과에는 확인된 영향이 없음
Urgency지금 대응해야 의미가 있음다음 근무 시간이나 합의된 기한 내 대응 가능대응 시점이 정해질 필요 없음
Time to Harm대응이 늦어질수록 짧은 시간 안에 피해가 커짐피해까지 충분한 준비 시간이 있음현재 추세만으로 구체적인 피해 시점을 말하기 어려움
Auto-recovery자동 복구가 없거나 실패했거나, 자동 복구 중에도 피해가 계속됨자동 복구는 되지만 반복 원인을 사람이 개선해야 함정상적으로 자동 복구됐고 후속 작업도 필요 없음
Human Actionability지금 사람이 할 수 있는 완화·복구·우회·중단·에스컬레이션이 존재사람이 변경·정비·분석해야 하지만 즉시 할 필요 없음사람이 지금 해도 상황이 달라지지 않음
Ownership호출받을 명확한 서비스·팀·On-call Owner가 있음해결 책임자가 업무 큐에서 받을 수 있음특정 담당자에게 작업을 배정할 단계가 아님
Confidence / False Positive Cost사람을 중단시킬 만큼 충분히 신뢰할 수 있는 증거가 있음불확실성이 조금 더 높아도 조사 작업으로 받을 수 있음가설·이상 징후·진단용 데이터 수준
DependencyDependency 문제라도 우리 쪽에서 즉시 완화할 행동이 있거나 해당 Dependency Owner가 바로 대응해야 함Dependency 저하가 있지만 우회가 작동하거나 여유 있게 조치 가능원인 후보·상태 정보로만 필요
Repetition / Deduplication현재 Incident를 대표하는 Page 하나로 묶음반복되는 문제의 근본 개선 작업으로 전환같은 Incident의 세부 증상은 Context로 보존
Alert Routing Decision Matrix — 판단 축 아홉 개에 대해 Page·Ticket·Dashboard로 보내는 조건

User Impact와 Time to Harm을 함께 본다

사용자 영향이 있다는 사실만으로 모든 문제가 동일하게 긴급해지는 것은 아닙니다. 예를 들어 다음 주에 인증서가 만료된다는 사실은 분명 해결해야 할 문제입니다. 하지만 충분한 시간이 있고 자동 갱신 상태를 점검할 수 있다면 일반적으로 업무 큐에서 처리하면 됩니다.

반대로 저장 공간이 빠르게 고갈되고 있고 현재 증가 속도라면 다음 On-call 교대 전에 서비스 쓰기가 중단될 것으로 예상되며 자동 확장도 불가능하다면, 아직 사용자가 오류를 보지 않았더라도 Page가 정당화될 수 있습니다. Google SRE 역시 Paging을 이미 발생한 사용자 증상에만 한정하지 않고 확실하게 임박한 문제도 고려합니다.[6] 다만 Page로 연결되는 규칙은 단순하고 이해 가능해야 한다고 강조합니다.

따라서 disk > 80%보다 유용한 질문은 다음과 같습니다. 현재 증가 속도와 남은 여유를 고려하면 서비스가 위험 상태에 도달하기까지 얼마나 남았는가? 그 전에 자동 또는 예약된 조치가 가능한가? 이 차이가 고정 Threshold와 실행 가능한 Alert의 차이입니다.

자동으로 해결되는 문제라면 사람이 왜 필요한가

서버 한 대가 비정상 상태가 됐지만 Load Balancer가 해당 인스턴스를 제외하고 새 인스턴스가 정상적으로 대체됐다고 해 봅시다. 사용자가 영향을 받지 않았고 추가 조치도 없다면, 해당 사건이 관측 데이터로서 가치가 있더라도 그 자체로 사람을 깨울 이유는 약합니다.

문제가 반복되고 있다면 이야기가 달라집니다. 매일 여러 차례 인스턴스가 죽었다 살아나지만 서비스는 자동 복구되는 경우 Page보다 원인을 제거하기 위한 Ticket이 더 적절할 수 있습니다. 특히 사람이 Page를 받을 때마다 같은 명령을 실행해 정상화한다면 Alert를 잘 설계한 것이 아니라 수동 자동화를 운영하고 있는 셈입니다. Google SRE는 반복되는 Page의 대응이 기계적으로 정해져 있다면 그 대응을 자동화할 수 있는지 검토해야 한다고 지적합니다.[1]

자동 복구가 존재해도 Page가 필요한 경우는 있습니다. 자동 복구 자체가 실패했거나, 복구가 반복되는 동안 사용자가 계속 실패하거나, 자동 조치가 더 큰 장애로 번질 가능성이 있어 사람이 중단 여부를 결정해야 하는 경우입니다. Page의 질문은 "자동 복구가 있는가?"가 아니라 "자동 복구만으로 현재 위험을 충분히 통제할 수 있는가?"입니다.

사람이 할 수 있는 일이 없다면 Page의 목적은 무엇인가

외부 서비스가 장애를 일으켰다고 가정해 봅시다. 우리 서비스에서 다른 공급자로 전환하거나, 기능을 제한하거나, 큐에 작업을 보존하거나, 트래픽을 우회하거나, 고객 영향 범위를 줄이는 행동이 가능하다면 담당자를 호출할 이유가 있습니다.

하지만 담당자가 깨어나서 외부 Status Page를 바라보는 것 외에는 할 일이 없다면 Page 정책을 다시 검토해야 합니다. 단, 장애 공지·거래 중단·업무 승인처럼 기술 복구 외의 운영 의사결정이 즉시 필요하다면 그것도 유효한 Human Action입니다. 따라서 Actionability는 "엔지니어가 코드를 수정할 수 있는가"보다 넓습니다. 롤백, Failover, Load Shedding, 기능 비활성화, 트래픽 전환, 공급자 에스컬레이션처럼 지금 수행했을 때 피해를 줄일 수 있는 결정도 포함합니다.

구체적인 Incident 대응 순서와 Runbook 구성은 별도의 Incident Response 문제입니다. Alert 정책은 그보다 앞에서 "지금 사람을 불러야 하는가"까지만 결정하면 됩니다.

Owner가 없는 Page는 왜 책임 구조의 문제인가

#alerts 같은 공용 채널에 경보를 쌓아 두고 누군가 발견하기를 기대하는 구조는 Page라고 보기 어렵습니다. Page에는 최소한 서비스 또는 기능의 Owner가 있어야 하고 현재 On-call이 누구인지 시스템이 알 수 있어야 합니다. 외부 Dependency가 문제라면 어느 팀이 사용자 결과에 책임지고 어느 팀이 Dependency 자체를 담당하는지도 구분해야 합니다.

긴급한 서비스인데 아직 Owner가 정리되지 않았다면 중앙 On-call 같은 임시 경로로 보호할 수는 있습니다. 하지만 그것을 정상 운영 모델로 남겨서는 안 됩니다. Unowned Page는 Alerting Debt이 아니라 Ownership Debt이기 때문입니다.

False Positive는 왜 공짜가 아닌가

경보 조건을 민감하게 만들면 장애를 놓칠 확률은 낮아질 수 있습니다. 대신 정상 상황에서도 사람을 자주 깨우게 됩니다. 반대로 너무 둔감하게 만들면 Page 수는 줄지만 실제 장애를 늦게 발견합니다.

Google SRE Workbook은 이 문제를 Precision, Recall, Detection Time, Reset Time의 관계로 설명합니다.[2] 실제 의미 있는 사건만 얼마나 정확히 경보하는지, 놓치는 사건은 없는지, 탐지에 얼마나 걸리는지, 복구 후 얼마나 빨리 경보가 해제되는지를 함께 봐야 합니다.

Page에는 특히 Precision 비용이 큽니다. 반복되는 False Positive는 그 한 번의 방해로 끝나지 않습니다. 사람이 Pager 자체를 신뢰하지 않게 만들기 때문입니다. 그렇다고 모든 Page가 완벽한 확신을 기다려야 한다는 뜻도 아닙니다. Time to Harm이 매우 짧고 놓쳤을 때의 피해가 크다면 낮은 지연을 위해 어느 정도 불확실성을 받아들여야 할 수 있습니다.

Confidence 기준도 고정 숫자보다는 다음 Trade-off로 정해야 합니다. 오탐으로 사람을 깨우는 비용과, 이 문제를 몇 분 더 늦게 발견했을 때 발생할 피해 중 어느 쪽이 큰가?

Dependency 하나에 Page 수십 개가 울려야 하나

실제 장애에서는 하나의 원인이 여러 컴포넌트의 Alert를 동시에 일으키기 쉽습니다. 데이터베이스 연결 문제 하나가 API 오류, Queue 지연, Worker 실패, Health Check 실패, 사용자 오류율 증가로 이어질 수 있습니다. 이 모든 Alert가 각각 다른 Page를 만들면 사람에게는 다섯 개의 문제가 생긴 것처럼 보입니다.

Prometheus Alertmanager는 이런 상황을 위해 Deduplication과 Grouping을 제공하고 상위 Alert가 활성화돼 있을 때 관련 하위 Alert의 알림을 억제하는 Inhibition도 지원합니다.[3] 다만 Dependency 그래프를 지나치게 영리하게 만드는 것도 위험합니다. Google SRE는 시스템 구조가 계속 변하는 환경에서 복잡한 Dependency 기반 경보 계층을 유지하기 어렵다고 설명합니다.[1]

실무에서는 "정확한 Root Cause를 Alert 시스템이 알아내게 한다"보다 다음 목표가 현실적입니다. 한 Incident가 사람에게 하나의 대표적인 Page로 보이도록 하고 나머지 컴포넌트 신호는 조사 Context로 남깁니다. 경보 시스템은 진단 시스템 전체를 대신할 필요가 없습니다.

반복 Page는 Threshold보다 무엇을 먼저 묻나

반복 Alert가 많아지면 흔히 가장 먼저 Threshold를 높입니다. CPU 80%에서 시끄러우니 90%로 바꾸고 90%에서도 시끄러우면 지속 시간을 늘리는 식입니다.

일시적인 Spike나 Flapping을 줄이기 위해 일정 시간 조건이 지속됐을 때만 Alert를 활성화하거나 복구 직후 일정 시간 Firing 상태를 유지하는 기능은 실제로 유용합니다. Prometheus도 for와 keep_firing_for를 이런 목적으로 제공합니다.[3] 하지만 이것은 원래 Page가 필요하다는 판단이 맞을 때의 튜닝 방법입니다.

Page를 받을 때마다 아무 행동도 하지 않는다면 Threshold 문제가 아닙니다. Page를 받을 때마다 같은 작업을 한다면 자동화 문제일 수 있습니다. 한 장애가 열 개의 Page를 만들면 Grouping 문제입니다. 다른 팀이 이미 대응 중이라면 Routing이나 Inhibition 문제입니다. 조건식을 정교하게 만드는 것보다 Page의 존재 이유를 먼저 검토해야 합니다.

고정 CPU 80%는 왜 좋은 출발점이 아닌가

CPU와 메모리 사용률이 필요 없다는 뜻은 아닙니다. 이런 자원 지표는 장애 원인을 설명하거나 Saturation이 임박했는지 판단하는 데 중요한 자료입니다. 문제는 자원 사용률 자체가 사용자 피해와 1:1로 대응하지 않는다는 데 있습니다. 위 표의 두 상황을 비교하면 같은 CPU 숫자가 다른 결과를 만듭니다.

그래서 임계값은 "몇 %가 위험한가"가 아니라 어떤 조건에서 이 값이 실제 사용자 피해로 이어지고 그 전에 사람이 해야 할 일이 무엇인가를 검증한 뒤 정해야 합니다. Prometheus 역시 가능한 한 개별 원인을 모두 Alert로 만들기보다 사용자 고통과 연결된 증상을 상위 계층에서 Alert하고 작은 흔들림에는 여유를 둘 것을 권고합니다.[3]

상황
더 적절한 Route
CPU가 높지만 자동 확장이 정상 작동하고 사용자 지연·실패가 없으며 여유 용량도 충분함Dashboard / Record
자원 포화가 진행 중이고 자동 확장이 실패했으며 현재 속도라면 중요한 사용자 기능이 곧 영향을 받고 On-call이 용량·트래픽을 조정할 수 있음Page
같은 CPU 숫자가 다른 Route로 가는 두 상황 — 자원 사용률과 사용자 피해가 1:1로 대응하지 않는 예

몇 가지 상황을 실제로 분류하면 어떻게 되나

위 표의 여섯 상황에서 볼 수 있듯 Route를 결정하는 것은 Metric의 종류가 아니라 피해와 행동 사이의 시간 관계입니다. 구매 완료 실패와 임박한 용량 소진은 Page이고, 앞서 탐지된 인증서 만료와 매일 반복되는 Worker 재시작은 Ticket이며, 사용자 영향 없이 자동 대체된 인스턴스는 Dashboard입니다.

상황
Route
이유
구매 완료 실패가 실제 사용자에게 발생하고 있으며 자동 Rollback이 실패했다. On-call이 이전 버전 전환으로 피해를 줄일 수 있다.Page사용자 영향 + 짧은 Time to Harm + 즉시 행동 가능
인증서 만료가 충분히 앞서 탐지됐고 담당자가 업무 시간에 갱신 상태를 수정할 수 있다.Ticket행동은 필요하지만 즉시 개입할 이유 없음
인스턴스 하나가 재시작됐지만 트래픽은 정상 노드로 이동했고 자동 대체됐으며 사용자 영향이 없다.Dashboard / Record현재 필요한 인간 행동 없음
Worker가 매일 자동 재시작해 서비스 영향 없이 복구되지만 같은 문제가 반복된다.Ticket새벽 Page보다 반복 원인 제거 작업이 필요
외부 Dependency 응답이 나빠졌지만 Fallback이 정상 작동하고 사용자 성공률에는 영향이 없다.Dashboard 또는 Ticket원인 Context는 필요하지만 즉시 Page할 사용자 피해가 없음
용량 소진이 임박했고 자동 확장도 불가능하며 다음 근무 시간 전에 서비스 중단이 예상된다.Page아직 장애 전이어도 Time to Harm이 짧고 사람이 예방할 수 있음
여섯 가지 상황의 Route 판정과 이유 — 피해와 행동 사이의 시간 관계로 나눈 예

Page에는 최소한 무엇이 들어 있어야 할까

Page를 받은 사람이 다시 처음부터 상황을 해석해야 한다면 Alert 시스템이 해야 할 일을 사람에게 넘긴 것입니다. 좋은 Page에는 적어도 영향받는 서비스나 사용자 기능, 문제가 시작된 시점과 범위, 현재 담당자, 최초 대응을 위한 Runbook 또는 확인 지점, 관련 Dashboard, 같은 Incident를 묶기 위한 식별 정보가 있어야 합니다. Prometheus Alerting Rule도 Alert annotation에 설명이나 Runbook 링크 같은 추가 정보를 넣을 수 있도록 합니다.[3]

여기서 Alert가 Root Cause를 확정할 필요는 없습니다. "결제 실패율이 올라갔고 어떤 데이터베이스가 원인이다"까지 Alert가 추론하려다 보면 규칙이 지나치게 복잡해집니다. Page가 확실히 말해야 하는 것은 더 단순합니다. 무엇이 영향을 받고 있으며 왜 지금 사람이 필요하고 누가 응답해야 하는가.

운영 중인 Alert도 계속 재분류해야 하나

처음에는 충분히 가치 있던 Page가 시간이 지나면서 불필요해질 수 있습니다. 자동 복구가 추가될 수도 있고 Architecture가 바뀔 수도 있고 문제 자체가 흔해져 대응 방법이 완전히 정형화될 수도 있습니다. 반대로 Dashboard에서만 보던 신호가 실제 장애의 선행 지표라는 사실이 반복적으로 확인되면 더 높은 Route가 필요할 수도 있습니다.

Alert Rule Review에서는 "현재 Threshold가 맞는가?"보다 실제 발생 이력을 가지고 다음을 확인하는 편이 낫습니다. Page가 울렸을 때 사람이 실제 행동했는가. 사용자 피해가 있었거나 정말 임박했는가. 사람이 확인하기 전에 이미 자동 복구된 비율은 얼마나 되는가. 같은 Incident가 여러 Page를 만들지는 않았는가. 매번 같은 수동 대응을 반복하고 있지는 않은가. 담당자가 Page를 믿고 즉시 반응하는가.

Google SRE도 Page 빈도를 개별 Alert가 아니라 On-call의 지속 가능한 운영 부하 관점에서 추적합니다.[7] 지나치게 많은 Page는 실제 문제를 조사하고 개선할 시간을 빼앗습니다.

사람을 깨우기 전에 마지막으로 물을 질문은 무엇인가

Alerting 시스템의 목적은 시스템에 생긴 모든 이상을 사람에게 전달하는 것이 아닙니다. 운영에 필요한 데이터는 훨씬 많이 수집해도 됩니다. 원인을 찾기 위한 메트릭, 로그, 트레이스, Dependency 상태도 풍부할수록 유용합니다. 하지만 그 모든 신호가 사람의 수면이나 집중을 중단시킬 자격을 갖는 것은 아닙니다.

Page를 만들기 전에는 이 질문 하나가 남아야 합니다. 이 알림을 지금 받는 사람이 실제로 무엇을 해야 하며 그 행동을 아침까지 미루면 어떤 사용자 피해가 더 커지는가? 명확한 답이 있다면 Page 후보가 됩니다. 행동은 필요하지만 기다릴 수 있다면 Ticket으로 보내면 됩니다. 아무 행동도 요구하지 않는다면 Dashboard나 기록으로 남기는 편이 낫습니다.

경보의 품질은 얼마나 많은 이상을 발견하느냐보다, 정말 사람이 필요할 때 사람을 부를 수 있느냐에서 드러납니다.