작성일 · · 최종 검토일 · · 6분

한국어 · English

컴퓨터는 어떻게 난수를 만드나

컴퓨터는 정해진 명령을 정해진 순서로 실행하는 기계입니다. 같은 입력을 주면 언제나 같은 결과를 냅니다. 그런 기계가 "무작위"를 만들 수 있을까요? 이 질문의 답은 "만들 수 있는 것처럼 보이게 하는 방법이 두 가지 있고, 두 방법의 성격이 다르다"입니다. 이 글은 의사난수와 암호학적 난수가 무엇인지, 어디서 편향이 생기는지를 설명한 다음, 이 사이트의 번호 생성기와 Lottery Lab이 실제로 코드에서 어떻게 번호를 뽑는지를 있는 그대로 적습니다.

의사난수: 공식으로 만든 난수

가장 오래된 방식은 점화식입니다. 이전 값에서 다음 값을 계산하는 공식을 정해 두고, 처음 값(시드)만 주면 그다음은 모두 공식이 만듭니다. 예를 들어 선형 합동 생성기는 이런 식입니다.

다음 값 = (1664525 × 현재 값 + 1013904223) mod 232

이 상수들은 수치 계산 교재에서 널리 쓰이는 값이고, 이 식은 232개의 값을 한 번씩 모두 지나서야 반복하는 "전체 주기"를 갖는다는 것이 알려져 있습니다(상수가 선형 합동 생성기의 전체 주기 조건을 만족하기 때문입니다). 아래 데모는 이 식에 시드를 넣어 로또 번호 모양의 숫자 6개를 만듭니다. 시드를 바꾸면 다른 숫자가, 시드를 같게 두면 몇 번을 눌러도 같은 숫자가 나오는 것을 확인해 보세요. 이 데모는 중복을 걸러 내지 않으므로 같은 번호가 두 번 나올 수 있습니다.

이 도구는 자바스크립트가 필요합니다.

"같은 시드, 같은 결과"가 의사난수의 가장 중요한 성질입니다. 단점이자 장점입니다. 시뮬레이션이나 테스트에서는 재현할 수 있다는 것이 큰 장점입니다. 이 사이트의 Lottery Lab에 시드 입력칸이 있는 이유도 그래서입니다. 반면 누군가 시드와 공식을 알면 나머지 숫자를 모두 예측할 수 있습니다. 추첨이나 보안에는 이 점이 치명적입니다.

암호학적 난수: 예측할 수 없도록 만든 난수

두 번째 방식은 예측 불가능성을 목표로 합니다. 운영체제는 하드웨어의 잡음, 이벤트의 정확한 타이밍 같은 외부의 불확실성(엔트로피)을 모으고, 이를 시드로 쓰는 생성기를 돌립니다. 이 생성기는 출력 일부를 보더라도 다음 출력을 알아낼 수 없도록 설계되어 있습니다. 브라우저에는 이것을 쓰는 창구가 있습니다. 개발자 문서(MDN)는 crypto.getRandomValues()가 "암호학적으로 강한 난수"를 준다고 설명하면서, 구현이 진짜 난수 생성기가 아니라 충분한 엔트로피로 시딩된 의사난수 생성기라는 점도 적고 있습니다. 알고리즘은 브라우저마다 다를 수 있지만 암호학 용도에 적합하다고 합니다. 같은 문서는 자바스크립트의 Math.random()을 비암호학적 난수원이라고 구분합니다.

그러니 "진짜 무작위"와 "의사난수"의 경계는 생각보다 흐립니다. 암호학적 난수도 내부는 공식입니다. 차이는 시드가 예측 불가능하게 만들어졌는가와, 출력에서 내부 상태를 거꾸로 추적할 수 없게 설계되었는가입니다. 이 사이트는 이 차이를 구분하지만 "진짜 난수"라고 말하지 않습니다.

나머지 연산의 함정: 모듈로 편향

