Files
2nd/10_Wiki/Topics/Architecture/가차(Gacha).md
T
Antigravity Agent f8b21af4be Wiki cleanup: error-doc removal, dedup merge, link normalization
10_Wiki/Topics 대규모 정리:
- 오류 캡처/미완성 stub 문서 227개 제거
- 교차폴더 중복 43클러스터 병합 (63파일 → redirect)
- 링크명 정규화: 깨진 링크 수정·redirect 직결·개념 매핑 ~2,400건
- 카테고리 MOC 6개 신규 생성
- Graph 섹션 미해결 related-keyword 링크 10,058건 제거

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 23:52:15 +09:00

6.0 KiB

id, title, category, status, canonical_id, aliases, duplicate_of, source_trust_level, confidence_score, verification_status, tags, raw_sources, last_reinforced, github_commit, tech_stack
id title category status canonical_id aliases duplicate_of source_trust_level confidence_score verification_status tags raw_sources last_reinforced github_commit tech_stack
wiki-2026-0508-가차-gacha 가차(Gacha) 10_Wiki/Topics verified self
Gacha
ガチャ
뽑기
Lootbox
none A 0.9 applied
game-design
monetization
randomness
mobile-game
2026-05-10 pending
language framework
TypeScript 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

type Item = { id: string; rarity: 'SSR'|'SR'|'R'; rateUp?: boolean };

function pull(rates: Record<string, number>, 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

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

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

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)

// 매 일본 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)

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

🤖 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