--- id: wiki-2026-0508-가차-gacha title: 가차(Gacha) category: 10_Wiki/Topics status: verified canonical_id: self aliases: [Gacha, ガチャ, 뽑기, Lootbox] duplicate_of: none source_trust_level: A confidence_score: 0.9 verification_status: applied tags: [game-design, monetization, randomness, mobile-game] raw_sources: [] last_reinforced: 2026-05-10 github_commit: pending tech_stack: language: TypeScript framework: Game Server (Node.js) --- # 가차(Gacha) ## 매 한 줄 > **"매 weighted random pull + pity system — 매 mobile game monetization 의 dominant 메커니즘."**. 1965 일본 캡슐 토이 (gachapon) 어원. 2010s Puzzle & Dragons / FGO / Genshin Impact 매 globalization. 매 2026 regulatory scrutiny (Belgium ban, China 概率 disclosure, Japan 上限) 매 mature. ## 매 핵심 ### 매 components - **Pool / Banner**: 매 pullable item set — rate-up, character-specific, standard. - **Rate**: 매 rarity 별 확률 (e.g. SSR 0.6%, SR 5.4%, R 94%). - **Pity**: 매 N pull guarantee — 매 player frustration cap (Genshin 90 pull, FGO 330). - **Soft pity**: 매 pity 근접 시 rate ramp (Genshin 75+ → SSR rate 폭증). - **Currency**: 매 premium (paid) vs free — 매 dual track. - **50/50**: 매 rate-up 미달 시 standard pool 으로 떨어짐. ### 매 design 축 - **Convergent vs divergent**: 매 dupe 가 useful (constellation) vs useless (shard). - **Hard pity**: 매 deterministic ceiling — 매 player trust. - **Spark / mileage**: 매 pull 누적 → 매 직접 교환 — 매 ultimate pity. ### 매 응용 1. Mobile RPG (Genshin Impact, Honkai Star Rail). 2. Card collection (Hearthstone pack 매 gacha 변형). 3. Battle pass 매 deterministic 변형. 4. Cosmetic-only gacha (매 regulatory safer). ## 💻 패턴 ### Weighted random pull ```typescript type Item = { id: string; rarity: 'SSR'|'SR'|'R'; rateUp?: boolean }; function pull(rates: Record, items: Item[]): Item { const r = Math.random(); let acc = 0; let chosenRarity: keyof typeof rates; for (const [rarity, p] of Object.entries(rates)) { acc += p; if (r < acc) { chosenRarity = rarity as any; break; } } const pool = items.filter(i => i.rarity === chosenRarity!); return pool[Math.floor(Math.random() * pool.length)]; } const rates = { SSR: 0.006, SR: 0.054, R: 0.94 }; ``` ### Soft + hard pity ```typescript class PitySystem { pulls = 0; softStart = 75; hardCap = 90; ssrRate(): number { if (this.pulls >= this.hardCap) return 1.0; if (this.pulls < this.softStart) return 0.006; // 매 linear ramp 75 → 89 const t = (this.pulls - this.softStart) / (this.hardCap - this.softStart); return 0.006 + t * (1.0 - 0.006); } pull(): { rarity: string; pulls: number } { this.pulls++; if (Math.random() < this.ssrRate()) { const out = { rarity: 'SSR', pulls: this.pulls }; this.pulls = 0; return out; } return { rarity: 'SR/R', pulls: this.pulls }; } } ``` ### 50/50 rate-up ```typescript class RateUpBanner { guaranteed = false; // 매 직전 SSR 이 off-banner 이면 다음 SSR rate-up 확정 rollSSR(featured: Item, standardSSRs: Item[]): Item { if (this.guaranteed) { this.guaranteed = false; return featured; } if (Math.random() < 0.5) { this.guaranteed = false; return featured; } this.guaranteed = true; return standardSSRs[Math.floor(Math.random() * standardSSRs.length)]; } } ``` ### Spark / mileage shop ```typescript type Wallet = { stones: number; mileage: number }; function spend(wallet: Wallet, cost: number) { if (wallet.stones < cost) throw new Error('insufficient'); wallet.stones -= cost; wallet.mileage += 1; // 매 pull 당 1 mileage } function exchangeMileage(wallet: Wallet, item: Item, price = 300) { if (wallet.mileage < price) throw new Error('mileage 부족'); wallet.mileage -= price; return item; } ``` ### 매 rate disclosure (compliance) ```typescript // 매 일본 JOGA / 중국 网信办 매 mandatory disclosure. function bannerDisclosure(banner: Banner) { return { rates: banner.rates, // SSR 0.6% etc pity: { soft: 75, hard: 90 }, rateUpItems: banner.featured.map(i => i.id), expectedCostJPY: estimateExpectedCost(banner), }; } ``` ### Server-side roll (anti-cheat) ```typescript import { randomBytes } from 'node:crypto'; // 매 client 의 RNG 신뢰 X — 매 server 결정. async function serverPull(userId: string, bannerId: string) { const seed = randomBytes(16).toString('hex'); const result = pull(bannerRates[bannerId], items); await db.gachaLog.insert({ userId, bannerId, seed, result, ts: Date.now() }); return result; } ``` ## 매 결정 기준 | 상황 | Approach | |---|---| | 매 player 신뢰 | hard pity + spark | | 매 monetization 극대화 | soft pity 후반 ramp | | 매 collection 게임 | convergent (constellation 유용) | | 매 PVP 밸런스 | 매 cosmetic-only 우선 (regulatory safe) | | 매 신규 banner | 50/50 with rate-up | **기본값**: 매 soft pity 75 / hard 90 / 50-50 / spark 300 — 매 Genshin model 의 industry baseline. ## 🔗 Graph - 부모: [[Game_Monetization]] · [[Random_Number_Generation]] - 변형: [[Lootbox]] · [[Battle_Pass]] · [[Card_Pack]] - 응용: [[Genshin_Impact]] · [[Honkai_Star_Rail]] · [[FGO]] - Adjacent: [[Pity_System]] · [[Whale_Mechanics]] · [[Game_Regulation]] ## 🤖 LLM 활용 **언제**: 매 mobile RPG monetization 설계, gacha sim, drop rate calculation. **언제 X**: 매 Belgium / Netherlands market (매 lootbox 금지). 매 PEGI 18 관련 region risk. ## ❌ 안티패턴 - **Hidden rate**: 매 disclosure X — 매 regulatory ban / store removal 위험. - **No pity**: 매 player frustration → churn 폭증. - **Client-side RNG**: 매 trivially exploit — 매 packet replay attack. - **Stacking dupes 무용**: 매 SSR pull 후 dupe = 매 무가치 → 매 trust 손실. 매 conversion 시스템 mandatory. - **PvP P2W gacha**: 매 정체된 player base — 매 cosmetic 분리. ## 🧪 검증 / 중복 - Verified (Genshin Wiki rate data, JOGA guidelines, Belgium Gaming Commission report). - 신뢰도 A. ## 🕓 Changelog | 날짜 | 변경 | |---|---| | 2026-05-08 | Phase 1 | | 2026-05-10 | Manual cleanup — gacha mechanics + pity / regulatory |