서버 A의 평균 응답 시간이 100ms이고 서버 B는 300ms라면, 전체 평균은 200ms일까? 두 서버가 처리한 요청 수가 다르면 각 평균에 요청 수를 곱해 합친 뒤 전체 요청 수로 나눠야 한다. 평균값 두 개를 똑같이 한 표씩 세는 계산은 요청 한 건씩을 똑같이 세는 계산과 다른 질문에 답한다.
이 글의 요청 수와 지연 시간은 모두 설명용 합성 자료다. 같은 기간, 같은 응답 시간 정의로 측정한 서로 겹치지 않는 요청 묶음을 가정한다. 실제 AI 서비스나 서버의 성능 측정 결과가 아니다.
10건과 90건을 합치면 200ms가 아니라 280ms다
A가 처리한 10건은 모두 100ms, B가 처리한 90건은 모두 300ms였다고 하자. 요청 한 건을 관측 단위로 삼으면 다음과 같이 계산된다.
| 묶음 | 요청 수 | 시간 합계 | 묶음 평균 |
|---|---|---|---|
| A | 10건 | 1,000ms | 100ms |
| B | 90건 | 27,000ms | 300ms |
| 전체 | 100건 | 28,000ms | 280ms |
평균의 단순평균은 (100 + 300) ÷ 2 = 200ms다. 반면 전체 요청 평균은 (100 × 10 + 300 × 90) ÷ (10 + 90) = 280ms다. 300ms인 요청이 아홉 배 많기 때문에 전체 평균은 300ms에 더 가깝다. 시간 합계 28,000ms는 각 요청 시간을 더한 값이며, 요청이 병렬로 실행될 수도 있으므로 서버의 실제 경과 시간이 28초였다는 뜻은 아니다.
일반식은 전체 평균 = 각 묶음의 합계 총합 ÷ 각 묶음의 건수 총합이다. 합계 대신 정확한 묶음 평균만 있다면 ‘평균 × 그 평균에 포함된 건수’를 합계로 사용한다. Prometheus의 관측 합계·건수 설명도 이 두 값을 합산한 뒤 나눠 전체 평균을 구하는 구조를 제시한다.

원시 요청과 합계·건수를 같은 코드로 대조한다
다음 JavaScript는 위 합성 요청을 그대로 만들고 세 계산을 비교한다. Windows의 Node.js v24.15.0에서 본문 코드의 복사 텍스트를 실행해 아래 출력을 확인했다. 별도 패키지는 필요하지 않다.
const a = Array(10).fill(100);
const b = Array(90).fill(300);
const sum = xs => xs.reduce((total, x) => total + x, 0);
const mean = xs => sum(xs) / xs.length;
const groups = [a, b].map(xs => ({ count: xs.length, sumMs: sum(xs) }));
const totalCount = groups.reduce((n, g) => n + g.count, 0);
const totalMs = groups.reduce((n, g) => n + g.sumMs, 0);
console.log(JSON.stringify({
meanOfMeansMs: (mean(a) + mean(b)) / 2,
fromSumAndCountMs: totalMs / totalCount,
fromRawRequestsMs: mean([...a, ...b]),
totalCount,
totalMs
}));
{"meanOfMeansMs":200,"fromSumAndCountMs":280,"fromRawRequestsMs":280,"totalCount":100,"totalMs":28000}
280ms가 두 경로에서 같다는 것은 이 합성 입력에서 계산이 일치했다는 뜻이다. 실제 로그가 모든 요청을 포함하는지, 재시도가 중복으로 들어갔는지까지 이 코드가 확인해 주지는 않는다.
요청 평균과 사용자 평균은 목적부터 다르다
이번 A의 10건을 한 사용자, B의 90건을 다른 한 사용자가 보냈다고 해 보자. ‘관측된 요청 한 건의 평균 시간’은 280ms다. ‘두 사용자의 개인별 평균을 같은 비중으로 본 값’은 200ms다. 후자는 사용자 한 명에게 같은 비중을 주므로 요청을 많이 보낸 사용자가 더 큰 가중치를 갖지 않는다.
따라서 200ms라는 숫자만 보고 계산 오류라고 단정할 수는 없다. 보고서가 전체 요청 평균이라고 이름 붙였다면 잘못된 집계이고, 개인별 평균을 사용자 수로 평균낸 지표라면 그 정의와 대상 사용자 범위를 밝혀야 한다. 개인별 평균을 복원하려면 사용자별 합계·건수나 그에 해당하는 자료가 필요하다. 서버별 평균만으로 사용자별 경험을 복원할 수는 없다.
가중치 전에 확인할 것은 같은 분모인지다
- 같은 기간과 요청 집합인가: 서로 겹치는 시간 구간이나 중복 수집된 요청을 합치면 같은 건이 두 번 들어간다.
- 시간의 정의와 단위가 같은가: 첫 토큰까지 시간과 전체 응답 완료 시간을 합치거나 ms와 초를 그대로 섞지 않는다.
- 평균과 건수의 포함 조건이 같은가: 성공 요청만의 시간 합계를 전체 요청 수로 나누면 성공 요청 평균도 전체 요청 평균도 아니다. 실패·타임아웃을 어떻게 기록하는지 별도로 정한다.
- 반올림 전 값이 있는가: 화면에서 반올림된 평균에 건수를 곱하면 원래 합계를 정확히 되찾지 못할 수 있다. 가능한 경우 원래 합계와 건수를 보존한다.
- 0건과 관측 누락을 구별했는가: 0건인 묶음의 평균은 0ms가 아니라 정의되지 않는다. 누락된 자료도 0건으로 바꾸지 않는다.
JOIN 뒤 합계가 부풀 때의 사전 집계는 같은 사실이 여러 행에 반복되는 문제를 다룬다. 여기서는 각 묶음이 이미 올바르게 집계됐더라도 평균을 합치는 과정에서 요청 수를 잃으면 다른 값이 나온다는 점을 다뤘다. 원자료의 중복과 집계 단계의 가중치는 각각 확인해야 한다.
집계의 정의가 맞은 뒤 운영 이상을 해석하려면 LLM 품질 문제를 좁히는 운영 신호처럼 같은 요청의 지연·오류·문맥 조건을 함께 본다. 전체 평균 하나로 느린 요청의 꼬리나 원인을 설명할 수는 없다.
자주 묻는 질문
두 묶음의 단순평균이 맞는 때도 있나요?
두 묶음 모두 0건이 아니고 정확한 평균을 쓴다면, 건수가 같거나 평균값이 같을 때 전체 요청 평균과 일치한다. 세 묶음 이상에서는 차이가 상쇄돼 우연히 같을 수도 있다. 한 번 값이 같았다는 사실로 단순평균 방식을 일반화하지 않는다.
평균값만 있고 요청 수를 모르면 어떻게 하나요?
서로 다른 평균들을 어떤 비중으로 합칠지 정할 정보가 부족하다. 전체 요청 평균을 확정하지 말고 각 묶음의 합계·건수를 확보하거나, 묶음별 평균이라는 범위로 보고한다.
평균을 합친 공식으로 p95도 합칠 수 있나요?
그럴 수 없다. 평균은 합계와 건수를 통해 복원하지만 p95는 값이 정렬된 분포의 위치에 달려 있다. 그룹 p95에 요청 수를 곱해 평균내는 것으로 전체 p95를 계산했다고 하지 않는다.