System Design · Retention

출석 시스템 설계

연속 출석(단기) · 누적 출석(장기) 2종을 한 시스템으로 묶어 리텐션을 설계

작성 한승호 프로젝트 복싱스타 : 매치 3 (런칭 ~ 라이브 서비스) 역할 리텐션 개선 시스템 신규 설계 — 규칙 · 데이터 구조 · 지표 로그 성과 도입 후 리텐션 지표 개선 확인

출석 시스템은 만들기는 쉽지만 "왜 이 숫자인가"를 설명하기 어려운 시스템입니다. 이 문서는 연속 7일 · 누적 10일 간격 · 3개 보상 그룹 같은 값 하나하나에 벤치마킹과 판단 근거를 붙이고(Design Note), 만든 뒤에도 어느 일차에서 이탈하는지 · 보상이 실제 재접속 동기가 되는지 확인할 수 있도록 지표 로그까지 함께 설계했습니다.

재직 중 직접 작성한 사내 기획서를 포트폴리오용으로 재구성한 것입니다. 회사 로고 · 대외비 표기 · 편집자 메모는 제거했고, 테이블 · 컬럼명 · 지표 이벤트명은 실제 스키마와 다르게 표기했습니다(구조 · 의미는 동일). 화면 이미지는 당시 와이어프레임을 그대로 사용했으며, 데이터 테이블은 핵심 로직 설명용으로 축약되었습니다.

1. 배경과 목표

이슈

문제
  • 리텐션을 올릴 수 있는 새로운 시스템이 필요함
해결 방향
  • 접속을 유도하는 출석 시스템 개발
기대 효과
  • 유저 접속 빈도 증가로 리텐션 상승
  • 다양한 보상 지급으로 타 콘텐츠 경험 유도
  • 이후 추가 개발을 통한 수익 창출

출석 시스템 = 유저의 게임 접속 여부와 빈도에 따라 보상을 주는 시스템. 하루에 한 번 출석 시 일일 보상을 지급하고, 출석의 종류를 연속 출석과 누적 출석 두 가지로 나눕니다.

출석 시스템 흐름

출석 (하루 1회)

미출석 상태에서 최초 접속 시 출석 상태로 전환

↓

연속 출석

연속해서 출석한 횟수에 맞는 일일 보상 지급 — 미접속 시 초기화

↓

누적 출석

총 출석한 횟수가 목표 수준에 도달하면 보상 지급 — 초기화 없음

2. 연속 vs 누적 — 두 트랙으로 나눈 이유

설계 의도

연속 출석 하나만 두면, 하루라도 놓쳐 초기화됐을 때 실패에 대한 스트레스가 큽니다. 출석 일수가 커진 유저일수록 이 스트레스도 커져서, 오히려 이탈 사유가 될 수 있습니다.

그래서 초기화되지 않는 누적 출석을 별개 트랙으로 둡니다. 연속 출석은 단기 연속 접속을 유도하고, 누적 출석은 실패 부담을 상쇄하며 장기 리텐션을 담당합니다. 두 트랙은 완전히 독립적이지 않아서, 연속 출석에 데이터가 없으면 누적 출석까지 오류가 날 수 있어 디폴트 값 처리를 함께 설계했습니다.

출석 체크 — 상태와 전환

미출석 상태

계정 생성 시 최초 상태. UTC 00시가 되면 이 상태로 초기화

→

→ 출석 상태

하루 동안 게임에 최초 접속 시 미출석 → 출석 상태로 전환

출석 횟수를 계산해 연속으로 출석한 횟수와 총 누적 출석 횟수를 각각 관리하고, 그에 따라 보상이 지급됩니다. 유저 출석 상태는 출석 시스템이 활성화된 이후부터 체크합니다.

3. 연속 출석 (단기)

기본 규칙

진행
  • 출석 후 다음 날에도 연속 출석하면 출석부가 진행되며, 일차별로 다른 일일 보상 획득
  • 최초 출석 시 1일차부터 시작, 최대 7일차까지
