랜덤 추첨기 (뽑기·팀 나누기)
이름 목록을 넣고 당첨자 추첨, 팀 나누기, 발표 순서 섞기, 숫자 범위 뽑기를 공정한 난수로 처리합니다.
1~45 중 6개, 중복 비허용, 정렬 → 로또식 번호 뽑기가 됩니다.
공정성 안내 · 난수는 브라우저 내장 암호학적 난수 생성기(crypto.getRandomValues)로 만들고, 나머지 연산 편향은 거부 샘플링으로 제거했습니다. 섞기는 피셔-예이츠 셔플을 사용합니다. 명단과 결과는 서버로 전송되지 않으며 결과는 어디에도 저장되지 않습니다.
랜덤 추첨기 (뽑기·팀 나누기)란?
이벤트 당첨자를 뽑거나, 조를 나누거나, 발표 순서를 정할 때 손으로 하면 늘 뒷말이 나옵니다. 이 도구는 이름이나 항목 목록을 붙여넣기만 하면 네 가지 방식으로 무작위 결과를 만들어 줍니다. 당첨자 추첨(중복 허용/비허용 선택), N개 팀으로 균등하게 나누는 팀 나누기, 전체 순서를 뒤섞는 순서 섞기, 그리고 1~45 중 6개처럼 숫자 범위에서 뽑는 방식입니다. 난수는 Math.random 이 아니라 브라우저의 암호학적 난수 생성기(crypto.getRandomValues)를 쓰고, 흔히 실수하는 나머지 연산 편향(모듈로 편향)까지 거부 샘플링으로 제거해 모든 항목의 당첨 확률을 똑같이 맞췄습니다. 섞기는 편향 없는 표준 알고리즘인 피셔-예이츠 셔플을 사용합니다. 결과는 복사하거나 텍스트 파일로 저장해 그대로 공지에 붙여넣을 수 있습니다.
사용 방법
- 위쪽에서 모드를 고릅니다 — 추첨 / 팀 나누기 / 순서 섞기 / 숫자 범위.
- 이름이나 항목을 입력창에 한 줄에 하나씩(또는 쉼표로 구분해) 넣습니다.
- 추첨은 뽑을 개수와 중복 허용 여부를, 팀 나누기는 팀 수를, 숫자 범위는 최소·최대·개수를 지정합니다.
- "추첨하기"를 누르면 결과가 하나씩 공개됩니다.
- 결과를 복사하거나 .txt 로 저장해 공지에 붙여넣습니다. 다시 누르면 새로 추첨됩니다.
랜덤 추첨기 (뽑기·팀 나누기) 사용 가이드
실제 작업에서 이 도구를 어떻게 쓰는지, 무엇을 조심해야 하는지 정리했습니다.
Math.random을 쓰지 않은 이유
웹에서 무작위가 필요하면 대부분 Math.random()을 씁니다. 간단한 게임이나 색 고르기에는 아무 문제가 없습니다. 하지만 당첨자를 뽑는 일에는 두 가지 결함이 있습니다.
첫째, Math.random은 암호학적으로 안전하지 않습니다. 내부적으로 의사난수 알고리즘을 쓰는데, 이전 출력값을 충분히 관찰하면 다음 값을 예측할 수 있습니다. 실제로 브라우저의 Math.random 내부 상태를 복원해 낸 연구들이 있습니다. 둘째, 명세가 균등성을 엄격히 보장하지 않고 구현이 브라우저마다 다릅니다.
그래서 이 도구는 crypto.getRandomValues()를 씁니다. 운영체제의 엔트로피에서 나오는 값이라 예측할 수 없고, 애초에 암호 키 생성에 쓰라고 만들어진 물건입니다.
모듈로 편향 — 대부분의 추첨기가 놓치는 것
난수를 잘 뽑아 놓고도 마지막 한 줄에서 공정성이 깨지는 경우가 있습니다. 0~4294967295 범위의 난수를 참가자 수로 나눈 나머지를 그대로 쓰는 흔한 방식입니다.
문제는 4294967296이 참가자 수로 딱 나눠떨어지지 않는다는 데 있습니다. 예를 들어 참가자가 3명이면, 나머지가 0이 나오는 경우가 1이나 2가 나오는 경우보다 딱 한 번 더 많습니다. 명단 앞쪽 사람이 아주 미세하게 유리해집니다.
차이가 극히 작아 보통은 무시되지만, 애초에 "완전히 균등"을 표방하는 도구가 굳이 편향을 남길 이유가 없습니다. 이 도구는 나눠떨어지지 않는 구간에 걸린 값은 버리고 다시 뽑는 방식(거부 샘플링)으로 이를 제거했습니다.
// 편향 있음 — 앞쪽 항목이 미세하게 유리
var bad = crypto.getRandomValues(new Uint32Array(1))[0] % n;
// 편향 없음 — 균등 구간을 벗어난 값은 버리고 다시 뽑는다
function randInt(n) {
if (n <= 1) return 0;
var limit = Math.floor(4294967296 / n) * n;
var buf = new Uint32Array(1);
do { crypto.getRandomValues(buf); } while (buf[0] >= limit);
return buf[0] % n;
}
이벤트 추첨의 진짜 문제는 난수가 아니라 신뢰입니다
정직하게 말하면, 이 도구가 아무리 완벽한 난수를 써도 참가자에게 그걸 증명할 방법은 없습니다. 결과 화면 캡처는 얼마든지 조작할 수 있고, "crypto.getRandomValues를 썼습니다"라는 말은 참가자에게 아무 의미가 없습니다.
추첨 시비는 난수 품질에서 나오지 않습니다. "주최자가 원하는 사람이 나올 때까지 다시 돌린 것 아니냐"에서 나옵니다. 이건 기술이 아니라 절차로 풀어야 합니다.
- 명단을 먼저 공개하세요. 추첨 전에 참가자 명단(닉네임 목록)을 공지에 올리고, 그 명단 그대로 붙여넣습니다. 결과만 발표하면 명단에 없던 사람을 넣었는지 알 수 없습니다.
- 추첨 과정을 녹화하세요. 화면 녹화로 명단 붙여넣기부터 결과까지 한 번에 담으면 "다시 돌리기"를 하지 않았다는 근거가 됩니다. 라이브 방송이면 더 확실합니다.
- 규칙을 미리 못 박으세요. "몇 명을, 언제, 어떤 도구로" 를 사전 공지하면 사후에 조건을 바꿨다는 의심이 줄어듭니다.
- 예비 당첨자를 함께 뽑으세요. 당첨자가 연락이 안 되어 다시 뽑는 상황이 시비의 단골 원인입니다. 처음부터 3명 + 예비 2명을 한 번에 뽑아 순위대로 공개하면 깔끔합니다.
- 참가자가 스스로 검증할 수 있어야 하는 규모라면 이런 브라우저 도구로는 부족합니다. 공개된 값을 시드로 쓰는 등 별도 설계가 필요합니다.
네 가지 모드, 언제 무엇을
"추첨"에서 개수를 전체 인원과 같게 두면 "순서 섞기"와 결과가 같아집니다. 다만 순서 섞기 모드는 당첨 확률 통계를 표시하지 않아 발표 순서 같은 용도에 더 맞습니다.
중복 허용은 헷갈리기 쉽습니다. 끄면 한 사람이 한 번만 뽑히고(당첨자 추첨), 켜면 같은 사람이 여러 번 뽑힐 수 있습니다(주사위처럼 매번 독립적으로 뽑는 경우). 이벤트 당첨자를 뽑는다면 거의 항상 꺼야 합니다.
| 모드 | 하는 일 | 실무 예 |
|---|---|---|
| 추첨 | 명단에서 N개를 뽑음 | 이벤트 당첨자, 발표자 지목, 오늘 점심 메뉴 |
| 팀 나누기 | N개 팀으로 균등 배분 | 조 편성, 체육대회 팀, 스터디 그룹 |
| 순서 섞기 | 전체 순서만 무작위로 | 발표 순서, 면접 순서, 시험 문제 배열 |
| 숫자 범위 | 숫자 구간에서 뽑음 | 로또, 좌석 번호, 경품 번호 |
팀 나누기에서 인원이 안 맞을 때
11명을 3팀으로 나누면 4명, 4명, 3명이 됩니다. 문제는 "누가 3명 팀이 되느냐"입니다. 단순하게 앞에서부터 자르면 항상 마지막 팀이 손해를 봅니다.
이 도구는 먼저 전체를 셔플한 뒤 한 명씩 돌아가며 배정합니다. 그래서 팀 간 인원 차이는 항상 1명 이내이고, 어느 팀이 한 명 더 받는지도 셔플 결과에 따라 매번 달라집니다.
- 팀 이름을 비우면 1팀·2팀·3팀으로 자동 지정됩니다. 쉼표로 구분해 "레드, 블루, 그린"처럼 넣으면 그 이름이 쓰입니다.
- 팀 이름을 팀 수보다 적게 넣으면 나머지는 자동으로 숫자 이름이 됩니다.
- 실력을 고려한 균형 배분은 이 도구가 하지 못합니다. 순수 무작위입니다. 실력 균형이 필요하면 상·중·하 그룹별로 따로 돌려 각 팀에 나눠 넣는 방식이 현실적입니다.
- 결과 아래 메시지가 몇 명씩 나뉘었는지 알려 줍니다. 딱 떨어지면 "정확히 N명씩", 아니면 어느 팀이 몇 명인지 표시합니다.
자주 묻는 질문
정말 공정한가요? 조작 여지는 없나요?
난수를 브라우저 내장 암호학적 난수 생성기(crypto.getRandomValues)로 만들고, 뽑기는 피셔-예이츠 셔플, 범위 추첨은 거부 샘플링으로 처리합니다. 흔한 구현처럼 난수를 항목 수로 나눈 나머지를 쓰면 앞쪽 항목이 아주 미세하게 더 자주 뽑히는 편향이 생기는데, 이 도구는 그 편향을 없앴습니다. 입력 목록의 순서나 이름 길이도 결과에 영향을 주지 않습니다.
중복 허용과 비허용은 뭐가 다른가요?
비허용은 한 번 뽑힌 항목을 다시 뽑지 않습니다(경품 당첨자 3명처럼 서로 다른 사람이 나와야 할 때). 허용은 매번 전체 목록에서 다시 뽑아 같은 항목이 여러 번 나올 수 있습니다(주사위처럼 매 회 독립적인 뽑기가 필요할 때).
팀 나누기에서 인원이 딱 안 나눠지면 어떻게 되나요?
먼저 전체를 섞은 뒤 순서대로 한 명씩 돌려 배정하므로 팀 간 인원 차이는 항상 1명 이내입니다. 예를 들어 10명을 3팀으로 나누면 4·3·3명이 되고, 어느 팀이 한 명 더 받을지도 무작위로 정해집니다. 결과 표에 팀별 인원이 함께 표시됩니다.
로또 번호도 뽑을 수 있나요?
숫자 범위 모드에서 최소 1, 최대 45, 개수 6, 중복 비허용, 오름차순 정렬로 설정하면 됩니다. 다만 이건 어디까지나 무작위 숫자일 뿐이며 당첨 확률을 높여 주지는 않습니다.
추첨 결과가 저장되나요? 나중에 증빙할 수 있나요?
결과는 어디에도 저장되지 않고 새로고침하면 사라집니다. 서버로 전송되지도 않습니다. 증빙이 필요하면 결과를 저장(.txt)하거나 화면을 캡처해 두세요. 다음에 이어서 쓸 수 있도록 입력한 명단만 브라우저 안(localStorage)에 남습니다.
입력한 명단이 서버로 전송되나요?
아니요. 추첨과 섞기 전부 사용자의 브라우저 안에서만 실행되며, 명단이나 결과가 서버로 전송되거나 저장되지 않습니다.