온라인 추첨기의 무작위는 믿을 수 있을까? 난수의 원리와 확인하는 법

“방금 돌림판, 왜 또 나야? 이거 조작 아니야?” 온라인 추첨기를 쓰다 보면 한 번쯤 듣게 되는 말이에요. 눈앞에서 섞고 뽑는 종이 제비와 달리 컴퓨터 속 추첨은 과정이 보이지 않으니 의심이 생기는 것도 당연해요. 그런데 컴퓨터는 정해진 계산만 하는 기계인데, 어떻게 ‘무작위’를 만들어 낼 수 있을까요?

이 글에서는 온라인 추첨기가 무작위 결과를 만드는 원리를 차근차근 살펴봐요. 흔히 쓰이는 난수와 암호학적 난수의 차이, 프로그래머들이 자주 빠지는 함정 두 가지, 결과가 애니메이션보다 먼저 정해져도 괜찮은 이유, 그리고 ‘같은 사람이 또 걸리는’ 현상을 확률로 따져 봐요. 마지막으로 누구나 해 볼 수 있는 공정성 확인 방법도 소개할게요.

컴퓨터는 어떻게 무작위를 만들까?

의사 난수(PRNG): 무작위처럼 보이는 계산

대부분의 프로그램이 쓰는 난수는 의사 난수 생성기(PRNG)가 만들어요. ‘시드’라고 부르는 시작값을 정해진 공식에 넣고, 그 결과를 다시 공식에 넣는 과정을 반복해 무작위처럼 보이는 수열을 만들어 내는 방식이에요. 계산이 빠르고 통계적으로도 고르게 퍼져 있어 게임이나 시뮬레이션에는 충분히 쓸 만해요.

하지만 결정적인 약점이 있어요. 공식과 내부 상태를 알면 다음에 나올 수를 전부 계산할 수 있다는 점이에요. 자바스크립트의 Math.random()이 대표적인 예로, 브라우저마다 구현은 다르지만 보안 용도로는 쓰지 말라고 안내되어 있어요. 출력값을 충분히 관찰하면 내부 상태를 거꾸로 추정할 수 있는 알고리즘도 있기 때문이에요.

암호학적 난수(CSPRNG): 예측할 수 없는 무작위

암호학적으로 안전한 난수 생성기(CSPRNG)는 지금까지 나온 값을 모두 보더라도 다음 값을 짐작할 수 없도록 설계된 난수예요. 운영체제가 기기 안에서 모은 예측하기 어려운 정보를 바탕으로 만들어지며, 비밀번호나 암호 키를 만들 때도 이 방식이 쓰여요. 브라우저에서는 Web Crypto API의 crypto.getRandomValues()로 이 난수를 얻을 수 있어요.

구분Math.random()crypto.getRandomValues()
종류의사 난수(PRNG)암호학적 난수(CSPRNG)
예측 가능성내부 상태를 알면 예측 가능이전 출력만으로 예측하기 어렵도록 설계
주 용도게임 효과, 시각 연출, 시뮬레이션암호 키, 보안 토큰, 공정한 추첨

좋은 난수는 결과 예측을 어렵게 하지만 브라우저 코드의 변경까지 막지는 않아요. 기기를 조작하는 사람이나 확장 프로그램이 결과에 개입할 수 있으므로 이 사이트를 공인 추첨이나 결과 인증 수단으로 사용하지 마세요.

함정 1. 나머지 연산이 만드는 ‘모듈로 편향’

좋은 난수를 얻었다고 끝이 아니에요. 난수를 원하는 범위로 바꾸는 과정에서 공정성이 깨지기 쉬워요. 가장 흔한 실수가 나머지 연산으로 범위를 맞추는 것이에요.

쉬운 예로, 0부터 7까지 여덟 가지 값이 똑같은 확률로 나오는 난수가 있고, 이것으로 세 사람(0, 1, 2번) 중 한 명을 뽑는다고 해 볼게요. 난수를 3으로 나눈 나머지를 쓰면 이렇게 돼요.

