모니터링 도구보다 먼저 정해야 하는 것은 사용자가 서비스에서 반드시 끝내야 하는 일과, 그 일이 성공했다는 증거다. 서버가 응답하고 CPU와 메모리에 여유가 있어도 사용자가 로그인하지 못하거나, 주문을 완료하지 못하거나, 업로드한 파일을 사용할 수 없다면 서비스는 신뢰할 수 있는 상태가 아니다.
인프라 지표는 문제가 생긴 이유를 설명하는 데 필요하다. 그러나 서비스 신뢰성의 최종 정의가 될 수는 없다. Google SRE는 모니터링에서 “무엇이 고장 났는가”라는 증상과 “왜 고장 났는가”라는 원인을 구분한다. CPU 포화나 데이터베이스 연결 오류는 원인일 수 있지만 사용자가 중요한 작업을 완료하지 못했다는 사실이 먼저다. HTTP 200 응답과 함께 잘못된 결과를 돌려주는 경우도 실패에 포함해야 한다. (Google SRE)
따라서 모니터링 설계 순서는 다음과 같아야 한다.
중요한 사용자 여정 → 성공 결과 → 시작·완료·실패 이벤트 → SLI → 측정 위치 → 필요한 계측 → 도구
도구를 먼저 정하면 이미 수집하기 쉬운 CPU, 메모리, 요청 수, 상태 코드가 대시보드를 채운다. 반대로 사용자 여정부터 정하면 어떤 데이터가 없고 어디를 새로 계측해야 하며 어떤 제품이나 저장 방식이 필요한지가 드러난다.
서버가 정상이어도 사용자는 실패할 수 있다
아래는 특정 기업의 실제 사례가 아니라, 측정 경계를 설명하기 위한 가상 예시다.
| 사용자 여정 | 시스템이 성공으로 오해하기 쉬운 신호 | 사용자가 겪은 실패 | 실제로 확인해야 할 결과 |
|---|---|---|---|
| 로그인 | 인증 API가 HTTP 200 반환 | 토큰 저장 또는 화면 초기화가 실패해 보호 화면에 들어가지 못함 | 인증된 화면이 실제로 사용 가능한 상태가 됨 |
| 주문·결제 | 결제 요청이 승인됨 | 주문 원장이 생성되지 않거나 영수증이 표시되지 않음 | 결제·주문·표시 상태가 일관되게 완료됨 |
| 파일 업로드 | 업로드 접수 API가 성공함 | 비동기 변환 작업이 실패해 파일을 열 수 없음 | 후처리를 마친 파일이 실제 사용 가능한 상태가 됨 |
| 검색 | 검색 API가 정상 응답함 | 오래된 색인이나 잘못된 필터로 필요한 결과를 찾지 못함 | 결과가 표시되고 정확성과 신선도 조건을 만족함 |
상태 코드가 유용하지 않다는 뜻은 아니다. 상태 코드는 요청 처리의 한 단계를 보여준다. 문제는 그 한 단계를 전체 사용자 결과로 확대 해석할 때 생긴다.
특히 비동기 작업에서는 accepted와 completed를 분리해야 한다. 큐에 작업을 넣은 순간은 중간 체크포인트일 뿐이다. 워커 실행, 외부 API 호출, 데이터 저장, 사용자에게 결과 제공까지 끝나야 여정이 완료된다.
1. Critical User Journey부터 고른다
Critical User Journey, 즉 중요한 사용자 여정은 사용자가 서비스의 핵심 가치를 얻기 위해 수행하는 일련의 작업이다. 온라인 상거래라면 상품 검색, 장바구니 추가, 구매 완료가 될 수 있다. 각 여정은 여러 컴포넌트와 요청으로 구성되기 때문에 기존 서버 로그 하나만으로 성공과 실패를 판정하기 어렵다. Google SRE도 무엇을 측정할지 정하기 전에 사용자에게 중요한 활동을 먼저 식별해야 한다고 설명한다. (Google SRE)
모든 화면과 API를 중요한 여정으로 지정할 필요는 없다. 다음 질문으로 먼저 범위를 좁힌다.
| 판단 기준 | 확인할 질문 |
|---|---|
| 사용자 가치 | 이 작업을 못 하면 사용자가 서비스를 이용한 목적을 달성할 수 없는가? |
| 피해 크기 | 실패하면 금전·데이터·권한·업무 지연 등 되돌리기 어려운 피해가 생기는가? |
| 사업 중요도 | 매출, 계약 이행, 고객 업무의 핵심 흐름과 직접 연결되는가? |
| 의존성 | 외부 인증, 결제, 메시징, 저장소 등 여러 시스템을 통과하는가? |
| 복구 난도 | 재시도만으로 해결되지 않거나 사람의 확인이 필요한가? |
| 도달 범위 | 많은 사용자가 이용하거나, 이용 빈도는 낮아도 실패 피해가 큰가? |
사용 빈도가 낮다고 중요하지 않은 것은 아니다. 월말 정산, 관리자 승인, 대량 데이터 제출처럼 자주 실행되지 않지만 실패했을 때 피해가 큰 여정도 있다.
Critical User Journey Canvas
| 항목 | 작성할 내용 |
|---|---|
| Journey Name | 사용자가 이해할 수 있는 동사형 이름. 예: 파일을 제출하고 처리 결과를 확인한다 |
| Actor | 이 여정을 수행하는 사용자·역할·시스템 |
| User Goal | 사용자가 얻으려는 최종 결과 |
| Start Boundary | 여정이 시작됐다고 볼 수 있는 관측 가능한 사건 |
| Completion Boundary | 사용자 목표가 달성됐음을 입증하는 사건 |
| Failure Boundary | 명시적 실패, 시간 초과, 잘못된 결과, 중간 상태 고착의 정의 |
| User Harm | 실패했을 때 생기는 실제 피해 |
| Valid Attempt | SLI 분모에 포함할 유효한 시도 |
| Excluded Attempt | 사용자 취소, 잘못된 입력 등 분모에서 제외할 조건과 이유 |
| Critical Segments | 사용자 유형, 지역, 기기, 테넌트 등 따로 확인해야 할 집단 |
| Dependencies | 여정이 의존하는 내부·외부 시스템 |
| Outcome Owner | 최종 결과의 정확성을 책임지는 팀 |
| Current Evidence | 현재 확보한 시작·완료·실패 이벤트 |
| Blind Spots | 아직 측정하지 못하는 구간과 그 영향 |
Completion Boundary는 “API가 응답했다”가 아니라 사용자가 얻으려던 상태가 만들어졌다는 증거여야 한다. 반대로 사용자가 의도적으로 취소한 여정을 서비스 실패로 집계해서도 안 된다. 분모에 무엇을 포함하고 제외했는지가 SLI 자체만큼 중요하다.
2. 여정을 Outcome·Event·SLI로 바꾼다
SLI(Service Level Indicator)는 서비스가 사용자에게 제공한 결과의 수준을 나타내는 측정값이다. 실무에서는 다음과 같이 좋은 이벤트와 유효한 전체 이벤트의 비율로 표현하면 재사용하기 쉽다.
계산식
사용자 여정 성공률 SLI
= 성공으로 확인된 유효 여정 수
÷ 측정 가능한 전체 유효 여정 수
Google SRE는 SLI를 먼저 “사용자에게 중요한 결과”로 명세한 뒤, 그 결과를 실제 데이터로 어떻게 측정할지를 별도의 구현 문제로 다룰 것을 권한다. 같은 SLI라도 서버 로그, 로드밸런서, 합성 테스트, 클라이언트 계측에서 서로 다른 방식으로 구현될 수 있고 각각 정확도·포괄성·비용이 다르다. (Google SRE)
OpenSLO 역시 SLI를 데이터 소스에서 지표를 읽는 방법으로 정의하고 good 또는 bad와 total을 분리해 표현한다. SLO의 목표값·평가 기간·경보 정책은 SLI와 별도 객체로 다룬다. (GitHub)
이 글에서는 SLI를 네 축으로 나눈다.
| SLI 축 | 답하는 질문 | 측정할 것 |
|---|---|---|
| 성공률 | 사용자가 중요한 일을 끝냈는가? | 완료된 유효 여정 / 전체 유효 여정 |
| 지연 | 사용자가 결과를 얻기까지 얼마나 걸렸는가? | 사용자 시작부터 실제 완료까지의 시간 분포 |
| 정확성 | 완료된 결과가 올바른가? | 업무 규칙과 불변 조건을 충족한 결과 / 확인한 결과 |
| 신선도 | 사용자가 본 데이터가 필요한 시점의 상태를 반영하는가? | 사용자 조회 시점과 원천 데이터·색인·집계 갱신 시점의 차이 |
여기서는 지연 기준이나 목표 성공률을 정하지 않는다. 먼저 시작과 끝을 일관되게 측정하고 분포와 원시 건수를 확보한다. 어느 수준을 목표로 삼고 어떤 기간에 평가할지는 후속 SLO 정책에서 결정한다.
Journey → Outcome → Event → SLI Mapping
| Journey | 사용자에게 필요한 Outcome | 주요 Event | 후보 SLI | 주의할 Blind Spot |
|---|---|---|---|---|
| 로그인 후 업무 시작 | 인증된 사용자가 보호 화면을 실제 사용할 수 있음 | login_submitted → session_created → protected_view_ready |
여정 성공률, 종단 간 완료 시간 | 외부 인증은 성공했지만 클라이언트 초기화 실패 |
| 주문·결제 완료 | 결제·주문 원장·영수증 상태가 서로 일치함 | checkout_submitted → payment_confirmed → order_committed → receipt_visible |
성공률, 완료 시간, 금액·상태 정확성 | 결제 승인 후 Webhook 실패, 중복 재시도 |
| 파일 업로드와 처리 | 파일이 접수되는 데서 끝나지 않고 실제 사용 가능함 | upload_started → upload_accepted → processing_started → file_ready |
최종 완료 성공률, 처리 시간 | 큐 적재 후 작업 유실, Dead Letter, 콜백 누락 |
| 검색 결과 확인 | 결과가 표시되고 필요한 데이터 범위와 최신 상태를 반영함 | search_submitted → results_rendered + index_watermark |
성공률, 표시 시간, 정확성·신선도 | HTTP 200 빈 결과, 오래된 색인, 일부 데이터셋 누락 |
| 승인 업무 완료 | 올바른 권한자가 승인했고 후속 상태가 반영됨 | approval_requested → approval_recorded → downstream_state_updated |
성공률, 완료 시간, 권한·상태 정확성 | 승인 기록은 있으나 후속 시스템 동기화 실패 |
이벤트 이름 자체는 조직마다 달라질 수 있다. 중요한 것은 하나의 여정 ID로 시작, 중간 단계, 최종 결과를 연결하는 것이다. 재시도가 발생하면 같은 시도를 여러 번 집계하지 않도록 멱등성 키나 상관관계 ID도 필요하다.
3. 어디에서 측정할지 정한다
사용자와 가까운 위치에서 측정할수록 실제 경험을 잘 반영하지만 구현 비용과 데이터 누락 가능성이 커질 수 있다. 서버 내부에서 측정하면 안정적으로 수집하기 쉽지만 요청이 서버에 도착하기 전의 실패나 클라이언트 화면 문제를 보지 못한다. Google SRE도 동일한 SLI 명세가 서버 로그, 브라우저 기반 합성 테스트, 클라이언트 계측으로 구현될 수 있으며 각각 다른 누락을 가진다고 설명한다. (Google SRE)
Measurement Point Comparison
| 측정 위치 | 잘 포착하는 것 | 놓치기 쉬운 것 | 적합한 사용 |
|---|---|---|---|
| 클라이언트 / 실제 사용자 측정 | 화면 표시, 사용자 네트워크, 브라우저·앱 오류, 실제 종단 간 지연 | 앱이 시작되지 않아 계측 코드도 실행되지 않은 실패, 차단된 SDK, 표본 편향 | 화면 사용 가능 여부와 실제 사용자 경험 |
| Edge / Load Balancer | 서버에 도달한 요청, 상태 코드, 네트워크 경계 지연, 백엔드 라우팅 | 화면 렌더링, 비즈니스 결과, 서버 이후 비동기 작업 | 사용자와 가까운 요청 성공·지연의 근사치 |
| Application Service | 업무 로직의 명시적 성공·실패, 오류 사유, 요청 처리 단계 | 요청이 서비스에 도달하기 전 실패, 클라이언트 사용 가능 여부 | 업무 의미를 가진 처리 결과 |
| Async Worker / Queue | 작업 시작·재시도·완료·고착·Dead Letter | 최초 사용자 시작과 최종 화면 표시 사이 연결 | 업로드 변환, 메시지 발송, 집계 등 비동기 여정 |
| Business Event / Data State | 주문 생성, 승인 기록, 정산 완료처럼 실제 업무 상태 | 사용자 화면에 결과가 전달됐는지, 이벤트 자체의 지연·누락 | 최종 완료와 정확성 증명 |
| External Dependency Boundary | 외부 인증·결제·메시징 호출 결과와 지연 | 외부 호출 이후 내부 저장·표시 실패 | 원인 분류와 공급자 영향 확인 |
| Synthetic Transaction | 실제 트래픽이 없어도 반복적으로 접근성과 주요 경로 확인 | 실제 사용자 분포, 실제 데이터 다양성, 일부 개인화 문제 | 낮은 트래픽 서비스, 완전 중단 탐지, 기본 종단 간 확인 |
한 위치만으로 모든 것을 판단하기 어렵다. 일반적으로는 사용자 결과를 입증하는 측정점과 실패 원인을 설명하는 내부 측정점이 함께 필요하다. 다만 로그·메트릭·트레이스 중 무엇을 선택할지는 별도 Signal Selection 문제다.
4. 자주 생기는 측정 사각지대
HTTP 200을 성공으로만 분류한다
HTTP 상태 코드는 프로토콜 처리 결과다. 응답 본문이 잘못됐거나, 일부 데이터만 반환했거나, 오류 메시지를 200으로 감싼 경우 사용자는 실패한다. Google SRE도 HTTP 200과 잘못된 콘텐츠가 함께 반환되는 경우를 암묵적 실패로 분류하며 이런 오류는 종단 간 확인이 필요하다고 설명한다. (Google SRE)
따라서 비즈니스 결과 코드, 화면 사용 가능 이벤트, 데이터 불변 조건 등 상태 코드 이외의 완료 증거가 필요하다.
비동기 요청의 접수와 완료를 혼동한다
202 Accepted, 큐 적재 성공, 작업 ID 발급은 여정의 완료가 아니다. 사용자에게 필요한 결과가 만들어지는 시점까지 같은 여정 ID를 유지해야 한다.
완료 이벤트가 오지 않을 때를 어떻게 처리할지도 정해야 한다. 명시적인 실패 이벤트만 집계하면 영원히 대기 중인 작업이 통계에서 사라진다. 결과 확정이 불가능한 상태는 성공으로 간주하지 말고 unknown 또는 stuck 상태로 별도 노출한다.
외부 Dependency 실패를 사용자 지표에서 제외한다
외부 결제나 인증 공급자가 실패했더라도 사용자는 해당 서비스를 사용하지 못했다. 사용자 여정 SLI에서는 실패로 남겨야 한다. 대신 실패 원인에 dependency를 표시해 내부 시스템 문제와 구분한다.
외부 공급자 책임이라는 이유로 사용자 결과에서 제거하면 내부 지표는 좋아 보이지만 실제 경험과 멀어진다. 종단 간 사용자 SLI를 유지하면서 컴포넌트·의존성 지표로 원인을 분리하는 편이 낫다. (Google SRE)
트래픽이 낮은데 비율만 본다
시도 수가 적은 서비스에서 한 번의 실패는 비율을 크게 흔든다. 반대로 해당 기간에 요청이 전혀 없으면 실패를 관측할 기회도 없다. Google SRE도 요청이 매우 적은 사용자의 가용성은 우연히 전부 성공하거나 한 번의 실패로 매우 낮아질 수 있다고 지적한다. (Google SRE)
낮은 트래픽에서는 다음 원칙이 필요하다.
- 비율과 함께 분자·분모의 실제 건수를 표시한다.
요청 없음을정상으로 바꾸지 않는다.- 기본 경로의 완전 중단은 합성 트랜잭션으로 보완한다.
- 실제 사용자 결과와 합성 테스트 결과를 같은 분모에 섞지 않는다.
- 목표값과 평가 기간은 충분한 데이터와 사용자 피해를 검토한 뒤 별도 정책에서 정한다.
측정하지 못한 여정을 성공으로 처리한다
클라이언트 이벤트 수집 장애, 샘플링, 잘못된 필터, 스키마 변경, 상관관계 ID 누락으로 결과를 알 수 없는 경우가 있다. 이때 관측되지 않은 이벤트를 성공으로 처리하면 계측 장애가 신뢰성 향상처럼 보일 수 있다.
SLI와 별도로 계측 포괄성을 확인해야 한다. 예상 시작 이벤트 대비 결과를 연결할 수 있는 비율, 이벤트 수집 지연, 스키마 오류, 미분류 결과 수를 함께 본다.
5. Instrumentation Gap Checklist
| 영역 | 점검 항목 |
|---|---|
| 여정 정의 | ☐ Actor와 사용자 목표가 명확하다 |
| ☐ 시작·완료·실패 경계를 시스템 컴포넌트가 아니라 사용자 결과로 설명할 수 있다 | |
| ☐ 사용자 취소·잘못된 입력 등 분모 제외 조건과 이유를 기록했다 | |
| 이벤트 연결 | ☐ 모든 유효 시도에 고유한 Journey ID 또는 상관관계 ID가 있다 |
| ☐ 재시도·중복 요청을 하나의 여정으로 정규화할 수 있다 | |
| ☐ 완료 이벤트뿐 아니라 실패·고착·결과 불명 이벤트를 구분한다 | |
| 비동기 처리 | ☐ 접수와 최종 완료를 다른 이벤트로 기록한다 |
| ☐ 큐·워커·Webhook·Callback 사이에 Journey ID가 전달된다 | |
| ☐ 처리 중 사라진 작업과 Dead Letter를 찾을 수 있다 | |
| 외부 Dependency | ☐ 외부 호출 실패가 사용자 여정 결과에 반영된다 |
| ☐ 공급자 실패와 내부 후속 처리 실패를 원인 코드로 구분한다 | |
| 정확성·신선도 | ☐ 상태 코드 외에 업무 결과의 정확성을 확인할 불변 조건이 있다 |
| ☐ 데이터 생성·색인·집계 시점 또는 Watermark를 기록한다 | |
| ☐ 일부 데이터만 처리된 부분 성공을 식별할 수 있다 | |
| 측정 포괄성 | ☐ 서버에 도달하지 못한 실패를 볼 측정점이 있다 |
| ☐ 클라이언트 계측이 실행되지 않은 경우를 보완할 방법이 있다 | |
| ☐ 실제 사용자 트래픽이 낮을 때 사용할 합성 확인 경로가 있다 | |
| ☐ SLI 비율과 함께 분자·분모·미분류 건수를 확인할 수 있다 | |
| 분류와 안전성 | ☐ 사용자·지역·기기·테넌트별 문제를 숨기지 않을 최소 세그먼트가 있다 |
| ☐ 개인정보나 비밀정보 없이 필요한 구분값을 수집한다 | |
| ☐ 높은 Cardinality가 집계·저장 비용을 무제한 늘리지 않도록 설계했다 | |
| 책임 | ☐ Outcome 정의 책임자와 계측 구현 책임자가 정해져 있다 |
| ☐ 이벤트 스키마 변경 시 SLI 영향 검토 절차가 있다 | |
| ☐ 측정 데이터가 끊겼을 때 이를 운영 문제로 처리한다 |
체크되지 않은 항목은 곧바로 특정 제품 구매 목록으로 바꾸지 않는다. 먼저 어떤 데이터가 왜 필요한지 계측 Backlog로 등록한다. 그다음 기존 로그나 이벤트로 해결할 수 있는지, 애플리케이션 변경이 필요한지, 별도 측정 인프라가 필요한지를 판단한다.
6. SLI를 다음 운영 결정으로 넘기는 방법
사용자 여정 SLI가 만들어졌다고 곧바로 경보나 배포 차단 규칙을 붙여서는 안 된다. 먼저 SLI의 의미와 데이터 품질을 다른 운영 정책이 사용할 수 있는 형태로 넘겨야 한다.
구조 다이어그램
Critical User Journey
↓
User Outcome
↓
Start / Completion / Failure Events
↓
SLI Specification
↓
SLI Implementation + Coverage Evidence
│
├─→ SLO Target·평가 기간·Error Budget
├─→ Alert 조건·긴급성·전달 대상
├─→ Logs·Metrics·Traces 등 Signal 선택
├─→ Incident Runbook
└─→ Deployment Gate와 Rollback 행동
OpenSLO도 SLI, SLO의 목표와 시간창, AlertPolicy를 분리된 구조로 표현한다. 이 분리는 특정 도구를 사용하기 위한 형식보다 측정 정의와 운영 결정을 섞지 않는 계약으로 이해하는 편이 유용하다. (GitHub)
Handoff Contract
| 다음 단계 | 이 글에서 넘겨야 할 입력 | 다음 글에서 결정할 것 |
|---|---|---|
| SLO·Error Budget | 여정 정의, good/total 이벤트, 측정 위치, 데이터 포괄성, 세그먼트, 결과 확정 방식 | 목표값, 평가 기간, 에러 버짓과 사용 정책 |
| Alert | 사용자 피해의 의미, 실패 사유 코드, 데이터 지연, 낮은 트래픽 특성 | 언제 사람을 깨울지, Page·Ticket·Dashboard 구분, 억제·중복 제거 |
| Deployment Gate | 배포 버전과 연결 가능한 SLI, 변경 전후 비교 가능성, 계측 정상 여부 | 배포 중단·승인·예외 조건과 정책 |
| Signal Selection | 조사해야 할 실패 구간과 측정점 | 로그·메트릭·트레이스·프로파일 중 어떤 신호를 어디에 둘지 |
| Incident / Rollback | 사용자 영향과 실패 여정, 영향 세그먼트 | 완화·복구·커뮤니케이션·롤백 또는 전진 복구 행동 |
이 단계에서 99.9% 같은 범용 목표를 넣을 이유는 없다. 목표 수치는 서비스의 사용자 기대, 피해, 현재 측정 데이터, 비용과 운영 책임을 함께 검토해 정해야 한다.
도구 선택은 측정 계약이 완성된 뒤다
사용자 여정과 SLI가 정의되면 모니터링 도구를 평가할 질문도 달라진다.
- 필요한 측정 위치의 이벤트를 수집할 수 있는가?
- 클라이언트와 서버, 비동기 작업, 외부 의존성을 하나의 여정으로 연결할 수 있는가?
- good events와 valid events의 분자·분모를 잃지 않고 계산할 수 있는가?
- 계측 누락과 결과 불명 상태를 숨기지 않는가?
- 사용자·지역·기기·테넌트별 문제를 필요한 수준까지 분리할 수 있는가?
- 배포 버전과 사용자 결과를 연결할 수 있는가?
- 측정 정의를 특정 제품 밖에서도 검토하고 이전할 수 있는가?
이 질문에 답할 수 없다면 기능이 많은 도구를 도입해도 대시보드만 늘어날 수 있다.
서비스가 신뢰할 수 있다는 말은 서버가 켜져 있다는 뜻이 아니다. 사용자가 중요한 일을 시작하고 올바른 결과를 필요한 시간 안에 얻을 수 있다는 뜻이다. 인프라 지표는 그 결과가 나빠진 이유를 찾게 해준다. 무엇을 신뢰성으로 볼지는 사용자 여정이 결정한다.