Report · 2026-08-08

p95와 p99,
평균이 숨기는 지연 시간

한마디로 p95는 “요청 100개 중 느린 쪽에서 5번째”, p99는 “100개 중 가장 느린 1개”의 응답 시간이다. p95 = 320ms라면 전체 요청의 95%가 320ms 안에 끝났고, 나머지 5%는 그보다 오래 걸렸다는 뜻이다.


01

지연 시간 분포를 그려보면

지연 시간 분포는 정규분포가 아니라 오른쪽으로 긴 꼬리(right-skewed)를 갖는다. 대부분의 요청은 빠르고, 소수가 아주 느리다. 분포를 그려보면 평균만 보면 안 되는 이유가 바로 보인다.

p50 평균 p95 p99 긴 꼬리 — 소수의 아주 느린 요청 응답 시간 → 빠름
전형적인 지연 시간 분포. 평균은 꼬리에 끌려 중앙값(p50)보다 오른쪽에 있지만, 실제 꼬리(p95·p99)가 얼마나 먼지는 전혀 말해주지 않는다.
02

왜 평균은 거짓말을 하나

평균은 “빠른 다수”와 “느린 소수”라는 두 세계를 하나의 숫자로 뭉개버린다. 극단적인 예로, 요청 100건 중 99건이 50ms, 1건이 5,000ms라면:

평균 = 99.5ms → 대시보드에서는 아주 건강해 보임

p99 = 5,000ms → 실제로는 100명 중 1명이 5초를 기다림

반대 방향의 함정도 있다. 캐시 히트 30ms / 미스 500ms처럼 분포가 두 덩어리(bimodal)로 갈라져 있으면, “평균 200ms”라는 값은 실제로 그 속도를 경험한 사용자가 한 명도 없는 숫자다.

03

p99가 특히 중요한 이유 — 꼬리 지연 증폭

“1%면 무시해도 되지 않나?”가 직관적인 반론이지만, 실제로는 그렇지 않다. 한 번의 페이지 로드가 백엔드 서비스 20개를 호출하고 사용자는 전부 응답해야 화면을 본다고 하면, 그중 하나라도 p99 꼬리에 걸릴 확률은:

1 − 0.9920 ≈ 18%개별 서비스의 1% 꼬리가 사용자 화면에서는 18%로 증폭된다

0% 10% 20% 30% 40% 0 20 40 50 (호출 수) 서비스 20개 → 18%
호출하는 서비스 수(N)에 따라 한 건이라도 p99 꼬리를 밟을 확률(1 − 0.99N)이 커진다. 팬아웃이 클수록 가파르게 증폭된다.

마이크로서비스나 팬아웃 구조일수록 심해지고, 이것이 구글이 말한 “tail at scale” 문제다. 게다가 느린 요청일수록 커넥션·스레드·메모리를 오래 붙잡고 있어서, 다른 요청까지 끌어내리는 경향이 있다.

04

실무에서 자주 틀리는 것들

1. 퍼센타일은 평균 낼 수 없다

서버 10대의 p95를 각각 구해서 평균 내면 그건 전체 p95가 아니다. 1분 단위 p99를 모아 평균 내도 1시간 p99가 아니다. 반드시 원본 분포(히스토그램/스케치)를 합쳐서 다시 계산해야 한다. Prometheus의 histogram_quantile, DataDog의 distribution 타입이 이런 이유로 존재한다.

2. 샘플 수를 확인하라

1분에 요청이 100건뿐이라면 p99는 사실상 데이터 포인트 1개다. 노이즈가 심해서 그래프가 요동친다. 이럴 땐 윈도우를 넓히거나 p95까지만 보는 게 낫다.

3. “어떤 p95냐”를 명확히 하라

전체 트래픽 기준 p95와 엔드포인트별·고객사별 p95는 완전히 다른 이야기다. 헬스체크 같은 초고속 요청이 섞여 있으면 퍼센타일이 통째로 낙관적으로 왜곡된다.

4. 백분위는 “사용자별”이 아니다

p99가 좋아 보여도, 요청을 많이 보내는 헤비 유저는 매 세션마다 꼬리를 밟는다. 사용자 단위 경험을 보려면 세션/유저 기준으로 다시 집계해야 한다.

05

그래서 뭘 봐야 하나

지표보는 목적
p50중앙값. 전형적인 사용자 경험 — 여기가 나빠지면 시스템 전반의 문제
p95SLO의 기본 축. 안정적이고 노이즈가 적음
p99꼬리 문제 조기 감지. GC, 락 경합, 콜드 스타트, 캐시 미스가 여기 먼저 나타남
p99.9대규모 팬아웃 시스템이나 내부 인프라 서비스에서만 의미 있음
max무시하지 말 것. 타임아웃 설정의 근거가 됨

SLO는 보통 이런 형태로 쓴다: “30일 동안 요청의 99%가 300ms 이내에 응답한다.” 여기서 “99%”와 “300ms”가 각각 p99와 임계값이고, 남는 1%가 에러 버짓이 된다.

그리고 p50과 p99를 같은 그래프에 겹쳐서 보는 습관을 들이면 좋다. 둘 다 올라가면 전체 부하 문제, p50은 그대로인데 p99만 벌어지면 특정 조건(느린 쿼리, 특정 샤드, GC pause)의 문제 — 원인 범위가 바로 좁혀진다.

99.5ms평균 (99×50ms + 1×5s)
5,000ms같은 분포의 p99
18%20개 팬아웃 시 꼬리 확률