스티커 정책
1. 목적
사용자가 콘텐츠를 정주행하면 리워드 스티커를 획득하여 수집 도감을 완성하는 게임화 요소를 제공합니다. 스티커 시스템은 사용자 참여도를 높이고, 콘텐츠 소비를 촉진하는 핵심 인센티브입니다.
2. 스티커 기본 구조
2-1. 스티커 (Sticker)
| 필드 | 타입 | 설명 |
|---|---|---|
episode | OneToOneField | 에피소드와 1:1 관계 |
name | CharField(200) | 스티커 이름 (다국어, TranslatableModel) |
image_url | URLField(500) | 스티커 이미지 URL |
base_score | FloatField | 사전 계산된 기본 점수 (크론에서 업데이트) |
score_updated_at | DateTimeField | 점수 마지막 업데이트 시각 |
- 에피소드 1개당 스티커 1개가 반드시 존재합니다.
- 스티커 이름은
TranslatableModel기반으로 서비스 언어별 제공됩니다.
2-2. 획득 (UserSticker)
- 사용자가 에피소드를 완독하면 스티커를 획득합니다.
- 고유 제약:
user+sticker조합 (중복 획득 불가) earned_at으로 획득 시각을 기록합니다.
3. 획득 API
3-1. 스티커 획득
- Endpoint:
POST /api/stickers/earn/<episode_id>/ - 에피소드 완독 후 호출하여 스티커를 획득합니다.
- 이미 획득한 스티커를 다시 요청하면 중복 처리 방지됩니다.
3-2. 보유 스티커 목록
- Endpoint:
GET /api/stickers/ - 사용자가 보유한 전체 스티커 목록을 반환합니다.
4. 스코어링 시스템
스티커 노출 우선순위를 결정하는 점수 계산 로직입니다. 크론 작업을 통해 주기적으로 base_score가 업데이트됩니다.
4-1. 점수 계산 공식
base_score = 신규(+3) + 캠페인(+2) + 어제노출(-1) + 인기도(+0.1 * 수집자수)
| 요소 | 점수 | 조건 |
|---|---|---|
| 신규 스티커 | +3 | 최근 등록된 스티커 |
| 캠페인 대상 | +2 | 활성 캠페인에 포함된 스티커 |
| 어제 노출 | -1 | 전일 노출 이력이 있는 스티커 |
| 인기도 보너스 | +0.1 * 수집자 수 | 수집자 수에 비례한 가산점 |
4-2. 노출 추적 페널티
최근 7일 내 Popular/Missing 영역에서 노출된 스티커에는 -2점이 추가로 적용되어, 동일 스티커가 반복 노출되는 것을 방지합니다.
5. 스티커 통계 (StickerStats)
스티커별 수집자 수를 기간별로 집계합니다.
| 필드 | 설명 |
|---|---|
total_collectors | 전체 수집자 수 |
daily_collectors | 일간 수집자 수 |
weekly_collectors | 주간 수집자 수 |
monthly_collectors | 월간 수집자 수 |
last_updated | 마지막 업데이트 시각 |
- 스티커와 1:1 관계 (OneToOne)
API
- Endpoint:
GET /api/stickers/stats/
6. 인기 스티커 (StickersPopular)
기간별, 국가별 인기 스티커 순위를 관리합니다.
| 필드 | 설명 |
|---|---|
position | 순위 |
popularity_score | 인기 점수 |
period | 집계 기간: daily / weekly / monthly / all-time |
country | 국가 코드 (KR, JP, EN, ES) 또는 null (글로벌) |
- 고유 제약:
sticker+period+country조합
API
- Endpoint:
GET /api/stickers/popular/ - 디버그:
GET /api/stickers/popular/debug/<sticker_id>/
7. 미보유 스티커 (StickersMissing)
사용자가 아직 보유하지 않은 스티커 목록을 관리합니다.
| 필드 | 설명 |
|---|---|
user | 사용자 |
sticker | 미보유 스티커 |
position | 노출 순서 |
- 고유 제약:
user+sticker조합 position및created_at기준으로 정렬됩니다.
API
- Endpoint:
GET /api/stickers/missing/
8. 공개 예정 스티커 (StickersUpcoming)
아직 공개되지 않은 예정 스티커를 관리합니다.
| 필드 | 설명 |
|---|---|
release_date | 공개 예정일 |
is_featured | 주요 스티커 여부 |
position | 노출 순서 |
API
- Endpoint:
GET /api/stickers/upcoming/
9. 위시리스트 (StickerWishlist)
사용자가 관심 있는 공개 예정 스티커를 저장합니다.
- 고유 제약:
user+sticker조합 - 최신순 정렬
API
- 목록 조회 / 추가:
GET / POST /api/stickers/wishlist/ - 삭제:
DELETE /api/stickers/wishlist/<sticker_id>/
10. 노출 추적 (StickerExposure)
사용자에게 Popular/Missing 영역에서 노출된 스티커를 기록하여 점수 계산에 활용합니다.
| 필드 | 설명 |
|---|---|
exposure_type | popular (인기 영역) 또는 missing (미보유 영역) |
exposed_at | 노출 시각 |
- 고유 제약:
user+sticker+exposure_type조합 - 동일 조합은 1개만 유지되며,
exposed_at만 업데이트됩니다. - 최근 7일 내 노출된 스티커에 -2점 페널티가 적용됩니다.
11. 캠페인 (StickerCampaign)
이벤트/캠페인과 스티커를 연결하여 노출 우선순위를 부스트합니다.
| 필드 | 설명 |
|---|---|
event | 연결된 이벤트 (FK, 선택적) |
campaign_name | 캠페인 이름 |
is_active | 활성 여부 |
priority_boost | 우선순위 가산점 (기본 +2점, 조정 가능) |
start_date | 캠페인 시작일 |
end_date | 캠페인 종료일 (nullable) |
- 캠페인 대상 스티커에는
priority_boost만큼의 가산점이 적용됩니다. is_ongoing속성으로 현재 진행 중 여부를 판단합니다:is_active가 true이고, 현재 시각이start_date와end_date사이인 경우