난수를 얻은 뒤에도 문제가 남습니다. 컴퓨터가 주는 값은 0부터 232 − 1 사이의 큰 정수입니다. 1~45 사이 번호를 만들려면 이것을 45로 나눈 나머지에 1을 더하는 방법을 흔히 씁니다. 그런데 이 방법은 미세한 편향을 만듭니다. 값의 개수가 45의 배수가 아니면 일부 번호가 한 번 더 뽑힐 기회를 얻기 때문입니다.

1~45 번호를 "난수를 45로 나눈 나머지"로 만들 때의 편향
난수의 크기값의 개수앞쪽 31개 번호가 나올 경우의 수나머지 14개 번호상대 확률 차이
8비트 (0~255)25665앞쪽 번호가 20% 더 나옴
32비트4,294,967,29695,443,71895,443,717약 0.0000001%

8비트 난수를 쓴다면 1~31번이 32~45번보다 확률이 20% 높게 나옵니다. 이런 편향은 실제로 만들 수 있는 실수입니다. 32비트 난수에서는 차이가 약 1억분의 1로 줄어들어 사실상 보이지 않지만, 편향이 있다는 사실 자체는 사라지지 않습니다. 이를 완전히 없애는 방법이 거부 표본추출입니다. 45의 배수에 맞지 않는 끝부분의 값이 나오면 버리고 다시 뽑습니다. 값의 개수를 45의 배수로 잘라낸 범위 안에서만 나머지를 취하면 모든 번호의 확률이 정확히 같아집니다.

중복 없는 번호: 피셔–예이츠 셔플

로또는 같은 번호가 두 번 나오지 않습니다. 이를 만드는 올바른 방법은 1~45를 늘어놓은 목록을 피셔–예이츠 셔플로 섞어서 앞에서 6개를 가져오는 것입니다. 뒤에서부터 각 위치를 그 위치까지 포함한 앞쪽의 무작위 위치와 바꾸는 방식이며, 모든 순서가 정확히 같은 확률로 나옵니다. 잘못 만든 셔플은 순서에 편향이 생깁니다. 이는 셔플·제비뽑기·사다리타기의 공정성 글에서 시뮬레이터로 직접 확인합니다.

LottoFlick은 실제로 무엇을 쓰나 (코드 기준)

이 절은 이 사이트의 소스 코드를 읽고 쓴 것입니다.

이 설명은 코드에서 읽은 구조이며 브라우저 안의 crypto가 내부에서 어떤 알고리즘을 쓰는지는 브라우저마다 다릅니다(이 글은 확인하지 않았습니다). 또한 이 사이트는 외부 기관의 난수 인증을 받지 않았습니다.

"무작위인지"는 어떻게 확인하나

난수가 좋은지를 증명하는 것은 불가능에 가깝고, 나쁜지를 가려내는 통계 검사들이 있을 뿐입니다. 번호의 빈도가 고른지, 연속한 값 사이에 상관이 없는지, 순서가 편향되지 않는지를 봅니다. 이 사이트의 핫·콜드 번호 글에서 한 방식, 곧 가짜 이력을 많이 만들어 실제 값과 비교하는 방법도 그 한 가지입니다. 검사를 통과했다는 것은 "그 검사가 찾는 결함이 없다"는 뜻이지 "완벽하게 무작위"라는 뜻이 아닙니다.

난수의 질은 당첨 확률과 관계가 있나

없습니다. 이 사이트의 생성기가 어떤 난수를 쓰든 한 장의 당첨 확률은 실제 추첨기가 뽑는 번호와 비교해 변하지 않습니다. 실제 복권의 당첨 번호는 이 사이트 생성기가 아니라 별도의 추첨 장치에서 나옵니다. 생성기의 난수가 훌륭한 것은 "번호가 쏠림 없이 뽑힌다"는 의미일 뿐 맞힐 가능성을 올린다는 뜻이 아닙니다. 다음 글 추첨은 어떻게 공정성을 보장하나에서 실제 추첨 장치를 다룹니다.

한계

LottoFlick은 독립 사이트이며 복권 운영사가 아닙니다. 당첨 번호는 무작위이고 예측할 수 없습니다.

출처와 확인 상태