# 수익화 시스템 설계 ## 메타 정보 - **문서 버전**: 1.0 - **최종 수정**: 2026-01-16 - **상태**: 계획 단계 - **플랫폼**: Android/iOS (모바일 전용) - **광고 SDK**: AdMob --- ## Task 리스트 ### Phase 1: 데이터 구조 (선행 작업) - [ ] `MonetizationState` 모델 생성 - [ ] `DeathInfo.lostItem: EquipmentItem?` 필드 추가 - [ ] `GameSave` v3 → v4 마이그레이션 - [ ] 장비 손실 확률 공식 변경: `20% + (level-1) * 8.89%` - [ ] `ItemService.determineRarity()` 확률 수정: 34/40/20/5/1 ### Phase 2: AdMob 연동 - [ ] `google_mobile_ads` 패키지 추가 - [ ] `AdService` 클래스 생성 - [ ] 리워드 광고 로드/표시/콜백 구현 - [ ] 인터스티셜 광고 로드/표시/콜백 구현 - [ ] 디버그 빌드 광고 ON/OFF 토글 구현 ### Phase 3: IAP 연동 - [ ] `in_app_purchase` 패키지 추가 - [ ] 광고 제거 상품 등록 (Google Play / App Store) - [ ] `IAPService` 클래스 생성 - [ ] 구매 처리 로직 구현 - [ ] 구매 복원 로직 구현 - [ ] 구매 상태 영구 저장 ### Phase 4: 캐릭터 생성 광고 - [ ] 굴리기 횟수 상태 관리 (rollsRemaining) - [ ] 굴리기 횟수 저장/로드 구현 - [ ] 되돌리기 히스토리 관리 - [ ] 되돌리기 횟수 상태 관리 (undoRemaining) - [ ] 캐릭터 생성 UI 수정: 굴리기 버튼 - [ ] 캐릭터 생성 UI 수정: 되돌리기 버튼 ### Phase 5: 부활 시스템 - [ ] 사망 시 `DeathInfo.lostItem` 저장 로직 - [ ] `reviveWithAdReward()` 함수 구현 - [ ] `reviveWithoutAd()` 함수 구현 - [ ] 자동부활 버프 상태 관리 (autoReviveEndMs) - [ ] 자동부활 버프 중 사망 처리 로직 - [ ] 사망 화면 UI: 광고 부활 버튼 - [ ] 사망 화면 UI: 일반 부활 버튼 ### Phase 6: 속도업 - [ ] 속도 상태 관리 (1x/2x/5x) - [ ] 명예의 전당 캐릭터 존재 여부 확인 로직 - [ ] 5배속 버프 상태 관리 (speedBoostEndMs) - [ ] 속도 UI: 버튼 표시 로직 - [ ] 속도 UI: 남은 시간 표시 ### Phase 7: 복귀 보상 - [ ] `lastPlayTime` 저장/로드 구현 - [ ] 오프라인 시간 계산 로직 - [ ] 오프라인 진행 시뮬레이션 (1배/2배) - [ ] 보물 상자 축적 로직 - [ ] 보물 상자 내용물 생성 로직 - [ ] 행운의 부적 버프 발동 로직 - [ ] 복귀 보상 UI: 환영 다이얼로그 - [ ] 복귀 보상 UI: 상자 오픈 ### Phase 8: 디버그 기능 - [ ] 메인 메뉴: 디버그 옵션 섹션 (kDebugMode) - [ ] 스타트 화면: 디버그 옵션 섹션 - [ ] 광고 ON/OFF 토글 - [ ] IAP 구매 시뮬레이션 토글 - [ ] 오프라인 시간 시뮬레이션 --- ## 스펙 요약 ### 광고 유형 | ID | 유형 | 길이 | 사용처 | | -- | ---- | ---- | ------ | | AD_REWARD_REVIVE | 리워드 | 30초 | 부활 | | AD_REWARD_UNDO | 리워드 | 30초 | 캐릭터 생성 되돌리기 | | AD_INTERSTITIAL_ROLL | 인터스티셜 | 6초 | 굴리기 횟수 충전 | | AD_INTERSTITIAL_SPEED | 인터스티셜 | 6초 | 게임 속도업 | ### IAP 상품 | ID | 가격 | 유형 | | -- | ---- | ---- | | remove_ads | $9.99 | 비소모성 (1회 구매) | ### 무료 vs 구매 유저 비교 | 기능 | 무료 유저 | 구매 유저 | | ---- | --------- | --------- | | 광고 | 표시 | 제거 (버튼 클릭 시 바로 활성화) | | 복귀 상자 최대 | 5개 | 10개 | | 오프라인 진행 속도 | 1배 | 2배 | | 행운 버프 발동 | 1시간당 5분 | 30분당 5분 | | 캐릭터 되돌리기 | 1회 (광고) | 3회 (무료) | | 굴리기 충전 | 광고 필요 | 무제한 | | 속도업 | 광고 필요 | 무제한 | --- ## 상세 스펙 ### 1. 캐릭터 생성 - 굴리기 ```yaml rollsRemaining: default: 5 min: 0 max: 5 recharge: +5 (인터스티셜 광고 시청 후) persistence: 저장됨 (0회로 종료 시 재시작해도 0회) ``` ### 2. 캐릭터 생성 - 되돌리기 ```yaml undoRemaining: free_user: 1 paid_user: 3 ad_required: free_user: true (30초 리워드) paid_user: false range: 1단계 전만 reset: 새로 굴리기 시작 시 초기화 constraint: min(undoRemaining, rollHistory.length) ``` ### 3. 장비 손실 확률 ```yaml formula: 20 + (level - 1) * 80 / 9 level_1: 20% level_5: 56% level_10_plus: 100% code: | int calculateEquipmentLossChance(int level) { if (level >= 10) return 100; return 20 + ((level - 1) * 80 ~/ 9); } ``` ### 4. 부활 시스템 ```yaml normal_revive: ad: false hp_recovery: 50% equipment_loss: confirmed sacrifice: required ad_revive: ad: true (30초 리워드) hp_recovery: 100% equipment_loss: cancelled (lostItem 복구) sacrifice: none auto_revive_buff: duration: 600000ms (10분) effect: 버프 중 사망 시 자동부활 + 장비 손실 없음 ``` ### 5. 게임 속도 ```yaml speed_levels: - 1x: 기본 - 2x: 명예의 전당 캐릭터 1명 이상 시 해금 - 5x: 광고 시청 (5분간) 또는 IAP 구매 시 무제한 speed_boost: duration: 300000ms (5분) ad: 인터스티셜 6초 paid_user: 광고 없이 무제한 ``` ### 6. 복귀 보상 ```yaml offline_progress: free_user: 1x paid_user: 2x treasure_chest: rate: 1개/시간 max_free: 5개 max_paid: 10개 contents: equipment: 50% gold: 30% potion: 15% bonus_equipment: 5% lucky_charm_buff: free_user: 5분/오프라인1시간 paid_user: 5분/오프라인30분 max_duration: 30분 effect: common: 34% → 28% uncommon: 40% → 40% rare: 20% → 20% epic: 5% → 10% legendary: 1% → 2% ``` ### 7. 아이템 희귀도 (목표) ```yaml rarity_distribution: common: 34% uncommon: 40% rare: 20% epic: 5% legendary: 1% note: 현재 코드와 다름. ItemService.determineRarity() 수정 필요 ``` --- ## 데이터 모델 ### MonetizationState ```dart class MonetizationState { final bool adRemovalPurchased; // IAP 구매 여부 final int rollsRemaining; // 굴리기 남은 횟수 (0-5) final int undoRemaining; // 되돌리기 남은 횟수 final List? rollHistory; // 되돌리기용 히스토리 final int? autoReviveEndMs; // 자동부활 버프 종료 시점 final int? speedBoostEndMs; // 5배속 종료 시점 final DateTime? lastPlayTime; // 마지막 플레이 시각 final int pendingChests; // 미개봉 상자 개수 final int? luckyCharmEndMs; // 행운 버프 종료 시점 } ``` ### DeathInfo 확장 ```dart class DeathInfo { // 기존 필드 final String? lostItemName; final EquipmentSlot? lostItemSlot; final ItemRarity? lostItemRarity; // 신규 필드 final EquipmentItem? lostItem; // 복구용 전체 장비 정보 } ``` ### GameSave 버전 ```yaml current_version: 3 next_version: 4 migration: - add: MonetizationState monetization - add: DeathInfo.lostItem ``` --- ## 엣지 케이스 | 케이스 | 조건 | 처리 | | ------ | ---- | ---- | | 광고 로드 실패 | 네트워크 오류 | 재시도 버튼 표시 | | 오프라인 상태 | 네트워크 없음 | 광고 버튼 비활성화 | | 광고 중 앱 종료 | 광고 미완료 | 보상 미지급 | | IAP 복원 | 앱 재설치 | 구글/애플 구매기록 확인 | | 자동부활 중 종료 | 버프 활성 중 | 남은 시간 저장 | | 시간 조작 | lastPlayTime > now | 복귀 보상 없음 | | 굴리기 0회 종료 | rollsRemaining == 0 | 0회 유지 | | 되돌리기 초과 | undoRemaining > historyLength | min 적용 | --- ## 디버그 옵션 (kDebugMode 전용) ```yaml debug_options: ad_enabled: type: bool default: true off_behavior: 광고 버튼 클릭 시 바로 보상 on_behavior: 실제 광고 재생 iap_simulated: type: bool default: false off_behavior: 무료 유저로 동작 on_behavior: 구매 유저로 동작 offline_hours: type: int options: [0, 1, 5, 10] default: 0 purpose: 복귀 보상 테스트 locations: - 메인 메뉴 (광고 제거 버튼 아래) - 스타트 화면 ``` --- ## UI 요약 ### 메인 메뉴 ``` [ 새 게임 ] [ 불러오기 ] [ 설정 ] [ 명예의 전당 ] ──────────── [ 광고 제거 - $9.99 ] ← 구매 후 비활성화 ── Debug Only ── [ 광고: ON/OFF ] [ IAP: 미구매/구매 ] ``` ### 캐릭터 생성 ``` STR: 14 CON: 12 DEX: 10 INT: 16 WIS: 8 CHA: 11 Total: 71 [ 굴리기 (N/5) ] ← 0회 시 🎬 표시 [ 🎬 이전으로 (N/M) ] ← 무료:1회, 구매:3회 ``` ### 게임 화면 - 속도 ``` 명예의 전당 없음: [ 1x ] [ 🎬 5x ] 명예의 전당 있음: [ 1x ] [ 2x ] [ 🎬 5x ] 5배속 중: [ 5x ⏱️ 4:32 ] ``` ### 사망 화면 ``` ☠️ You Died Killed by: {monster} Lost: {item} [ 🎬 광고 부활 (30초) ] - 장비 복구 - 제물 없음 - HP 100% - 10분 자동부활 [ 일반 부활 ] - 장비 손실 - 제물 소모 - HP 50% ``` --- ## 참고 ### 관련 파일 - `lib/src/core/model/game_state.dart`: GameState 모델 - `lib/src/core/engine/progress_service.dart`: 사망 처리 로직 - `lib/src/core/storage/`: 저장/로드 시스템 - `lib/src/core/engine/item_service.dart`: 아이템 희귀도 결정 ### 의존성 패키지 ```yaml dependencies: google_mobile_ads: ^5.0.0 # AdMob in_app_purchase: ^3.1.0 # IAP ```