초기화
  • 미접속 시 1일차부터 다시 시작
  • 7일차까지 출석 후 다음 일차가 될 때도 초기화 (다시 1일차부터)
  • 보상 업데이트 등의 이유로 전체 유저 출석부를 초기화하는 경우도 있음
보상 수령
  • 출석한 일차 보상을 1회에 한해 수령 가능
  • 획득 순서는 순차적이지 않음 — 다음 일차 보상을 먼저 수령 가능
  • 초기화 시 미수령 보상('미수령 보상')은 삭제되어 수령 불가

Design Note — 연속 출석부 길이를 7일로 정한 이유

출석부가 너무 길거나 짧으면 유저가 목표로 삼기 어렵다고 판단했습니다. 벤치마킹한 캐주얼 게임(모노폴리 고 · 코인 마스터 · 트리플 매치 등)이 대부분 7일로 설정되어 있었고, 사회적으로 1주일(7일)이 기본 생활 주기라 유저가 이해하고 적응하기 쉬울 것이라 판단해 7일로 정했습니다.

ContinuousRewardTable

연속 출석 일차별 보상 정의

컬럼자료형설명
PatternIdInteger일일 보상 세트(패턴)를 구분하는 값
DayIndexInteger패턴 내 일차 (1~7)
RewardIdInteger
  • 해당 일차에 지급할 보상 패키지 ID (RewardData 컨테이너 참조)
  • 같은 일차에 여러 RewardId를 두면 해당 아이템 모두 지급

Design Note — 연속 출석 보상 운영을 Constant 값으로 관리

초기엔 운영 웹에서 출석 스케줄을 관리하려 했으나 개발을 중지했습니다. 운영 웹 구현·유지 비용이 콘텐츠 볼륨에 비해 크고, 연속 출석 보상을 자주 교체하지 않을 것이며, 월 1회 패치 때 Constant 테이블의 '기본 연속 출석부 ID' 값만 바꿔주면 보상 교체가 가능하다고 판단했기 때문입니다. 정의되지 않은 기간엔 이 기본값을 불러와 오류를 방지합니다.

4. 누적 출석 (장기)

기본 규칙

진행
  • 매일 출석할 때마다 누적 출석일이 1씩 증가
  • 연속 출석과 달리 연달아 출석하지 않아도 초기화되지 않음
보상
  • 10일 간격으로 누적 출석 보상 획득 가능
  • 보상을 터치해 획득 가능하며, 현재 누적 출석부에 있는 보상을 전부 수령할 수 있을 때만 다음 보상이 노출됨 → 연속 출석과 달리 미수령 보상이 발생하지 않음
볼륨
  • 최초 버전 기준 누적 출석부 길이 60일 (6개 보상)
  • 총 300일까지 길이를 늘릴 예정, 이후로는 로테이션되는 누적 출석 시스템 추가 개발 예정

Design Note — 누적 출석 보상이 10일 간격인 이유

자주 지급하면 보상으로 줄 수 있는 아이템이 금방 고갈됩니다. "월에 몇 번 보상을 지급할 것인가"를 기준으로 세웠을 때, 2번은 장기 접속 동기로 부족하고, 4번은 연속 출석 지급과 겹칠 것으로 판단해 3번(10일 · 20일 · 30일)으로 선정했습니다.

누적 출석 보상 그룹 — 3개씩 묶음

Group 001

보상 A(10일) · B(20일) · C(30일)

→

Group 002

보상 A(40일) · B(50일) · C(60일) — 이전 그룹 전부 수령 시 '갱신'

→

Group 003 …

동일 구조로 반복. 누적 출석일은 그룹 갱신과 별도로 계속 증가

Design Note — 보상을 3개씩 그룹으로 묶은 이유

