부하 테스트 · 부하 모델과 지표(RPS·p95·에러율) · 이론
평균은 꼬리가 나빠지는 것을 감지하지 못한다
한 줄 요약
같은 로그를 보고도 평균만 보는 팀은 롤백을 결정하고, 중앙값만 보는 팀은 성공 사례로 발표하고, p99 만 보는 팀은 인시던트를 연다. 셋 다 같은 데이터를 봤다.
왜 이게 필요했나
요청 10,000건 중 9,900건이 50ms, 100건이 3,000ms 인 서비스를 보자. 평균은 79.5ms 다. 실제로 79.5ms 에 응답받은 요청은 단 한 건도 없다. 평균은 존재하지 않는 사용자를 묘사한다. p50 도 p95 도 p99 도 전부 50ms 이고, p99.9 만 3,000ms 다.
더 나쁜 것은 민감도다. 느린 100건이 3,000 → 6,000ms 로 두 배 나빠져도 평균은 79.5 → 109.5ms 밖에 움직이지 않는다. 평균은 꼬리가 나빠지는 것을 거의 감지하지 못한다.
실제 롤아웃 전후 숫자를 보면 결론이 갈리는 이유가 분명해진다. 평균 112 → 122ms(+9%), p50 99 → 54ms(−46%), p95 224 → 454ms(+103%), p99 309 → 678ms(+119%). 평균만 보면 소폭 악화, 중앙값만 보면 큰 개선, p95/p99 를 보면 심각한 회귀다.
어떻게 동작하나
p99 를 "1%의 불운한 사용자"로 이해하면 우선순위를 잘못 잡는다. 꼬리는 증폭된다. 요청을 n번 할 때 최소 한 번 p99 구간을 만날 확률은 1 − 0.99^n 이다.
| 호출 횟수 | p99 를 만날 확률 |
| --- | --- |
| 1회 | 1.0% |
| 5회 | 4.9% |
| 20회 | 18.2% |
| 50회 | 39.5% |
| 200회 | 86.6% |
대시보드 한 화면이 20개의 API 를 호출한다면 화면을 한 번 열 때 p99 지연을 만날 확률은 18% 다. 하루 200번 요청하는 활성 사용자라면 87% 가 하루에 한 번 이상 최악 구간을 겪는다. p99 는 소수의 불운한 사용자가 아니라 거의 모든 사용자의 일상이다. 그래서 한 화면이 20개를 호출한다면 서비스 하나의 목표는 99% 가 아니라 99.9% 여야 화면 수준에서 98% 가 나온다.
백분위는 합칠 수도 없다. 서버 A(9,900건 전부 50ms)의 p99 는 50, 서버 B(100건 전부 3,000ms)의 p99 는 3,000 이다. 단순 평균은 1,525ms, 요청 수 가중 평균은 79.5ms, 진짜 통합 p99 는 3,000ms 다. 세 숫자가 전부 다르고 앞의 두 개는 아무 의미가 없다.
현장에서 만나는 모습
부하 테스트 보고서에서 가장 자주 보이는 결함은 조건이 없다는 것이다. RPS 와 p95 만 적혀 있고 동시성도, 총 요청 수도, 언제 쟀는지도 없다. 그런 숫자는 다음 달에 비교할 수 없으므로 기준선이 아니다.
두 번째는 한 번만 재는 것이다. 같은 조건으로 세 번 돌리면 변동폭이 보이고, 그 변동폭보다 작은 차이는 개선이라고 부를 수 없다.
다음 실습에서 할 것
nginx 컨테이너를 부하 대상으로 띄우고 hey 로 스모크·워밍업·본 측정을 나눠 실행합니다. 도구 출력에서 RPS 와 p50/p95/p99 와 에러율을 직접 뽑아 JSON 으로 정리하고, 평균 대비 p95 배수를 계산한 뒤, 세 번 반복해 변동폭까지 포함한 기준선을 확정합니다.