뽑히는 사람해당하는 난수확률
0번0, 3, 63/8 (37.5%)
1번1, 4, 73/8 (37.5%)
2번2, 52/8 (25%)

8이 3으로 나누어떨어지지 않아서 남는 두 값(6, 7)이 앞쪽 사람들에게 몰렸어요. 이것이 모듈로 편향이에요. 해결책은 간단해요. 6이나 7이 나오면 버리고 다시 뽑는 것이에요. 그러면 0~5만 남아 세 사람이 정확히 2/6씩, 즉 1/3의 확률을 갖게 돼요. 이렇게 공정한 범위를 벗어난 값을 버리고 다시 뽑는 방법을 ‘기각 샘플링’이라고 해요.

실제 프로그램은 0부터 약 43억(2의 32제곱) 미만까지의 큰 난수를 쓰기 때문에 치우침이 아주 작아요. 6명 중 한 명을 뽑는다면 43억 개 가운데 남는 값이 4개뿐이거든요. 하지만 작다고 없는 건 아니니, 공정성을 약속하는 도구라면 이 작은 치우침까지 없애는 게 맞아요.

함정 2. 잘못된 섞기

사다리의 결과 칸이나 발표 순서처럼 목록 전체를 섞어야 할 때도 함정이 있어요.

올바른 방법: 피셔–예이츠 셔플

피셔–예이츠 셔플은 목록의 맨 뒤 칸부터 시작해, 그 칸과 ‘아직 확정되지 않은 칸들’ 중 무작위로 고른 한 칸을 맞바꾸는 일을 앞쪽으로 가며 반복하는 방법이에요. 이름이 4개라면 마지막 자리에 올 이름을 4개 중에서, 그다음 자리를 남은 3개 중에서, 그다음을 남은 2개 중에서 고르는 셈이에요. 선택지의 수가 4 × 3 × 2 = 24로 가능한 순서의 수(4! = 24)와 정확히 같고, 각 선택이 서로 다른 순서로 이어지기 때문에 모든 순서가 똑같이 1/24의 확률로 나와요.

흔한 실수 ①: 무작위 비교로 정렬하기

정렬 함수에 ‘두 값을 비교할 때마다 무작위로 크다 작다를 대답하는’ 비교 함수를 넣어 섞는 방법이 인터넷에 자주 보이는데, 이 방법은 공정하지 않아요. 결과가 정렬 알고리즘의 동작 방식에 따라 달라지기 때문이에요.

예를 들어 가, 나, 다 세 이름을 삽입 정렬로 섞는다고 해 볼게요. 먼저 가와 나를 비교해 반반의 확률로 순서를 정하고, 다를 끼워 넣을 때 바로 앞 이름과 비교해 ‘뒤에 남기’가 1/2, 한 칸 앞으로 간 뒤 멈추기가 1/4, 맨 앞까지 가기가 1/4이에요. 그 결과 ‘다’가 맨 뒤에 남을 확률은 1/2(50%)로, 공정한 값인 1/3(약 33.3%)보다 훨씬 높아요. ‘가, 나, 다’ 순서 그대로 나올 확률도 1/4(25%)로 공정한 값 1/6(약 16.7%)보다 커요.

흔한 실수 ②: 매번 전체에서 골라 바꾸기

“각 칸을 전체 칸 중 아무 칸과 바꾼다”는 방법도 공정하지 않아요. 세 칸이면 칸마다 3가지 선택지가 있어 전체 경우의 수가 3 × 3 × 3 = 27가지인데, 가능한 순서는 6가지예요. 27은 6으로 나누어떨어지지 않으니 여섯 가지 순서가 같은 횟수씩 나올 수가 없어요. 피셔–예이츠처럼 ‘남은 칸 중에서만’ 골라야 경우의 수가 순서의 수와 딱 맞아떨어져요.

결과가 애니메이션보다 먼저 정해져도 괜찮을까?

대부분의 온라인 추첨기는 버튼을 누르는 순간 결과를 먼저 정하고, 그 결과에 맞춰 돌림판이 멈추거나 사다리가 내려가는 애니메이션을 보여 줘요. 이 사실을 알면 “결과가 이미 정해져 있었다니, 속은 기분인데?” 싶을 수 있어요.

