사진은 작게 줄여 이 기기 브라우저에만 저장돼요. 서버로 보내지 않아요.
사용법
- 명단칸에 이름을 붙여 넣으세요. 한 줄에 한 명씩, 또는
철수, 영희, 민수처럼 쉼표로 구분해도 됩니다. 엑셀·구글 시트에서 열 하나를 복사해 붙여 넣어도 줄바꿈으로 나뉘어요. - 모드를 고릅니다.
- N명 뽑기 — 당첨자 수를 정하면 그만큼 뽑고, 미당첨자도 함께 보여 줘요. 1명이면 전통적인 제비뽑기입니다.
- 팀 나누기 — '팀 수'(예: 3팀) 또는 '팀당 인원'(예: 4명씩)을 정하면 무작위로 조를 짜요.
- 순서 정하기 — 전체 명단을 무작위 순서로 섞어 1번부터 번호를 매깁니다.
- (선택) 참가자 사진 — 명단 아래 이름 동그라미를 누르고 휴대폰 앨범에서 사진을 고르면, 추첨 화면과 결과에 그 사람 얼굴이 나와요. 사진을 안 넣으면 이름 첫 글자가 든 색 동그라미로 보여요. 사진은 가로세로 128px로 줄여 이 브라우저에만 저장하고 서버로 보내지 않아요.
- 추첨하기를 누르면 제비통이 흔들리며 이름(과 얼굴)이 빠르게 돌아가다가, 결과가 한 장씩 뒤집히며 나오고 색종이가 떨어져요. 명단칸에서 Ctrl/⌘ + Enter로도 추첨할 수 있습니다.
- copy로 결과 텍스트를 복사해 단톡방·공지에 붙여 넣으세요.
어떻게 공정하게 뽑나요? (추첨 원리)
세 모드 모두 같은 원리예요. 명단 전체를 Fisher-Yates 셔플로 한 번 섞고, 그 순서를 그대로 쓰거나(순서 정하기) 앞에서 N명을 자르거나(N명 뽑기) 돌아가며 팀에 배정합니다(팀 나누기).
- Fisher-Yates 셔플 — 맨 뒤 자리부터 "아직 안 정해진 사람 중 하나"를 골라 자리를 바꾸는 방식이라, n명의 가능한 순서 n!가지가 모두 정확히 같은 확률로 나옵니다. 같은 사람이 두 번 뽑히는 중복도 생기지 않아요.
- 난수 —
Math.random대신 브라우저의 암호학적 난수crypto.getRandomValues를 쓰고, 범위를 줄일 때 생기는 치우침(모듈로 편향)은 거부 샘플링으로 없앴습니다. - N명 뽑기 확률 — 명단 n명 중 k명을 뽑으면 각자 당첨 확률은 정확히
k ÷ n이에요. 명단 순서(먼저 적은 사람, 나중에 적은 사람)는 결과에 영향을 주지 않습니다.
팀 나누기 인원 계산
섞은 명단을 1팀, 2팀, 3팀… 순서로 한 명씩 돌아가며 배정하기 때문에 팀 인원 차이는 최대 1명입니다. '팀당 인원'으로 정하면 팀 수 = 전체 인원 ÷ 팀당 인원의 몫(소수점 버림)으로 팀 수를 정한 뒤 남는 사람을 여러 팀에 한 명씩 더 넣어요. 그래서 모든 팀이 정한 인원 이상이 되고, 혼자 남는 팀은 생기지 않아요. 예를 들어 11명을 팀당 3명으로 나누면 3팀(4·4·3명)이에요.
| 인원 | 설정 | 결과 |
|---|---|---|
| 10명 | 3팀 | 4명 · 3명 · 3명 |
| 10명 | 팀당 4명 | 10 ÷ 4 = 2.5 → 3팀 (4·3·3명) |
| 13명 | 팀당 4명 | 13 ÷ 4 = 3.25 → 3팀 (5·4·4명) |
| 22명 | 팀당 5명 | 22 ÷ 5 = 4.4 → 4팀 (6·6·5·5명) |
| 30명 | 6팀 | 5명씩 6팀 |
팀당 인원을 꼭 맞추고 남는 사람만 따로 두고 싶다면, 'N명 뽑기'로 먼저 필요한 인원을 뽑은 뒤 나머지를 다시 나누는 방법도 있어요.
사용 예시
- 댓글 이벤트 30명 중 3명 추첨: N명 뽑기에서 3명 → 각자 당첨 확률 3 ÷ 30 = 10%, 나머지 27명은 미당첨자로 함께 표시돼요.
- 워크숍 10명 3팀: 팀 나누기에서 팀 수 3 → 4명 · 3명 · 3명으로 배정됩니다.
- 발표 순서 6명: 순서 정하기 → 6! = 720가지 순서 중 하나가 같은 확률로 나와요.
Math.random과 crypto.getRandomValues는 무엇이 다를까
둘 다 "무작위 숫자"를 주지만 만들어지는 방식이 달라요. MDN 문서도 Math.random()은 보안용 난수가 아니니 getRandomValues()를 쓰라고 안내해요.
| 항목 | Math.random() | crypto.getRandomValues() |
|---|---|---|
| 만드는 방식 | 브라우저 엔진의 의사난수 공식 (크롬 V8은 xorshift128+) | 운영체제의 암호학적 난수원(CSPRNG) |
| 예측 가능성 | 출력 몇 개로 내부 상태를 거꾸로 계산할 수 있다고 알려진 공식 | 앞 결과로 다음 결과를 알 수 없음 |
| 결과 형태 | 0 이상 1 미만 소수 | 정수 배열 (한 번에 최대 65,536바이트) |
| 쓰기 좋은 곳 | 게임 효과, 애니메이션 | 추첨, 비밀번호, 토큰, UUID |
모듈로 편향은 얼마나 클까
난수를 "인원 수로 나눈 나머지"로 바꾸면 조금 치우칠 수 있어요. 예를 들어 0~255 바이트 하나를 6으로 나눈 나머지를 쓰면 256 = 6 × 42 + 4라서 나머지 0~3이 한 번씩 더 나와요.
| 방식 (6명 중 1명) | 1~4번째 사람 | 5~6번째 사람 |
|---|---|---|
| 바이트 % 6 (보정 없음) | 43/256 = 16.80% | 42/256 = 16.41% |
| 이 도구 (32비트 + 거부 샘플링) | 정확히 16.67% | 정확히 16.67% |
이 도구는 32비트 난수(0~4,294,967,295)를 쓰고, 인원으로 딱 나누어떨어지는 범위를 넘는 값은 버리고 다시 뽑아요. 30명이면 버려지는 값이 232 가운데 16개뿐이라 다시 뽑는 일은 사실상 없지만, 그 덕분에 확률이 정확히 같아져요.
확률 미리 계산표
| 상황 | 계산 | 확률 |
|---|---|---|
| 30명 중 3명 추첨, 내가 당첨 | 3 ÷ 30 | 10% |
| 30명 중 3명 추첨, 나와 친구 둘 다 당첨 | (3 × 2) ÷ (30 × 29) | 약 0.69% |
| 100명 중 10명 추첨, 둘 다 당첨 | (10 × 9) ÷ (100 × 99) | 약 0.91% |
| 12명을 2팀(6·6), 두 사람이 같은 팀 | 2 × (6 × 5) ÷ (12 × 11) | 약 45.5% |
| 10명을 3팀(4·3·3), 두 사람이 같은 팀 | (4×3 + 3×2 + 3×2) ÷ (10 × 9) | 약 26.7% |
| 20명을 4팀(5명씩), 두 사람이 같은 팀 | 4 × (5 × 4) ÷ (20 × 19) | 약 21.1% |
이 표의 값은 실제 이 페이지의 셔플 코드로 20만 번씩 돌려 본 결과와도 0.1%p 안에서 맞았어요(10명 3팀 26.9%, 30명 중 둘 다 당첨 0.68%).
흔한 실수
| 실수 | 무슨 일이 생기나 | 이렇게 하세요 |
|---|---|---|
| 결과가 마음에 안 들어 한 번 더 누름 | 사실상 원하는 결과가 나올 때까지 고르는 셈이라 공정성이 깨져요 | "첫 결과로 확정"을 미리 정하고 화면을 함께 보며 누르기 |
| '같은 이름은 한 번만'을 끄고 N명 뽑기 | 명단에 두 번 적힌 사람은 확률이 두 배이고, 한 사람이 두 자리에 당첨될 수도 있어요 | 중복 응모를 인정할 때만 끄기 |
| 팀당 2명(짝 짓기)에 홀수 인원 | 9명이면 4팀이 되고 한 팀만 3명이에요(3·2·2·2명) | 3명 팀이 싫다면 1명을 진행자·심판으로 빼고 8명으로 나누기 |
| 엑셀에서 이름과 번호를 함께 복사 | "홍길동 010…"이 한 명으로 들어가요 | 이름 열만 복사하기 |
이럴 때 쓰세요
- 이벤트 당첨자 추첨 — 댓글 참여자 아이디를 붙여 넣고 N명 뽑기. '같은 이름은 한 번만'을 켜 두면 여러 번 댓글을 단 사람도 한 번만 응모한 것으로 처리돼요(중복 응모를 인정하려면 끄세요).
- 수업·워크숍 조 짜기 — 출석부를 복사해 팀 나누기. 결과를 복사해 공지에 그대로 올리면 됩니다.
- 발표·당번 순서 — 순서 정하기로 1번부터 차례를 정해요.
- 풋살·농구 편 가르기 — 2팀으로 나누면 인원이 홀수여도 1명 차이로 맞춰집니다.
- 커피 내기 — 1명 뽑기로 간단하게. 긴장감이 필요하면 사다리타기도 좋아요.
명단은 다음에 다시 쓰기 편하도록 이 브라우저(localStorage)에만 저장되고 서버로 전송되지 않아요. 공개 경품 추첨처럼 공정성 증명이 필요하다면 추첨 화면을 녹화하거나 여러 사람 앞에서 진행하는 걸 권합니다.