룰렛 돌리기는 정말 공평할까 — 60만 번 돌려서 확인했습니다
점심 메뉴를 룰렛으로 정하다 보면 한 번쯤 의심이 듭니다. "이거 진짜 랜덤 맞나? 아까부터 계속 저기만 걸리는데."
돌림판 프로그램은 크게 두 가지로 나뉩니다. 당첨을 먼저 뽑고 거기까지 굴리는 방식과, 멈출 각도를 뽑고 그 각도가 가리키는 칸을 읽는 방식입니다. 꿀도구 룰렛은 뒤쪽입니다. 실제로 공평한지 600,000번 돌려 확인했습니다.

결과를 먼저 정하지 않는다
버튼을 누르면 두 개의 난수가 뽑힙니다. 하나는 몇 바퀴를 돌지, 다른 하나는 마지막에 어느 각도에서 멈출지입니다. 바퀴 수는 5바퀴에서 10바퀴 사이, 멈출 각도는 한 바퀴 안의 아무 지점입니다.
이 두 값을 더한 만큼 판이 돌고, 멈춘 뒤에야 바늘이 가리키는 위치를 거꾸로 계산해서 어느 칸인지 읽습니다. 당첨 항목을 미리 뽑아두고 그 자리에 맞춰 각도를 만드는 게 아닙니다. 실제 룰렛판과 순서가 같습니다.
차이가 중요한 이유가 있습니다. 결과를 먼저 뽑는 방식에서는 화면에 보이는 것과 실제 계산이 따로 놀 수 있습니다. 칸 넓이를 무시하고 균등하게 뽑아놓고는 애니메이션만 그럴듯하게 맞출 수도 있습니다. 각도부터 뽑는 방식에서는 그런 어긋남이 원리적으로 생기지 않습니다. 보이는 칸이 곧 계산 결과입니다.
바늘이 가리키는 각도를 구하는 계산에는 바퀴 수가 아니라 나머지 각도만 남습니다. 5바퀴를 돌든 10바퀴를 돌든 한 바퀴는 제자리로 돌아오기 때문입니다. 바퀴 수 난수는 사실상 연출용이고, 결과를 정하는 것은 두 번째 난수 하나입니다.

600,000번 돌려본 결과
도구가 쓰는 계산식을 그대로 옮겨 6칸짜리 룰렛을 600,000번 돌렸습니다. 이전 회전이 쌓인 상태에서 이어 돌리는 것까지 똑같이 재현했습니다.
| 칸 | 기대 확률 | 실측 | 차이 |
|---|---|---|---|
| 1번 | 16.67% | 16.68% | +0.02%포인트 |
| 2번 | 16.67% | 16.67% | +0.01%포인트 |
| 3번 | 16.67% | 16.62% | -0.05%포인트 |
| 4번 | 16.67% | 16.73% | +0.07%포인트 |
| 5번 | 16.67% | 16.67% | -0.00%포인트 |
| 6번 | 16.67% | 16.62% | -0.04%포인트 |
가장 크게 벗어난 칸도 0.07%포인트 차이입니다. 600,000번을 던지면 동전 앞뒤조차 이 정도는 흔들립니다. 어느 칸이 유리하다고 볼 근거는 없습니다.
그럴 수밖에 없는 이유는 단순합니다. 멈출 각도가 한 바퀴 안에 고르게 퍼져 있으면, 어떤 칸에 걸릴 확률은 그 칸이 차지한 각도의 비율과 같아집니다. 6칸을 똑같이 나눴으니 각 칸은 60도씩, 전체의 16.67%입니다. 시뮬레이션 결과가 그 값 주변에 모이는 것은 당연한 일입니다.
느려지는 연출은 결과를 바꾸지 않는다
돌아가는 판이 끝에서 천천히 멈추는 것을 보면 "거의 다 와서 한 칸 더 밀렸다"는 느낌을 받습니다. 그래서 감속 방식이 결과에 영향을 준다고 생각하기 쉽습니다.
그렇지 않습니다. 멈출 위치는 버튼을 누른 순간 이미 정해집니다. 4초 동안의 애니메이션은 그 위치까지 어떻게 가는지를 그릴 뿐입니다. 처음엔 빠르고 끝으로 갈수록 느려지는 곡선을 쓰지만, 그 곡선을 다른 것으로 바꿔도 도착점은 같습니다.
칸 경계를 지날 때마다 나는 딸깍 소리도 마찬가지입니다. 지금 그려지고 있는 각도를 보고 소리를 낼 뿐, 어디서 멈출지에는 관여하지 않습니다.
난수의 품질도 짚어둘 만합니다. 이 룰렛은 브라우저의 암호학적 난수 발생기를 씁니다. 게임 점수나 시각 정보에서 값을 만들어내는 방식이 아니라, 운영체제가 모아둔 예측 불가능한 재료로 만든 값입니다. 4,294,967,296가지 중 하나를 뽑아 각도로 바꾸므로 각도 해상도는 1도의 천만 분의 1 수준입니다. 사람 눈으로 구분할 수 있는 범위를 한참 넘어섭니다.
엄밀히 따지면 아주 미세한 치우침은 있습니다. 4,294,967,296는 6로 나누어떨어지지 않아서 4개 칸이 값 하나씩을 더 갖습니다. 비율로는 715,827,882분의 1, 즉 7억 번에 한 번 더 나오는 수준입니다. 현실의 룰렛판이 미세하게 기울어져 있을 확률이 훨씬 큽니다.

