예상매출 = DAU × PU% × ARPPU: 매출 시뮬레이션 만들기

목표 KPI가 코앞인데 “이대로면 얼마 나올까요?”라는 질문을 받으면, 예전의 나는 한참을 헤맸다. 문제는 그거였다 — 미달이 확인될 때쯤엔 BM 대응 액션이 이미 늦는다. 그래서 매출을 세 변수로 쪼갠 시뮬레이션을 만들어, 월 중반에 “지금 페이스면 미달”이라는 신호를 미리 받도록 했다. 이 글은 그 설계 과정을 일반화해 복원한 기록이다. (수치는 전부 가데이터다.)

매출은 왜 세 조각으로 쪼개지나?

라이브 게임 매출의 뼈대는 단순하다.

flowchart LR
  classDef b fill:#fef7e0,stroke:#b06000,stroke-width:1.4px,color:#202124
  DAU["예상 DAU"] -->|"× PU%"| PU["결제 유저"]
  PU -->|"× ARPPU"| REV["예상 매출"]
  class DAU,PU,REV b

쪼개두면 결과가 빗나갔을 때 어느 조각이 빗나갔는지 바로 짚힌다. 매출은 결과일 뿐, 손댈 수 있는 건 이 세 변수다.

DAU를 어떻게 ‘예측’했나?

여기가 이 시뮬레이션의 핵심이었다. DAU를 감으로 찍는 게 아니라, 유입과 리텐션에서 역산했다. 실제 설계 순서는 이랬다.

flowchart TB
  classDef s fill:#e8f0fe,stroke:#1a73e8,stroke-width:1.4px,color:#202124
  A["① 마케팅으로 유입될 신규·복귀 예상 유저수"]:::s --> C
  B["② 전월에서 이어질 기존 예상 유저수"]:::s --> C
  C["③ 최근 3개월 평균 M+1 리텐션 적용"]:::s --> D["예상 MAU"]:::s
  D --> E["최근 3개월 일평균 DAU 대비율로 예상 일평균 DAU"]:::s
  • ① 마케팅 계획에서 신규·복귀 예상 유입을 받고,
  • ② 전월에서 넘어올 기존 유저를 추정하고,
  • ③ 거기에 최근 3개월 평균 M+1 리텐션을 곱해 예상 MAU를 만들고,
  • 마지막에 최근 3개월 ‘일평균 DAU / MAU’ 비율로 예상 일평균 DAU를 환산했다.

과거 데이터에서 뽑은 비율을 쓰니, 예측이 ‘희망’이 아니라 ‘근거’가 됐다.

유형을 왜 나눠서 예측하나?

처음엔 전체를 한 덩어리로 곱했다. 그런데 신규·복귀·기존은 리텐션도 결제 성향도 완전히 다르다. 뭉뚱그리면 평균의 함정에 빠진다. 그래서 셋을 나눠 각각 곱하고 합산했다.

유형예상 DAUPU%ARPPU(원)예상매출(원)
신규3,0002%15,000900,000
복귀1,0004%25,0001,000,000
기존6,0006%30,00010,800,000
합계10,00012,700,000

기존 유저가 매출 대부분을 짊어진다는 게 표에서 바로 보인다.

파이썬으로는 어떻게 짰나?

유형별 가정을 딕셔너리로 두고 곱해 더하는 게 골격이었다.

segments = {
    "신규": {"dau": 3000, "pu": 0.02, "arppu": 15000},
    "복귀": {"dau": 1000, "pu": 0.04, "arppu": 25000},
    "기존": {"dau": 6000, "pu": 0.06, "arppu": 30000},
}
def expected_revenue(segs):
    total = 0
    for name, s in segs.items():
        rev = s["dau"] * s["pu"] * s["arppu"]
        print(f"{name}: {rev:,.0f}원")
        total += rev
    return total

여기에 당월 BM 플랜과 스팟형 BM 상품의 예상매출을 얹어 사업PM에게 공유했고, 실제 누적 매출을 겹쳐 그려 월 중반에 갭을 추적했다.

flowchart LR
  classDef p fill:#e8f0fe,stroke:#1a73e8,stroke-width:1.4px,color:#202124
  P["예상선 (모델)"] --- G{"갭 추적"}
  R["실측선 (누적매출)"] --- G
  G -->|"벌어지면"| ACT["어느 변수가 빠졌는지 분해 → BM 액션"]:::p
  class P,R,ACT p

예측이 빗나갈 때 어떻게 대응했나?

시뮬레이션은 맞히려고 만든 게 아니라, 빗나감을 빨리 알아채려고 만든 거였다. 그래서 매달 같은 루틴을 돌렸다.

flowchart TB
  classDef s fill:#e8f0fe,stroke:#1a73e8,stroke-width:1.4px,color:#202124
  A["월초: 예상매출 집계 → 사업PM 공유"]:::s --> B["월 중반: 실제 누적 vs 예상선 갭 확인"]:::s
  B --> C{"갭이 벌어지나?"}
  C -->|"예"| D["DAU·PU%·ARPPU 중 어느 변수인지 분해"]:::s
  D --> E["스팟형 BM 상품·이벤트로 보정"]:::s

핵심은 월말이 아니라 월 중반에 갭을 본 것이다. 그래야 당월 안에 손을 쓸 수 있으니까. 갭이 벌어지면 세 변수 중 어디가 가정과 다른지 분해했고, 부족분은 목표 KPI 기반의 당월 BM 플랜과 스팟형(단발) BM 상품의 예상매출로 메꾸는 방안을 사업PM과 논의했다.

이게 원래 이 시뮬레이션을 만든 이유였다. 예전엔 목표 미달이 확정된 뒤에야 BM 대응이 나가서 늘 한 박자 늦었다. 시뮬레이션은 그 대응을 월초·월중으로 당겨줬다. 예측의 가치는 정확도가 아니라 의사결정을 앞당기는 시간에 있었다.

오늘의 기록

이 세 칸 모델의 진짜 힘은 정확한 예측이 아니라 대응의 속도였다. “왜 미달할 것 같냐”에 “복귀 유저 PU%가 가정보다 낮게 나오고 있어서요”라고 즉답할 수 있으면, 회의는 추궁이 아니라 대응 논의가 된다. 다음 글에선 그 갭을 5분 만에 분해 트리로 파고드는 법을 적어보려 한다.

실제 매출 시뮬레이션 설계 경험을 바탕으로 하되, 모든 수치는 가데이터이고 게임명·내부 구조는 일반화했습니다.