테이블 목록에 이런 것이 있었다.
user_gift_box (유저 선물함 정보 테이블)
컬럼이 넷이다.
seq
user_id
gift_coin 선물코인
reg_date 선물도착 일시
Table of contents
Open Table of contents
바로 주면 안 되나
처음 든 생각이 이것이었다. 친구가 선물을 보내면 user_info 의 user_coin 을 바로 늘리면 되지 않나.
UPDATE user_info SET user_coin = user_coin + ? WHERE user_id = ?;
한 줄이다. 한 단계가 더 있으면 코드도 늘고 화면도 하나 더 필요한데 선물함이 왜 있는지가 궁금했다.
받는 행위가 남는다
며칠 생각하다 떠오른 것이 있다. 바로 넣으면 받는 행위가 없어진다.
바로 넣으면 로그인해 보니 user_coin 이 늘어 있는 것이다. user_gift_box 가 있으면 선물이 왔다는 안내를 보고 받기를 누른다. 게임에서 선물을 받는 순간이 하나의 이벤트다.
접속 이유가 되는 것도 있다. user_gift_box 에 선물이 쌓여 있으면 받으러 들어오게 되는데 바로 들어가 있으면 들어올 이유가 하나 준다.
유효기간을 걸 수 있다
또 하나 떠오른 것이 있다. reg_date 가 있으니 경과 시간을 잴 수 있고 도착한 지 며칠 지나면 소멸하게 만들 수 있다.
바로 user_coin 으로 들어가면 이런 것을 못 한다. 코인은 그냥 코인이라 받기 전 상태로 있어야 조건을 걸 수 있다.
다만 기한을 reg_date 에 기간을 더해 계산하는 방식이면 조심할 것이 있다. 기간을 서른 날에서 열흘로 줄이는 순간 이미 나가 있던 건까지 한꺼번에 당겨진다. expire_date 같은 만료 시각 컬럼을 따로 두고 넣을 때 박아 두면 그 건이 나갈 때의 기간이 그대로 남는다.
seq 가 기본키라 한 유저가 여러 행을 가질 수 있다.
user_id gift_coin reg_date
────────────────────────────
100 500 1월 1일
100 500 1월 2일
100 1000 1월 3일
보낸 사람마다 보낸 때마다 한 줄이라 몇 개 왔는지를 COUNT(*) 로 셀 수 있다. 다만 그 조회가 쓸모가 있으려면 user_id 에 인덱스가 있어야 하고 기본 키만 있으면 전부 훑는 쪽으로 간다.
문제 — 보낸 사람과 사유의 부재
여기서 걸린 것이 있다. 컬럼에 보낸 사람이 없다.
user_id 는 받는 사람으로 보이고 from_user_id 같은 컬럼이 없다. 그러면 누가 보냈는지를 알 수 없다. 누가 선물을 보냈다는 안내를 화면에 못 띄운다.
다만 이것이 빠진 것이 아닐 수도 있겠다 싶었다. 선물이 친구가 보낸 것만은 아닐 수 있어서 운영자 지급이나 이벤트 보상이나 레벨업 보너스에는 보낸 사람이 없다. 그러면 gift_coin 하나로 전부 같은 모양이 된다.
그래도 왜 왔는지는 있으면 좋아 보인다. 코인 로그에는 reason 이 있어서 변동 사유가 남는데 선물함에는 없다.
reason 이 있으면 친구 선물인지 이벤트 보상인지가 구분되고 없으면 전부 같은 선물이다. 받는 사람 입장에서 어디서 온 것인지 모르고 문의가 들어왔을 때 지급 시각을 이력과 맞춰 보는 수밖에 없다.
대기열과 이력의 분담
설계서에 받은 뒤 처리는 안 나와 있다. 받으면 행을 지우는 방식과 recv_date 로 받음 표시를 남기는 방식이 떠오르는데 컬럼에 상태가 없으니 삭제 쪽으로 보인다.
삭제하면 얼마나 받았는지가 안 남는다. 다만 코인 로그에는 남을 것이다.
log_coin
up_coin = +500
reason = "선물"
선물함은 대기열이고 코인 로그가 이력이 되는 구조로 보인다. 역할이 나뉘어 있다면 삭제해도 이력은 남고 대기열은 짧게 유지되며 이력은 계속 쌓인다.
받는 처리를 UPDATE 로 쓸 때 조건에 아직 안 받았다는 것을 같이 걸어 두면 버튼을 두 번 눌러도 두 번째는 조건에 안 걸려 affected_rows 가 0으로 온다. 그 값을 보고 잔액을 더할지 말지를 가르면 두 번 들어가는 일이 안 생긴다.
정리
- 선물을 바로 코인에 넣지 않고 별도 테이블에 둔다
- 바로 넣으면 유저가 온 것을 모른다
- 받는 행위가 하나의 이벤트가 된다
- 받을 것이 있다는 것이 들어올 이유가 된다
reg_date가 있으니 유효기간을 걸 수 있다- 기한은 도착 일시에서 계산하지 말고 만료 시각을 행에 박아 둔다
- 한 유저에 여러 건이 쌓이고 개수를 셀 수 있다
- 보낸 사람 컬럼이 없고 운영자 지급도 같은 모양이라 그럴 수 있다
- 사유 컬럼이 있으면 어디서 온 것인지 구분된다
- 선물함이 대기열이고 코인 로그가 이력으로 나뉘어 보인다
- 수령은
UPDATE조건에 미수령을 걸고affected_rows로 가른다