하지만 이것은 공정성과 전혀 충돌하지 않아요. 중요한 건 결과가 언제 정해지느냐가 아니라 정해진 추첨 규칙에 맞는 확률로 선택하느냐예요. 종이 제비도 손을 넣어 한 장을 집는 순간 결과는 정해져 있고, 종이를 펼치는 건 그 결과를 확인하는 과정일 뿐이에요. 잘 섞인 카드를 뒤집는 것도 마찬가지고요.

오히려 결과를 먼저 정하는 방식이 더 공정할 때도 있어요. 실제 룰렛처럼 버튼을 누르는 힘과 타이밍으로 결과가 정해진다면 연습한 사람이나 운 좋게 타이밍을 맞춘 사람이 유리해질 수 있어요. 결과를 난수로 먼저 정하면 누르는 방식과 결과가 완전히 분리돼요. 물론 ‘10초 멈추기’나 반응속도 게임처럼 원래부터 실력을 겨루는 게임은 예외예요. 이런 게임은 무작위가 아니라 실력이 결과를 정한다는 걸 참가자 모두가 알고 시작해야 해요.

또 나야? 연속 당첨과 도박사의 오류

공정한 추첨기에서도 같은 사람이 연달아 걸리는 일은 생각보다 흔해요. 문제는 우리 직관이 무작위를 ‘골고루 섞인 상태’로 기대한다는 거예요. 실제 무작위는 생각보다 훨씬 들쭉날쭉해요. 5명이 추첨하는 상황으로 계산해 볼게요.

상황 (5명, 매번 5명 전원 대상)확률
방금 걸린 사람이 다음 판에 또 걸릴 확률1/5 = 20%
3번 뽑는 동안 누군가 두 번 이상 걸릴 확률1 − (5×4×3)/125 = 52%
5번 뽑는 동안 특정한 한 사람이 한 번도 안 걸릴 확률(4/5)의 5제곱 ≈ 32.8%
5번 뽑아서 5명이 정확히 한 번씩 걸릴 확률5!/5의 5제곱 = 120/3125 = 3.84%
10번 뽑는 동안 같은 사람이 연속으로 걸리는 장면이 한 번 이상 나올 확률1 − (4/5)의 9제곱 ≈ 86.6%

5명이 다섯 번 뽑았을 때 모두가 사이좋게 한 번씩 걸리는 경우는 4%도 안 돼요. 누군가는 두세 번 걸리고 누군가는 한 번도 안 걸리는 게 오히려 정상이에요. 열 번쯤 하다 보면 누군가 연속으로 걸리는 장면도 거의 틀림없이 나와요.

반대로 “저 친구는 세 번 연속 안 걸렸으니 이번엔 걸리겠지”라는 생각도 착각이에요. 이것을 도박사의 오류라고 불러요. 난수 생성기에는 기억이 없어서, 매 판마다 모든 사람의 확률은 처음과 똑같이 1/5이에요. 이전 결과가 다음 결과에 영향을 주지 않는 것, 그것이 바로 공정한 무작위의 정의예요.

연속 당첨이 싫다면 규칙을 바꾸세요 — 무작위를 의심하기보다 ‘이번에 걸린 사람은 다음 판에서 빠진다’는 규칙을 정하는 편이 좋아요. 돌림판의 당첨 항목 빼기처럼 제외 기능을 쓰면 한 사람에게 부담이 몰리지 않아요. 이건 공정성을 고치는 게 아니라 게임 규칙을 바꾸는 거예요.

공정한지 직접 확인하는 방법