유저에게 보이는 화면은 한정적이라 모든 보상을 한 화면에 보여줄 수 없습니다. 유저가 월 단위로 보상을 인지하고 목표를 세울 수 있도록 3개(≈30일) 단위로 구분했고, 그룹별로 동일 컨셉의 코스튬을 연달아 지급하면 "세트를 다 모으는 것"이 출석 동기가 됩니다.

Design Note — 누적 출석부 길이를 뒤에 계속 늘리지 않은 이유

새 보상을 출석부 뒤에 계속 추가하는 방식은 ① 리소스 제작 속도가 업데이트 속도를 못 따라가고 ② 장기 유지 유저 일부만을 위한 업데이트가 된다는 문제가 있습니다. 현재 출석부를 다 진행한 유저에게는 동일한 보상을 반복 지급하는 방식을 도입해, 누적 보상 데이터가 없어 생기는 오류를 막고 새 리소스를 제작할 시간을 벌 수 있게 했습니다.

그룹 진행도 — 프로그레스 바

GroupProgress

현재 그룹의 총 길이(30일) 대비 유저의 출석일을 수치로 (0 ~ 30). 예: 24/30 = 80%

→

표시

보상 A·B·C 획득 지점에 마커. 그룹이 갱신될 때 0으로 초기화

Design Note — 그룹 진행도가 필요한 이유

보상까지 남은 수치가 안 보이면 유저가 직관적으로 받아들이기 어렵습니다. 전체 출석일이 아니라 그룹별 진행도를 프로그레스 바로 보여줘, 출석할 때마다 바가 눈에 띄게 차서 성취감을 느끼고 '이 그룹을 다 채우는 것'을 단기 목표로 삼도록 했습니다.

CumulativeRewardTable

누적 출석 그룹별 보상 정의

컬럼자료형설명
GroupKeyInteger그룹을 구분하는 값
TargetDayInteger
  • 보상을 지급하는 누적 출석일
  • 누적 출석일 ≥ TargetDay 일 때 획득 가능
RewardIdInteger누적 보상 패키지 ID (아이템 ID · 수량 · 리소스 포함, RewardData 참조)
GroupImageString그룹 이미지 파일명 (컨테이너로 관리)

5. 팝업 호출 & 시스템 활성화

팝업 창 호출 조건

출석 시
게임에 접속해 출석 처리되고, 수령하지 않은 출석 보상이 있으면 팝업 강제 호출 (연속 · 누적 보상 중 하나라도 미수령)
UI 클릭 시
로비의 출석부 알림 아이콘 / 옵션 창의 출석부 알림 버튼 터치 시
우선순위
팝업 창 · 아이콘은 상시 로비에서 확인 가능하므로 우선순위 높음. 강제 호출은 로그인 이벤트 다음 순서

출석 시스템 활성화

게임 시작

비활성화 상태 — 출석 처리 안 됨, 알림 아이콘 미표시

→

트로피 점수 달성

트로피 점수가 기준치를 넘으면 활성화

→

출석 시스템 활성화

활성화된 날부터 출석 처리 · 연속/누적 출석 · 로비/옵션 아이콘 활성화

Design Note — 활성화 시점에 대한 고민

출석 시스템을 언제부터 유저에게 학습시키고 보상을 지급할지 고민했습니다. 빨리 하면 초기 리텐션은 올릴 수 있지만 아직 언락되지 않은 아이템이 보상으로 지급될 수 있고, 늦게 하면 초기 리텐션을 못 올립니다. 기본 튜토리얼이 끝나고, 글러브 종류에 따라 효과가 다르다는 것을 학습했을 것으로 판단되는 트로피 점수를 활성화 시점으로 결정했습니다.

6. 화면 구성

출석부 팝업 창 — 상단(명칭·뒤로가기) / 중단(누적 출석) / 하단(연속 출석) 3영역. 당시 와이어프레임.
출석부 팝업 창 — 상단(명칭·뒤로가기) / 중단(누적 출석) / 하단(연속 출석) 3영역. 당시 와이어프레임.

팝업 창 영역

