카테고리 없음
[확률, 복권] 즉석 복권 기능을 개발하려면 어떤 것들을 고려해야 할까?
by hbIncoding
2025. 1. 15.
0. 즉석 복권을 개발할 때 고려해야할 점들은 무엇이 있을까?
- 개발자 혹은 관리자가 복권의 결과를 미리 알 수 있으면 안된다.
- 문제가 생겼을 때 다시 복구하거나 재연할 수 있어야한다.
- 가령 어떤 실수로 1등이 1명이어야하는데 10명이 나왔다고 하자, 과연 누가 진짜 1등이었을까?!
- 기획적인 측면에서 어떤 추가해야 좀더 의미있는 복권 기능이 될 것인가?
1. 단순 확률 게임이 아닌 RandomSeed를 관리해보자
- 예를들어 100개의 복권중에 1개만 당첨이라고 한다면 random을 통해 0.01미만이 나와야 당첨이라고 하자.
- 여기서 0.01이하가 아니라 미만인 이유는 랜덤이 0을 포함하여, 0이상 1미만의 수가 나오기 때문이다.
- 실제로 0.01이 나와서 당첨될 확률도 매우 낮겠지만, 공정한 확률은 0~0.00999999... 단위로 나뉘어야한다.
- 당연하게도 Math.random()은 매번 다른 수를 내뱉는다. 그래서 seedrandom 모듈을 이용해서 같은 시드일 때는 같은 값이 나오도록 해주었다.
const seedrandom = require('seedrandom');
const rng = seedrandom('alpha');
const randNum = rng();
console.log(randNum);
- 그렇다면 이제 저 seedrandom() 안에 들어가는 seed만 잘 관리해준다면, 관리자 혹은 개발자도 어떤 값이 나올지도 모르면서, 반대로 들어간 값만 잘 기록해준다면 문제 상황을 해결할 실마리로 사용할 수 있다는 뜻이다.
2. Seed를 어떤값을 넣고, 어떻게 당첨과 꽝을 나누면 좋을까?
- 여기서는 다소 기획적인 점이 추가된다.
- 100개의 복권을 파는데 모든 복권의 확률이 1/100이라면 최악의 경우 당첨자가 안나오는 사기 복권이 된다.
- 그렇다면 1개씩 팔릴때 마다 당첨 확률이 늘어나는 수 밖에 없다. 1/100, 1/99, 1/98 ... 과 같이
- 첫 구매자가 불리한 것은 맞아보인다. 하지만 웹 기능이여서 그렇지, 실제로 본다면 확률은 똑같다.
- 오프라인 실물 복권에서도 앞사람이 꽝복권을 사갔다면, 자연스럽게 내 확률은 올라간다.
- 하지만 모든 복권을 똑같이 놓고 본다면 1/100이고, 실물과 온라인의 차이점은 그 결과가 미리 써있냐, 살때 정해지냐의 차이이다.
- 그렇다면 Seed에 어떤값을 넣어주었는가?
- 결과 먼저 말하자면 seed = secret_key + 회차 번호 + 구매 번호 + 구매자 ID 로 시드를 생성해서 확률을 만들었다.
- secret_key는 당연히 환경변수로 아무도 모르게 관리된다.
- 누가 몇번 째로 구매할지 예측 불가능하게 관리할 수 있다.
- 더 예측불가능하게 관리하자면, 구매시간을 ms 혹은 ns단위로 seed에 추가하는 방법도 있다.
- 구매 예시
- 3회차에 25번째로 123번이 구매했다면 seedrandom(secret_key+'3'+'25'+'123')의 값이 1/75보다 낮아야 당첨되는 것이다.
- 문제 해결 예시
- 그렇다면 이제 아까 말했던 1등이 10명 나온 상황을 다시 되짚어 보자.
- 당연하게도 누가 언제 복권을 구매했는지에 대한 Log 혹은 구매기록이 남아있어야 한다.
- 그 로그를 통해서 누가 몇회차, 몇번째에 복권을 구매했는지 다시 시뮬레이션을 돌려보고 1등 확률에 random이 잘 맞춰져서 나왔는지 확인하면 된다.
3. 현실에서 발생하는 이벤트를 참고해보자.
- 현실의 이벤트
- 동행복권 사이트에 가끔 사람들이 몰릴 때가 있다. 복권은 90%이상 판매됐는데 아직 1등이 안나온 경우이다.
- 어떻게 소문을 듣고 사람들은 소액 혹은 거금을 투자해본다.
- 여기서 만약 1등이 나온다면?? 나머지 복권은 판매하지 않는다. 누가 꽝인 복권을 사겠는가....
- 추가하면 좋을 아이디어
- 1등이 나오면 그 회차는 종료가 된다.
- 실시간으로 당첨현황과 구매현황을 공개하여 사람들이 몰릴 수 있게 해본다.