도구가 정말 공정한지 궁금하다면 직접 여러 번 돌려 보고 세어 보면 통계적 치우침을 살펴볼 수 있어요. 반복 실험만으로 코드의 안전성이나 조작 여부를 증명할 수는 없어요. 다만 몇 번 해 보고 판단하면 안 되고, 충분히 많이 해야 해요.

  1. 조건을 고정해요. 예를 들어 이름 5개를 넣은 이름 뽑기나 돌림판으로 100번을 뽑기로 정해요.
  2. 결과를 기록해요. 사람마다 몇 번 뽑혔는지 세어요.
  3. 기대값과 비교해요. 100번이면 한 사람당 평균 20번이 기대값이에요. 이때 흔들림의 크기를 나타내는 표준편차는 √(100 × 0.2 × 0.8) = √16 = 4예요. 기대값에서 표준편차 두 배만큼 벗어난 12~28번 사이라면 지극히 정상적인 흔들림이에요. 한두 명이 이 범위를 살짝 벗어나는 것도 가끔은 있을 수 있어요.

조금 더 엄밀하게 하고 싶다면 ‘카이제곱 검정’을 써 볼 수 있어요. 각 사람의 (실제 횟수 − 기대 횟수)의 제곱을 기대 횟수로 나눈 값을 모두 더하는 방법이에요. 예를 들어 100번 뽑아 24, 17, 21, 15, 23번이 나왔다면 (16 + 9 + 1 + 25 + 9) ÷ 20 = 3.0이에요. 5명일 때는 이 값이 약 9.49를 넘지 않으면 ‘공정한 추첨에서 충분히 나올 수 있는 결과’로 봐요. 3.0이면 아주 자연스러운 결과예요.

공정성과 함께 확인하면 좋은 것도 있어요.

  • 결과가 서버를 거치는지 — 결과를 서버에서 정하는 도구라면 운영자가 결과에 개입할 수 있는 구조예요. 브라우저 개발자 도구의 네트워크 탭을 열어 두고 추첨해 보면, 버튼을 누를 때 외부로 요청이 나가는지 확인할 수 있어요.
  • 확률을 바꾸는 설정이 화면에 드러나는지 — 가중치나 중복 항목처럼 확률을 바꾸는 요소가 있다면 모두가 볼 수 있어야 공정해요.

복불복 놀이터는 이렇게 만들었어요

복불복 놀이터의 모든 도구는 위에서 설명한 원칙을 그대로 따르고 있어요.

  • 암호학적 난수 사용 — 무작위 선택에는 브라우저의 crypto.getRandomValues()를 사용해요. 이 기능을 사용할 수 없으면 도구를 시작하지 않고 안내해요. 화면 효과·효과음은 결과와 별개예요.
  • 모듈로 편향 제거 — 범위를 맞출 때 나누어떨어지지 않는 끝부분의 값은 버리고 다시 뽑는 기각 샘플링을 써서, 모든 선택지가 정확히 같은 확률을 가져요.
  • 피셔–예이츠 셔플 — 사다리의 결과 칸, 순서 정하기, 팀 나누기처럼 목록을 섞을 때는 모든 순서가 같은 확률로 나오는 피셔–예이츠 방식을 써요. 사다리타기가 사다리 모양과 관계없이 공정한 이유도 이 덕분이에요.
  • 모든 계산은 내 기기 안에서 — 추첨은 전부 사용자의 브라우저 안에서 이루어지고, 입력한 이름이나 결과를 서버로 보내지 않아요. 서버에서 결과를 받는 구조는 아니지만, 브라우저 코드가 변경되지 않았다는 보증은 제공하지 않아요.

사다리가 어떻게 1:1 짝짓기를 만드는지는 사다리타기의 수학에서 더 자세히 다뤘어요.

마무리

무작위는 ‘골고루’가 아니라 ‘예측할 수 없음’이에요. 같은 사람이 연달아 걸리는 것도, 누군가 한 번도 안 걸리는 것도 공정한 추첨에서 얼마든지 일어나는 일이에요. 좋은 추첨기는 예측할 수 없는 난수를 쓰고, 범위를 맞추거나 섞는 과정에서 치우침을 만들지 않으며, 결과 검증이 필요한 용도에는 별도의 감사·위변조 방지 절차가 필요해요. 이 사이트에는 그런 인증 기능이 없어요. 다음에 “또 나야?”라는 말이 나오면 이 글의 확률표를 떠올려 보세요. 억울함이 조금은 덜어질 거예요.

다른 가이드

전체 보기 →