① 상단 영역
  • 출석부 명칭
  • 뒤로 가기 버튼
  • 규칙 안내(Information) 버튼
② 중단 영역 (누적)
  • 현재 그룹 세트 이미지 · 타이틀
  • 누적 보상 A·B·C (지급 일자 · 보상 아이콘, 수령 시 체크 이미지로 전환)
  • 그룹 진행도 프로그레스 바
  • 누적 출석 일수 텍스트
  • 그룹 리스트 페이지 이동 아이콘
③ 하단 영역 (연속)
  • 1~7일차 보상 (일차 텍스트 · 보상 이미지, 7일차는 강조)
  • 획득 가능 보상 / 수령한 보상 이미지 분기

보상 수령 화면

리워드 팝업창

수령할 보상 이미지 · GET 버튼

→

박스 개봉 연출

보상이 랜덤 박스인 경우 — 글러브 박스 → 서브 스킬 박스 → 스티커 박스 순 개봉 (기존 연출 재사용)

출석 연출 자체는 팝업창의 컨셉을 정한 뒤 파트 담당자와 협의하도록 열어두고, 보상 수령 연출은 별도 구현 없이 현재 게임에 도입된 연출을 재사용했습니다.

7. 지표 로그 설계

"만들고 끝"이 아니라, 출석부가 실제로 리텐션에 기여하는지 확인할 수 있도록 로그를 함께 설계했습니다.

공통 추적자 속성 (모든 출석 이벤트에서 수집)

continuous_count
  • 유저의 현재 연속 출석 횟수
continuous_reward_state
  • 연속 출석 보상 수령 상태를 7자리 숫자 문자열로 (좌→우 1~7일차)
  • 0: 출석 안 함 / 1: 출석했으나 보상 안 받음 / 2: 출석·보상 모두 받음
  • 예: 1211210
cumulative_count
  • 유저의 현재 누적 출석 횟수

이벤트 로그

출석부 도입에 따른 지표 변화를 판단하기 위한 4개 이벤트

컬럼자료형설명
attendance_info_checked로비 진입 전
  • 연속/누적 출석부의 진행 속도·분포 파악
  • 연속 출석 횟수가 낮은 수치에서만 반복되면 → 연속 보상이 접속 동기가 안 됨 → 보상 변경으로 개선
  • 누적 횟수가 일정 수치에서 안 올라가면 → 그 구간에 이탈 유저 발생 추정
continuous_reward_claimed연속 보상 수령 시
  • 어떤 보상을 수령했는지 기록 (보상 인덱스)
  • 특정 보상 수령 횟수가 적으면 → 유저들이 해당 보상을 원하지 않는다고 추정
cumulative_reward_claimed누적 보상 수령 시
  • 수령한 누적 보상 인덱스 기록
  • TargetDay와 누적 출석 횟수의 차이가 적을수록 → 보상 획득을 위해 꾸준히 출석 / 팝업 정보를 확인 중이라고 추정
attendance_popup_opened팝업 호출 시
  • popup_open_source: auto_triggered / via_alarm_icon / via_menu_list
  • 강제로 뜬 게 아니라 직접 눌러서 연 유저가 많다면 → 출석부에 관심이 있고 보상 정보를 확인하고 싶어 한다고 추정

8. 도입 결과

실제 도입 화면 — 출석부 팝업(연속·누적 출석 UI).
실제 도입 화면 — 출석부 팝업(연속·누적 출석 UI).
실제 도입 화면 — 누적 출석 보상(의상) 리스트.
실제 도입 화면 — 누적 출석 보상(의상) 리스트.

회고

출석 시스템은 기능 구현보다 "이 숫자가 왜 이 값인가"를 팀에 설득하는 게 어렵습니다. 7일 · 10일 · 3그룹 같은 값에 벤치마킹과 판단 근거를 붙여 문서화했고, 만든 뒤에도 지표 로그로 검증·개선할 수 있게 한 것이 이 설계의 핵심입니다.