한 줄 정의
p95는 측정값 100개를 빠른 순서대로 줄 세웠을 때, 대략 95개가 그 값 이하에 들어오고 5개가 그 값을 넘는 경계값이야. API 응답 시간에서 p95가 1.8초라면 “대부분은 1.8초 안에 끝났지만, 가장 느린 쪽 5%는 그보다 더 걸렸다”는 뜻에 가까워.
그래서 p95는 평균 속도보다 사용자 체감 지연을 더 잘 드러내는 경우가 많아. 평균은 아주 빠른 요청과 아주 느린 요청을 한 숫자로 섞어 버리고, 최대값은 단 한 번의 튐에 너무 쉽게 흔들려. p95는 그 사이에서 “느린 요청이 실제로 운영 판단을 흔들 만큼 쌓였나”를 보게 해주는 추론 운영 지표야.
어떻게 작동하나
먼저 같은 범위의 측정값을 모아야 해. 예를 들어 model=gpt-x, region=us, endpoint=/chat, window=5m처럼 범위를 잡고 각 요청의 지연시간을 남겨. 그다음 짧은 요청부터 긴 요청까지 정렬하거나, Prometheus나 Cloud Monitoring처럼 histogram bucket에 담긴 분포에서 95번째 지점을 추정해.
계산 방식은 도구마다 조금 달라. CloudWatch는 지정한 period 안의 데이터로 p95 같은 percentile statistic을 만들고, custom metric에서는 원시 데이터 포인트가 있어야 percentile을 제대로 계산할 수 있다고 설명해. Google Cloud Monitoring의 distribution metric은 bucket 안에서 percentile을 추정하기 때문에 bucket 폭과 sample count가 결과를 흔들 수 있어. Prometheus에서는 classic histogram이면 보통 bucket을 먼저 합친 뒤 전체 p95를 구해.
histogram_quantile(0.95, sum by (le) (rate(request_duration_seconds_bucket[5m])))
중요한 건 instance별 p95를 평균내지 않는 거야. 서버 A의 p95와 서버 B의 p95를 더해서 둘로 나누면, 실제 사용자 요청 전체의 95번째 지점이 아니게 돼. 전체 분포를 보려면 raw sample이나 histogram bucket을 합친 뒤 p95를 다시 계산해야 해.
왜 중요한가
LLM 서비스에서는 평균 지연이 좋아 보여도 p95가 튀면 사용자는 느리다고 느껴. 특히 긴 컨텍스트, 큰 배치, 부족한 GPU 메모리, KV 캐시 miss, 큐 대기, 첫 호출 JIT compile 같은 일이 느린 5%에 몰릴 수 있어.
그래서 p95는 새 런타임, 새 GPU 세대, BF16이나 FP8 경로, 양자화 설정을 비교할 때 같이 봐야 해. tokens/sec만 올랐는데 p95가 나빠졌다면 작은 benchmark에서는 빨라도 실제 요청 큐에서는 밀리고 있을 수 있어. 반대로 p95가 줄었지만 답변 품질이나 오류율이 나빠졌다면 그것도 성공이라고 보기 어려워.
AI 인프라 기사에서 전력, 칩 수, 데이터센터 면적 같은 숫자가 크게 보일 때도 마지막 판단은 서비스 지표로 돌아와. OpenAI API든 자체 로컬 LLM 서빙이든, 운영자가 같은 표에서 봐야 할 숫자는 p50, p95, p99, 첫 토큰 지연, 전체 응답 지연, 5xx, timeout, rate limit, 토큰/sec야.
실무에서 어떻게 재나
p95를 재기 전에 무엇의 지연인지 먼저 가르는 편이 좋아. 첫 토큰까지 걸린 시간인지, 마지막 토큰까지의 전체 응답 시간인지, embedding 요청인지, tool call까지 포함한 에이전트 실행 시간인지가 다르면 숫자를 섞을 수 없어.
작은 측정표는 이렇게 잡으면 돼.
- 같은 모델, 같은 region, 같은 endpoint끼리만 묶어.
- 입력 토큰 길이와 출력 토큰 길이를 bucket으로 나눠.
- p50, p95, p99, 평균, 최대값을 같은 window에서 봐.
- timeout과 retry를 성공 요청에서 빼지 말고 별도 오류율로 같이 둬.
tokens/sec, queue time, first-token latency, full-response latency를 나눠.- 배포 직후 5분 p95와 하루 p95를 따로 봐.
표본도 중요해. Google Cloud Monitoring 문서는 sample이 20개보다 적으면 95번째와 99번째 percentile이 같은 bucket에 들어갈 수 있다고 설명해. 그러니까 요청이 적은 새 기능에서 p95 한 줄만 보고 “꼬리가 잡혔다”고 말하면 위험해. 이때는 raw trace 몇 개를 직접 보고, histogram bucket 폭을 줄이거나 관측 기간을 늘려야 해.
헷갈리기 쉬운 경계
p95는 p99보다 덜 극단적인 tail 지표야. p99는 가장 느린 1%를 보니까 장애나 긴 꼬리에 더 민감하지만, traffic이 적으면 너무 흔들릴 수 있어. p95는 운영 dashboard의 기본 경보로 쓰기 좋고, p99는 더 깊은 장애 분석이나 enterprise SLA 쪽에서 같이 보는 편이 맞아.
p95가 낮다고 품질이 좋아졌다는 뜻도 아니야. 추론에서는 빠른 답변이 틀린 답변일 수 있고, 도구 호출이 빠져서 빨라진 것처럼 보일 수도 있어. 그래서 모델 변경이나 GPU 변경을 비교할 때는 p95 지연시간 옆에 task score, 오류율, 출력 길이, 비용을 같이 둬야 해.
마지막으로 p95는 사용자가 직접 느끼는 약속값이 아니라 관측 window 안의 통계값이야. “p95 1.8초”는 느린 5%를 허용한다는 말이지, 모든 요청이 1.8초 안에 끝난다는 보장이 아니야. 운영 문서에는 이 차이를 적어 두는 게 안전해.