본문 바로가기

이벤트 즉석 상품 당첨 로직 개발하기

by 식 2023. 1. 3.

 

신년 이벤트로 즉석 상품 당첨을 개발하게 되었다

 

막연히 당첨 확률을 지정하고 랜덤 함수를 돌리면 되겠지 싶긴 했는데..

 

지원자가 몇명일지도 모르겠고 몇가지 조건들이 있어서 머리가 아팠던 기억을 정리한다

 

 

조건

당첨 상품은 1~4등이 있고, 3등까지는 개수 제한이 있음

한달간 진행되며 상품은 날짜별로 주기적으로 풀림

휴대폰 번호를 고유값으로 참여

당첨결과는 즉석해서 조회

상품은 모두 분배되어야 함

 


 

테이블 설계

create table Request
(
	id bigint primary key auto_increment,
	phone_number varchar(20) null,
	ip_addr varchar(20) null,
	user_agent text null,
	created_at datetime default CURRENT_TIMESTAMP not null
);

create index request_phone_number_index
	on Request (phone_number);

create table Prize
(
	id int primary key auto_increment,
	ranking tinyint default 1 not null,
	request_id bigint null,
	start_at timestamp null,
	updated_at timestamp CURRENT_TIMESTAMP null
);

참여 테이블은 휴대폰 번호 조회가 잦을 예정이니 인덱싱 걸어두었다

참여자의 아이피와 유저에이전트도 기록해두는게 좋다.

 

상품 테이블에 미리 지정된 상품을 순위와 랭킹에 맞게 INSERT로 사전 작업 해둔다

참여 아이디를 외래키로 두고 업데이트 시각을 당첨시각으로 계산한다

 

 


 

서버 개발(PHP)

// 응모했는지 여부 체크
$sql = "SELECT COUNT(*) as cnt FROM Request WHERE phone_number = '{$phoneNumber}'";
$row = sql_fetch($sql);
if ($row && ($row['cnt'] > 0)) {
    http_response_code(409);
    return;
}

// 요청 추가
$sql = "INSERT INTO Request (phone_number, auth_code, ip_addr, user_agent) VALUES ('{$phoneNumber}', '{$authCode}', '{$ipAddr}', '{$userAgent}')";
sql_query($sql);

// 요청 아이디 가져오기
$requestId = sql_insert_id();

// 당첨 후보 선정
$isCandidate = $requestId % 1000 == 0;
$rank = 4;
if ($isCandidate) {
    $sql = "UPDATE Prize SET request_id = {$requestId}, updated_at = NOW() WHERE start_at < NOW() AND request_id IS NULL ORDER BY RAND() LIMIT 1";
    sql_query($sql);

    $sql = "SELECT * FROM Prize WHERE request_id = {$requestId}";
    $row = sql_fetch($sql);

	if($row) {
    	$rank = $row['ranking'];
    }
}

echo json_encode(array('rank' => $rank), true);

 

몇명이 참여할지 모르는 프로젝트고 주기적으로 상품이 풀려야 했다

 

우선은 지원자 천명마다 당첨 후보를 뽑고 [수령 가능 기간]이고 [당첨자가 선정 되지 않은] 상품이 있으면 해당 상품을 수령하기로 했다

 

매일 지원자수를 보고 가중치를 조정하기가 괜찮다고 생각했는데 해놓고 나니 생각대로 돌아가서 좋았다

 

[요청 아이디] % 500 == 0 && [숫자 1~3] > 2

 

당첨 후보자를 가변적으로 가중치를 주고 싶으면 이런식으로 가는것도 나쁘진 않았을듯하다.

 

 

 


 

즉석 상품 당첨 이벤트는..

당첨 로직을 개발하다 보면 신경이 예민해진다

 

단기간에 하는 일이라 작은 실수 하나에 당첨자가 상품수보다 많아지는 불상사가 생기는 경우도 직접 봤고

 

상품이 걸려있다보니 어뷰징이나 부정하게 수급하려고 하는 사람들도 간혹 있어서 시큐어 코딩에 신경을 써야 하고

 

일회성 프로젝트다 보니 담당자도 적고 개발 인력도 관리도 안되서 조작 하기가 너무 쉽고 간단하니깐 유혹에 빠지기도 쉽다

 

주변에 그런 경우를 너무 많이 봐서 정부나 대기업 이벤트라도 주최측에서 다 해먹겠지 싶어서 애초에 이런데 지원도 안하고 살았는데

 

구글 어널리틱스로 실시간으로 참여자를 보는데 전국적으로 많이 참여한걸 보자니..

 

각자의 설레임을 안고 참여할텐데 몰래 상품 3등 상품이라도 하나 받을까 살짝 흔들렸던 마음마저도 죄스럽게 느껴진다

 

나야 돈도 가오도 없지만.. 이런거 조작하면 영혼이 오염되는거 같아서 못하겠다

 

 

 

벌써 2023년

 

올해 목표는 봄여름가을겨울 놓치지 않고 다 즐기고 살기.

 

1월 1일은 또 이렇게 일하다 놓쳐버렸지만..

 

재밌게 살자

반응형