확률형 출석 보상 설계 면접 질문: 하루 세 번 상자와 확률표는 어디에 두나
시스템 디자인 Vol.1 · 19장 「하루 세 번, 확률이 다른 출석 상자」에서
이런 화면입니다
이벤트 기획서가 왔습니다. 손님은 하루에 출석 상자를 세 개까지 받고, 상자를 열면 확률에 따라 포인트나 쿠폰이 나오거나 꽝이 나옵니다. 세 상자의 확률은 서로 다르고, 한 번 연 상자는 다시 못 씁니다.
앞의 문제들은 손님이 누른 것에 맞는 답을 돌려주는 일이었습니다. 이 문제에서는 처음으로 무엇이 나올지를 서버가 정하고, 그 결과에 책임을 집니다.
면접관이 이렇게 묻습니다
하루에 세 개까지 주는 출석 상자가 있고 상자마다 확률이 다릅니다. 테이블을 설계하고 쓸 쿼리까지 말씀해 보세요.
범위부터 좁힙니다
기획서의 조건은 넷입니다. 하루 세 개, 상자마다 다른 확률, 한 번만 열림, 그리고 나오는 것 가운데 포인트가 있다는 것.
마지막 조건이 나머지의 무게를 정합니다. 포인트는 나오는 즉시 결제에 쓸 수 있고, 쓰고 난 뒤에는 되돌릴 수 없습니다. 그래서 요구사항이 하나 더 붙습니다. 무엇이 왜 나왔는지를 나중에 다시 셀 수 있어야 한다.
뽑는 것보다 뽑은 것을 나중에 설명하는 일이 더 어렵습니다. 「왜 나만 계속 꽝이냐」는 문의에 답할 수 있는 설계와 답할 수 없는 설계가 여기서 갈립니다.
가장 많이 나오는 답
확률은 코드 안 배열에 두고 무작위 함수로 뽑습니다. 하루 세 개는 오늘 연 상자를 조회해서 셉니다.
double[] probs = {0.05, 0.25, 0.70}; // 포인트, 쿠폰, 꽝
if (countOpenedToday(me) >= 3) return;
Reward r = pick(probs);
save(me, r);
하루에 한 번씩 천천히 열어 보면 기획서대로 동작합니다.
그런데 여기서 깨집니다
조회와 삽입 사이에 두 요청이 들어오면 둘 다 「오늘 두 개」를 보고 둘 다 엽니다. 네 번째 상자가 열립니다.
확률을 바꾸려고 배포하면 어제의 확률은 어디에도 남지 않습니다. 한 달 뒤 「그날 확률이 얼마였냐」는 질문에 답할 길이 없습니다.
떨어지는 답은 이런 모양입니다
- 확률표를 코드 배열에 둡니다.
- 하루 세 개를 조회해서 세는 것으로 막습니다.
- 결과에 무엇이 나왔는지만 남깁니다.
- 포인트 예산을 넘긴 것을 정산하는 날에야 압니다.
면접관은 여기서 멈추지 않습니다
어제 오후 두 시에 그 손님이 받은 확률이 얼마였는지 답할 수 있나요?
한 달 뒤의 질문에 답할 기록이 남아 있는지 봅니다.
두 요청이 동시에 오면 네 번째 상자가 열리나요?
3부 선착순 쿠폰과 같은 모양의 틈을 알아보는지 봅니다.
포인트 예산을 넘기면 언제 알게 되나요?
확률과 예산이 서로를 모른다는 점을 짚는지 봅니다.
이 다음 판단은 책에서 이어집니다
책은 확률표와 하루 세 번 제한과 결과를 각각 어디에 둘지 정하고, 그 위에서 쓸 쿼리를 하나씩 보여 줍니다. 확률과 예산이 서로를 모를 때 생기는 일도 이어서 다룹니다.
19장에서 이어지는 것
- 확률표를 두는 자리
- 하루 세 번을 지키는 방법
- 결과를 나중에 다시 세는 방법
- 확률과 예산이 서로를 모를 때