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