비중을 주면 그만큼만 늘어난다
항목마다 비중을 1에서 10까지 줄 수 있습니다. 비중을 올리면 그 칸이 차지하는 각도가 그만큼 넓어지고, 확률도 정확히 같은 비율로 올라갑니다.
첫 항목에만 비중 3을 주고 나머지 셋은 1로 두면 전체 비중이 6이 되어 첫 항목이 절반을 차지합니다. 같은 방식으로 600,000번 돌린 결과입니다.
| 항목 | 비중 | 기대 확률 | 실측 |
|---|---|---|---|
| 1번 | 3 | 50.00% | 49.93% |
| 2번 | 1 | 16.67% | 16.67% |
| 3번 | 1 | 16.67% | 16.62% |
| 4번 | 1 | 16.67% | 16.78% |
비중을 쓸 때 헷갈리기 쉬운 점이 하나 있습니다. 비중 3은 "3배 확률"이 아니라 "전체 6 중 3"이라는 뜻입니다. 다른 항목이 몇 개인지에 따라 같은 비중이라도 확률이 달라집니다. 항목이 열 개인데 하나만 비중 3을 주면 그 항목은 절반이 아니라 25.0%가 됩니다.
- 연속으로 같은 게 나와도 이상하지 않다 — 6칸에서 같은 칸이 세 번 연달아 나올 확률은 2.78%입니다. 서른 번쯤 돌리면 대개 한 번은 겪습니다.
- 기록을 보면 감이 잡힌다 — 결과 기록이 최근 20개까지 남습니다. 치우친 느낌이 들 때 실제로 그런지 세어보면 대개 착각입니다.
- 정말 균등하게 하고 싶으면 비중을 건드리지 않는다 — 비중을 한 번이라도 조정했다면 초기화 버튼으로 전부 1로 되돌릴 수 있습니다.
- 항목이 적을수록 결과가 튄다 — 두세 칸짜리 룰렛은 몇 번 돌려서는 한쪽에 몰린 것처럼 보입니다. 확률은 그대로인데 횟수가 적어서 생기는 착시입니다.
실제로 몰린 것처럼 보이는 대부분은 기억의 문제입니다. 같은 항목이 연달아 나온 순간은 또렷하게 남지만 골고루 나온 구간은 그냥 지나갑니다. 6칸 룰렛을 스무 번 돌리면 어떤 칸은 여섯 번, 어떤 칸은 한 번도 안 나오는 일이 흔합니다. 평균이 세 번 조금 넘는 상황에서 그 정도 들쭉날쭉함은 정상 범위입니다.
결론은 간단합니다. 이 룰렛에서 보이는 넓이가 곧 확률입니다. 칸을 똑같이 나눴으면 똑같은 확률이고, 넓게 만들었으면 그만큼 잘 걸립니다. 그 사이에 몰래 끼어드는 보정은 없습니다.
룰렛 돌리기에서 항목을 직접 입력하고 비중까지 조절해볼 수 있습니다. 결과 기록이 남으니 정말 고르게 나오는지 직접 확인해 보세요.
자주 묻는 질문
- 꿀도구 룰렛은 결과를 미리 정해놓고 돌리나요?
- 아닙니다. 버튼을 누르면 바퀴 수(5~10바퀴)와 멈출 각도, 두 난수를 뽑고 판이 멈춘 뒤 바늘이 가리키는 각도를 거꾸로 계산해 칸을 읽습니다. 당첨 항목을 먼저 뽑아 애니메이션을 맞추는 방식이 아니라, 화면에 보이는 칸이 곧 계산 결과입니다.
- 정말 모든 칸이 같은 확률로 나오나요?
- 6칸 룰렛을 600,000번 돌린 실측에서 각 칸은 16.62~16.73%로 나왔습니다. 기대값 16.67%에서 가장 크게 벗어난 칸도 0.07%포인트 차이로, 어느 칸이 유리하다고 볼 근거는 없습니다.
- 비중 3을 주면 3배 잘 나오나요?
- '3배 확률'이 아니라 '전체 중 3'입니다. 항목 4개 중 하나만 비중 3이면 전체 6 중 3, 즉 50%지만, 항목 10개 중 하나만 3이면 12 중 3으로 25.0%입니다. 다른 항목이 몇 개인지에 따라 같은 비중이라도 확률이 달라집니다.
- 같은 칸이 연달아 나오는데 고장 아닌가요?
- 6칸에서 같은 칸이 세 번 연달아 나올 확률은 2.78%로, 서른 번쯤 돌리면 대개 한 번은 겪습니다. 스무 번 돌렸을 때 어떤 칸은 여섯 번, 어떤 칸은 한 번도 안 나오는 것도 정상 범위이고, 결과 기록(최근 20개)을 세어보면 대개 착각입니다.
함께 읽으면 좋은 글
본문의 실측값은 도구가 쓰는 계산식(회전 각도 생성 → 멈춘 각도 정규화 → 슬라이스 판정)을 그대로 옮겨 600,000회 시뮬레이션한 결과입니다. 같은 시드를 쓰면 같은 값이 재현됩니다. 브라우저에서 실제로 돌릴 때는 암호학적 난수를 쓰므로 매번 다른 결과가 나오지만, 확률 분포는 같습니다.
참고 자료
- MDN Web Docs — Crypto.getRandomValues() — 이 룰렛이 쓰는 브라우저 암호학적 난수 발생기 설명