검사 역설은 무작위로 도착한 사람이 재는 버스 간격이 시각표의 평균 간격보다 길게 나오는 현상이다. 긴 간격일수록 도착자가 그 안에 걸릴 확률이 커서, 기대 대기시간은 "평균의 절반"이 아니라 운행이 불규칙할수록 늘어난다.
시각표는 10분 간격인데 나는 왜 10분을 기다리는가

시각표에는 10분 간격이라고 적혀 있다. 그런데 정류장에 서서 시계를 재 보면 늘 10분 가까이 기다린다. 몇 번은 운이 나빴다고 넘길 수 있다. 한 달을 기록해도 평균은 5분으로 내려오지 않는다.
시각표가 틀린 것일까, 내 기록이 틀린 것일까. 답은 둘 다 옳다는 쪽이다. 시각표는 버스가 오는 간격의 평균을 적었고, 나는 내가 도착한 순간이 걸린 간격을 쟀다. 두 기록은 이름이 비슷할 뿐 서로 다른 것을 재고 있다.
이 어긋남에는 이름이 있다. 검사 역설(inspection paradox), 대기시간 쪽으로 좁혀 부르면 대기시간 역설이다. 기분 탓이 아니라 표본을 뽑는 방식이 만든 차이라서, 계산으로 그 크기를 정확히 짚을 수 있다. 이 글에서는 어긋남의 구조를 말로 세운 다음 식으로 옮기고, 마지막에 관찰자 100만 명을 직접 뿌려 그 식이 맞는지 검산한다.
긴 간격은 더 넓은 표적이다 — 길이 편향
버스가 지나간 자리를 시간축 위의 눈금이라고 하자. 눈금과 눈금 사이가 간격이고, 어떤 간격은 짧고 어떤 간격은 길다. 무작위로 도착한다는 말은 이 시간축 위 아무 데나 화살표를 한 번 꽂는다는 뜻이다.
여기서 갈린다. 간격을 세는 일과 간격을 재는 일은 다르다. 짧은 간격이 개수로 훨씬 많아도, 시간축에서 차지하는 폭이 좁으면 화살표는 그 위에 잘 꽂히지 않는다.
마스다와 포터가 든 예시가 이 차이를 깔끔하게 보여준다. 한 시간 동안 버스 9대가 다니는데, 4분 간격이 6번이고 12분 간격이 3번이다. 개수로 보면 짧은 간격이 두 배 많으니 4분 간격에 걸릴 확률은 6/9, 약 0.67처럼 보인다. 그런데 4분 간격 6개가 차지하는 시간은 24분이고, 12분 간격 3개가 차지하는 시간은 36분이다. 무작위로 도착한 사람이 4분 간격에 걸릴 확률은 24/60 = 0.40이다. 개수로는 짧은 쪽이 우세한데, 시간 폭으로는 긴 쪽이 우세하다.
그림 1에서 관찰자를 20명, 200명, 2,000명으로 늘리면 간격별 비율이 어디로 가는지가 드러난다. 2,000명 줄에서 4분 간격에 떨어진 비율은 0.399로, 앞서 계산한 시간 폭 비율 0.400에 거의 붙는다. 관찰자가 어느 간격에 걸릴 확률은 그 간격이 몇 개 있느냐가 아니라 그 간격이 얼마나 넓으냐를 따른다. 이것을 길이 편향(length-biased sampling)이라고 부른다. 이 예시의 기대 대기도 같은 방향으로 움직인다. 평균 간격의 절반으로 소박하게 추정하면 3분 20초인데, 실제 기대 대기는 4분 24초다.
기대 대기시간의 식 — 평균과 변동계수 두 숫자
말로 세운 구조를 식으로 옮겨 보자. 간격의 길이를 $X$라고 하면, 시각표가 말하는 것은 $X$의 평균 $E[X]$다. 내가 걸린 간격은 그냥 $X$가 아니라 길이에 비례해 뽑힌 $X$이므로 다른 이름을 준다 — $X_{obs}$.
이 기울임을 적분해 정리하면 다음 식이 나온다. 여기서 $CV$는 변동계수, 즉 표준편차를 평균으로 나눈 값이다.
걸린 간격의 길이를 알면 대기시간은 한 걸음이다. 길이 편향으로 간격 하나가 뽑히고 나면, 그 간격 안에서 내 도착 위치는 균일하게 흩어진다. 그러니 남은 시간의 기대값은 그 간격의 절반이다.
식 2가 이 글의 핵심이다. 평균 간격만으로는 대기시간을 못 구한다. 흩어짐이 반드시 함께 들어가고, 그것도 제곱으로 들어간다. $CV=0$인 완벽하게 규칙적인 운행에서만 익숙한 "평균의 절반"이 성립한다. 두 식의 출처도 분명히 해 둔다. 앞 절의 숫자 예시는 마스다와 포터의 것이지만, 식 1와 식 2는 그 논문의 식이 아니라 갱신이론(renewal theory)의 표준 결과다.
이 식은 두 가지를 가정한다. 하나는 간격이 정상 갱신과정을 이룬다는 것, 다른 하나는 관찰자가 시간축 위에 균일하게 무작위로 도착한다는 것이다. 시각표를 보고 도착 시각을 맞춰 나가면 두 번째 가정이 깨지고, 그만큼 편향도 줄어든다. 앱이 실시간 도착 정보를 알려줄 때 체감이 나아지는 이유가 여기에 있다.
식이 옮기는 것은 평균 하나가 아니다. 길이에 비례해 기울인 표본은 분포의 모양까지 통째로 오른쪽으로 밀려난다. 얼마나 밀리는지 그림으로 확인해 두자.
그림 2의 두 분포는 같은 버스를 재고 있다. 한 축 위에 겹쳐 놓았는데, 청록은 버스가 지나간 간격을 하나씩 센 것이라 왼쪽에 몰려 있고, 빨강은 무작위로 도착한 사람이 걸린 간격을 모은 것이라 오른쪽으로 밀려 있다. 평균선이 9.978분에서 19.945분으로, 정확히 두 배 가까이 밀린다.
직접 재 본다 — CV 0, 1, 2에서의 대기시간
식을 믿기 전에 재 보는 편이 낫다. 간격 20만 개를 이어붙인 시간축을 만들고, 그 위에 관찰자 100만 명을 균일하게 뿌린 다음 각자의 대기시간을 잰다. 경계 효과를 피하려고 시간축 앞뒤 5%는 관찰 구간에서 뺐다. 아래 표에서 볼 것은 평균이 아니라 흩어짐이 대기시간을 어디까지 끌고 가는지다.
import numpy as np
rng = np.random.default_rng(42)
N_GAP, N_OBS = 200_000, 1_000_000
def measure(gaps):
edges = np.concatenate([[0.0], np.cumsum(gaps)])
lo, hi = edges[-1] * 0.05, edges[-1] * 0.95
t = rng.uniform(lo, hi, N_OBS)
i = np.searchsorted(edges, t, side="right") - 1
w = edges[i + 1] - t
ex, cv = gaps.mean(), gaps.std() / gaps.mean()
return ex, cv, w, (ex / 2) * (1 + cv**2)
print(f"{'분포':<12}{'E[X]':>7}{'CV':>7}{'E[W] 실측':>10}{'E[W] 공식':>10}")
ex, cv, w, th = measure(np.full(N_GAP, 10.0))
print(f"{'결정론 10분':<12}{ex:>7.3f}{cv:>7.3f}{w.mean():>10.3f}{th:>10.3f}")
ex, cv, w_exp, th = measure(rng.exponential(10.0, N_GAP))
print(f"{'지수(평균 10)':<12}{ex:>7.3f}{cv:>7.3f}{w_exp.mean():>10.3f}{th:>10.3f}")
sigma = np.sqrt(np.log(1 + 2.0**2)) # 로그정규 CV=2 목표
mu = np.log(10.0) - sigma**2 / 2
ex, cv, w, th = measure(rng.lognormal(mu, sigma, N_GAP))
print(f"{'로그정규(CV=2)':<12}{ex:>7.3f}{cv:>7.3f}{w.mean():>10.3f}{th:>10.3f}")분포 E[X] CV E[W] 실측 E[W] 공식
결정론 10분 10.000 0.000 4.998 5.000
지수(평균 10) 9.978 1.000 9.966 9.974
로그정규(CV=2) 10.051 2.037 26.316 25.875세 줄을 나란히 놓고 보면 할 말이 분명해진다. 평균 간격은 셋 다 10분 언저리인데 기대 대기는 5분, 10분, 26분으로 벌어진다. 바뀐 것은 평균이 아니라 흩어짐뿐이다.
식과 실측이 얼마나 가까운지도 줄마다 다르다. 결정론 운행에서는 실측 4.998분이 공식 5.000분과 소수점 둘째 자리까지 맞고, 지수 간격에서는 9.966분과 9.974분이다. 로그정규 쪽은 실측과 공식이 둘 다 26분 언저리에서 만나지만 소수점까지 맞지는 않는다 — 꼬리가 무거운 분포라 20만 개로도 아직 수렴이 덜 됐다.
그림 3에서 실측점 셋이 모두 이론 곡선 위에 앉는다. 이 정도로 맞는다면 왜곡은 모형이 만들어 낸 것이 아니다. 아무 때나 무작위로 도착해서 재는 행위 자체가 만든 것이다.
푸아송 버스의 극단 — 이미 기다린 시간은 아무 정보도 주지 않는다
이 곡선 위에서 유독 이야기가 많은 자리가 하나 있다. $CV=1$인 지수 간격이다. 식 2에 넣으면 $E[W] = (E[X]/2)(1+1) = E[X]$가 된다. 평균 10분 간격 버스를 평균 10분 기다린다는 뜻이고, 소박한 직관의 정확히 두 배다.
여기서 한 걸음 더 나가면 직관이 한 번 더 뒤집힌다. 이미 5분을 기다린 사람은 남은 대기가 짧아졌다고 느낀다. 그럴 리 없다면 확인해 보면 된다. 앞의 관찰자 집합에서 $W>s$인 사람만 걸러 남은 대기를 다시 재 본다.
# 앞 블록의 지수 케이스 관찰자 대기시간 w_exp를 그대로 이어 쓴다
for s in (0, 5, 10, 20):
rest = w_exp[w_exp > s] - s
print(f"s={s:>2}분 기다린 뒤 남은 기대 대기 {rest.mean():.3f}분 (n={rest.size:,})")s= 0분 기다린 뒤 남은 기대 대기 9.966분 (n=1,000,000)
s= 5분 기다린 뒤 남은 기대 대기 9.960분 (n=605,816)
s=10분 기다린 뒤 남은 기대 대기 9.972분 (n=366,213)
s=20분 기다린 뒤 남은 기대 대기 9.956분 (n=134,441)20분을 기다린 사람에게 남은 기대 대기도 여전히 10분이다. 이것이 무기억성(memorylessness)이다. 기다린 시간은 앞으로에 대해 아무것도 말해 주지 않는다. 버스가 진짜 푸아송 과정으로 온다면, 정류장에서 20분을 버틴 사람과 방금 도착한 사람은 같은 처지다.
식 2는 $E[X^2]$가 유한할 때만 뜻이 있다. 꼬리가 무거워 2차 모멘트가 발산하는 분포에서는 우변이 무한대가 되고 식은 아무것도 알려주지 않는다. 위 표의 로그정규 행이 이미 그 방향을 보여준다 — 상대오차가 1.7%로 다른 두 행의 스무 배가 넘는다. 이 행의 값은 자릿수 수준으로만 읽고, 소수점을 그대로 인용하지 않는 편이 안전하다.
배차 간격의 평균만 알고 있으면 대기시간을 절반으로 착각하게 된다. 알아야 할 숫자는 둘이다 — 평균과 흩어짐. 실시간 도착 정보를 보고 나가는 것이 체감 대기를 줄이는 이유도 여기 있다. 도착 시각을 정보에 맞추는 순간 균일 무작위 도착 가정이 깨지고, 편향의 몫이 줄어든다.
같은 편향이 만드는 다른 이야기 — 친구 역설로
같은 기울임은 버스에만 붙지 않는다. 사람 관계로 옮겨 보자. 무작위로 고른 사람에게 친구 수를 물으면 평균이 나온다. 그런데 무작위로 고른 사람의 친구에게 물으면 평균보다 큰 값이 나온다. 친구가 많은 사람일수록 누군가의 친구 목록에 더 자주 등장하기 때문이다.
구조가 같다. 간격을 개수로 세느냐 폭으로 세느냐가 갈렸듯이, 사람을 개수로 세느냐 관계 수로 세느냐가 갈린다. 마스다와 포터가 버스와 친구 역설을 한 논문에 나란히 놓은 이유다. 콜센터 대기, 서버 응답, 강의실 수강 인원처럼 "무작위로 마주친 사례"를 재는 자리에는 같은 기울임이 숨어 있다.
이 글에서 얻은 것은 두 숫자다. 평균과 변동계수. 이 둘만 있으면 시각표가 적어 주지 않은 값, 내가 실제로 기다릴 시간을 계산할 수 있고, 버스에서 검산한 그 식이 버스 밖에서도 그대로 쓰인다. 다음에 어떤 평균을 볼 때 물어볼 것도 정해졌다 — 이 숫자는 무엇을 세어서 나온 것인가.
더 읽기
- Naoki Masuda, Mason A. Porter, "The Waiting-Time Paradox", arXiv:2007.05883 — https://arxiv.org/abs/2007.05883
- Sheldon M. Ross, Introduction to Probability Models — 갱신이론과 잔여 대기시간(inspection paradox) 장
- 버스는 왜 뭉쳐서 오는가 — 뭉침은 별개의 동역학이지만 CV를 키워 이 역설을 증폭시킨다