6 분 소요

1. AI 코멘트가 풀려는 문제

대시보드에 숫자만 보여주면 사용자가 직접 해석해야 합니다. “긍정률 87%”는 좋은 건가? 평소보다 떨어진 건가? 이 게임의 특정 코호트는 다른가? — 이런 질문에 답을 자동으로 짚어주는 게 AI 코멘트의 목표입니다.

2. 설계 원칙 — “분석은 코드, 표현은 AI”

핵심 결정: Gemini에게 분석을 시키지 않습니다. 분석은 모두 Python + BigQuery로 수행하고, Gemini는 결과 dict를 받아 자연어로 변환만 합니다.

이유:

  • 환각 방지 — Gemini가 숫자를 만들거나 추세를 발명하면 신뢰 무너짐
  • 일관성 — 같은 데이터면 항상 같은 분석 결과 (LLM 비결정성 회피)
  • 비용 — 통계 계산은 BQ가 압도적으로 저렴

3. 3섹션 9항목 구조

설계 단계에서 인사이트를 (현황·구조·이벤트) 관점으로 분리했습니다.

섹션 ① 감성·키워드 요약 (현황)

현재 이 게임을 유저들이 어떻게 평가하나?

항목 무엇을 보나
1. Top 긍정/부정 카테고리 점유율 인용 (“부정 의견 중 80%가 반복성”)
2. TF-IDF 차별화 키워드 전체 게임 + 같은 장르 두 코퍼스 대비 이 게임만의 키워드
3. 긍정률 4주 추세 최근주 vs 직전 3주 평균

섹션 ② 유저 세그먼트 시그널 (구조)

어떤 유저층이 만족/불만인가?

항목 무엇을 보나
4. 플레이타임 코호트 0-10h / 10-50h / 50h+ 추천률 — 진입장벽·이탈
5. 언어별 추천률 갭 Top 5 언어, 최고-최저 차 — 현지화 시그널

섹션 ③ 변화 알림 (이벤트)

최근 무슨 일이 있었나?

항목 무엇을 보나
6. 패치 임팩트 최근 뉴스 ±7일 추천률·동접 변화
7. 세일 효과 최근 할인 윈도 동안 동접 변화
8. 부정 키워드 급증 최근 1주 vs 직전 4주 평균
9. 동접 z-score 이상치 |z|≥2 일자에 뉴스/세일 cross-ref

4. 통계적 유의성 — 단순 % 비교의 함정 회피

사례로 보는 차이

게임 A에서 60% 할인 진행. 직전 7일 대비 세일 기간 동접 +22.1% 증가.

  • 단순 % 임계값 (예: ±15%): “효과 있음” 판정 → “ROI 검증된 가격 정책” 멘트 생성
  • baseline z-score: 이 게임의 비-세일 일별 동접 변동성을 baseline으로 두면 σ=7,103. 세일 기간 평균 - baseline 평균을 σ로 나눈 z = +0.37 → 평소 변동 범위 안 → “세일 효과로 단정하긴 어려움”

같은 +22.1%지만 게임의 자체 변동성에 따라 의미가 완전히 다릅니다. 안정적인 게임의 +22%는 큰 신호고, 평소부터 들쭉날쭉한 게임의 +22%는 일상 변동.

적용한 통계 방법

항목 방법
추천률 변화 (패치 임팩트) 두 비율 z-test (pooled SE) — 표본이 작으면 SE가 커져 자동으로 z 작아짐
동접 변화 (패치/세일) Baseline z-score — 이벤트 ±7일 제외한 60일 일별 평균 분포 기준
동접 이상치 (단발) Baseline z-score, |z|≥2

5단계 카테고리화로 일관된 라벨링:

뚜렷한_증가 (z≥2) / 약한_증가 (1≤z<2) / 평소_변동_범위 / 약한_감소 / 뚜렷한_감소
뚜렷한_상승 / 약한_상승 / 유의미한_변화_없음 / 약한_하락 / 뚜렷한_하락
def _two_proportion_z(pos1, n1, pos2, n2):
    p1, p2 = pos1/n1, pos2/n2
    p_pool = (pos1 + pos2) / (n1 + n2)
    se = sqrt(p_pool * (1 - p_pool) * (1/n1 + 1/n2))
    return (p2 - p1) / se if se else None

def _categorize_z(z, labels):
    if z is None: return None
    if z >= 2:  return labels[0]
    if z >= 1:  return labels[1]
    if z > -1:  return labels[2]
    if z > -2:  return labels[3]
    return labels[4]

5. TF-IDF 차별화 키워드 — 전체 vs 같은 장르

키워드 빈도 TOP 5만 보면 모든 게임이 비슷한 단어(“재미”, “그래픽”)만 나옵니다. 이 게임만 유난히 자주 나오는 단어를 찾으려면 다른 게임 대비 비교가 필요합니다.

TF  = keyword_analysis.ratio (이 게임 리뷰에서의 비중)
IDF = ln(코퍼스 게임수 / 해당 키워드 등장 게임수)
TF-IDF = TF × IDF

추가로 같은 장르 코퍼스 비교를 따로 합니다. 정의: genres 필드의 첫 2 토큰 일치.

  • 예: “Action, Adventure, Free To Play” 게임은 “Action, Adventure”로 시작하는 모든 게임과 비교
  • 같은 장르 게임 < 10개면 장르 비교 생략 (IDF 안정성)

결과로 두 관점이 같이 나옵니다:

  • 전체 게임 대비: 이 게임의 마케팅 메시지 후보
  • 같은 장르 대비: 동종 경쟁 게임 대비 차별점

6. Gemini 프롬프트 설계 — 액션 시그널 패턴

3개 섹션 각각 전용 프롬프트(SECTION1_PROMPT / SECTION2_PROMPT / SECTION3_PROMPT).

출력 패턴 강제 — “구체 숫자 → 통계 결론 → 따라서 ~”

특히 섹션 ③(변화 알림)은 강한 가이드를 줘서 출력이 일관되도록 유도:

- 항상 절대 수치(delta_pp / delta_pct)를 먼저 짚고
- 그 다음 "통계적 검정 결과 유의미한/유의미하지 않은 변화로 나왔습니다" 식으로 결론 평이하게
- 마지막에 "따라서 ~" 형태로 액션 시그널 마무리

예) "추천률이 12.9%p 상승했고 통계적 검정 결과 유의미한 변화로 나왔습니다.
     따라서 패치 방향성이 호평받았다고 볼 수 있습니다"

표현 화이트/블랙리스트

허용:  "통계적 검정 결과", "통계적으로 의미있는/유의미한 변화",
       "평소 변동 범위 안", "약한 증가/감소", "뚜렷한 증가/감소"

금지:  "z-score", "표준편차", "p-value", "신뢰구간", "분산", "ROI"

일반인이 읽기 어려운 raw 통계 용어는 차단하되, “통계적으로 유의미한”처럼 일반화된 표현은 허용. 결과적으로 보고서스러운 톤은 빠지고 마케팅 코멘트 톤이 살아납니다.

결측 처리 — 메타 코멘트 금지

데이터 없는 항목은 통째로 언급 금지:

추세가 None이면 추세에 관한 어떤 문장도 쓰지 마.
"데이터가 부족하다" / "확인되지 않습니다" / "파악하기 어렵습니다" 같은
메타 코멘트도 절대 금지. 추세는 통째로 없는 항목으로 간주.

이 룰 없으면 Gemini가 “데이터가 부족해서 알기 어렵네요” 같은 잡음을 자주 끼워넣습니다.


7. 실제 출력 예시 — Dead by Daylight (app_id 381210)

최근 5월 5일 "9.6.1 | Bugfix Patch" 업데이트 이후 추천률은 3.6%p 하락했지만,
패치 직후라 표본이 적어 통계적으로 의미 있는 변화로 보긴 어렵습니다.
동접도 7.5% 줄었지만 이 역시 평소 변동 범위 안이라 패치 영향으로
단정하기는 어렵습니다.

한편, 4월 24일부터 5월 6일까지 진행된 60% 할인 세일 기간 동안
동접이 직전 7일 대비 22.1% 증가했지만, 통계적으로는 평소 변동 범위 안이라
세일 효과로 단정하기 어렵고 다른 요인도 함께 살펴봐야 할 것 같습니다.

5월 1일부터 3일까지는 동접이 평소보다 많이 높게 나타났는데, 이는
해당 기간 동안 진행된 60% 할인과 'Play While You Wait: Now available in 1v4!'
및 'What's new in 2V8?' 같은 뉴스 콘텐츠가 동반된 영향으로 보입니다.

3가지 모두 단순 % 비교라면 “효과 있음”으로 잡힐 수치(-3.6pp, -7.5%, +22.1%)이지만, 통계적으론 평소 변동 범위라 신중한 결론을 냅니다.


8. UX — 단일 트리거 + 병렬 실행

단일 트리거

🤖 popover 제목 옆에 “▶ 분석 실행” 버튼 하나. 클릭하면 3 섹션 모두 실행됩니다. 항목별 버튼 분리는 UX 복잡도만 늘림.

병렬 실행

from concurrent.futures import ThreadPoolExecutor

with st.spinner("3개 섹션 동시 분석 중..."):
    with ThreadPoolExecutor(max_workers=3) as ex:
        f1 = ex.submit(ai_comment_sentiment, app_id)
        f2 = ex.submit(ai_comment_segment, app_id)
        f3 = ex.submit(ai_comment_events, app_id)
        # 3 Gemini 호출이 동시에 진행 (직렬 ~15초 → 병렬 ~5-8초)

이중 캐싱

  • @st.cache_data(ttl=3600) — 모든 사용자 공유, 같은 게임 재호출 시 0$
  • st.session_state[f"ai_*_{app_id}"] — popover 닫았다 열어도 결과 유지

가독성 후처리

정규식으로 숫자(94.1%, 12.9%p, 53만 건)와 따옴표 안 한국어 키워드('밸런스', '중국어 간체')를 추출해 골드 색 굵은 글씨로 강조. 긴 문단도 핵심 숫자가 한눈에 들어옵니다.


9. 비용

게임당 분석 1회 = ~$0.001 (BQ 쿼리 ~10회 + Gemini 호출 3회).

항목 게임당
BigQuery 스캔 ~$0.0005
Gemini Flash 입력 (~3k tokens) ~$0.0002
Gemini Flash 출력 (~900 tokens) ~$0.0003
합계 ~$0.001

자연 트래픽 기준 월 $1 미만. 최악 시나리오(누가 매시간 다른 게임 100개씩 누름) ~$0.10/시간.

비용 통제 안전망:

  • GCP Billing Alert (월 $5 임계값) — 이메일 알림
  • Vertex AI Quota cap — 일일 호출 제한
  • 캐시 적중 시 0원

10. 협업 디테일 — Claude Code와 어떻게 만들었나

이 섹션이 본 시리즈의 핵심 차별화 포인트라 협업 흐름을 자세히 남깁니다.

본인이 결정한 것

  • 9개 분석 항목 자체 — 어떤 인사이트가 의사결정에 필요한지 정의
  • 3 섹션 분류 (현황/구조/이벤트) — 마케터가 받아볼 보고서 구조 관점
  • 통계 방식 선택 — 단순 % 임계값에서 z-score baseline으로 전환 결정
  • 임계값 — |z|=2 (95% CI), TF-IDF의 df≥2/count≥3, 코호트 n≥30 등
  • 프롬프트 패턴 — “구체 숫자 → 통계 결론 → 따라서 ~”, 통계 용어 화이트/블랙리스트
  • UX 흐름 — 단일 트리거, 병렬 실행, 이중 캐싱, 숫자/키워드 강조
  • 트레이드오프 — Streamlit 공개 배포 시 비용 vs 접근성, AI hide vs 캐시 모드

Claude Code가 한 것

  • 결정된 SQL/Python을 코드로 옮기는 페어 프로그래밍
  • BQ 쿼리 디버깅 (PARSE_TIMESTAMP 타입 mismatch 같은 것)
  • 정규식 작성 (한글 키워드 매칭)
  • 코드 리뷰 (3개 에이전트 병렬 — 재사용성/품질/효율성)
  • 문서 초안 (PROJECT_PLAN.md 보강, 이 블로그 포스트 시리즈)

그래서 얻은 것

혼자 했다면 한 달 이상 걸렸을 분량을 압축적으로 끝냈습니다. 그 시간을 방법론 자체를 다듬는 데 더 썼습니다. 예를 들어 단순 +15% 임계값으로 1주 운영해보고 “381210 데이터에서 +22%지만 사실 평소 수준”이라는 케이스를 발견 → z-score baseline으로 전환 → 같은 케이스가 z=+0.37로 정확히 잡히는지 검증 → 5단계 카테고리화 일관성 확인. 이런 반복적 개선이 가능했던 게 협업 효과입니다.

도구는 결정을 대신 내려주지 않습니다. 무엇을 만들지 정의하고 그 결과가 만족스러운지 판단하는 건 본인입니다. Claude Code는 그 정의를 빠르게 코드로 옮겨주는 파트너 역할을 했습니다.


11. 마무리 — 시리즈 정리

5개 포스트로 다룬 것을 한 줄씩:

  1. 개요 — 의사결정 보조 데이터 서비스 + Claude Code 협업 방식
  2. 데이터 수집 & GCP — Cloud Scheduler/Functions × 5 + BQ 직접 적재
  3. 데이터 구조 & 분석 — 8 BQ 테이블 + Kiwi 형태소 분석 + 24 카테고리
  4. 대시보드 — 3탭 + anchor 기능 + Streamlit Cloud 배포
  5. AI 코멘트 — 통계 검정 + Gemini 자연어 변환 (이 글)

결과물

다음 확장

  • FastAPI + React로 풀스택 분리
  • 인증 + 게임 개발자용 본인 게임 KPI 대시보드
  • Pre-compute 모드로 AI 코멘트 비용 0화

읽어주셔서 감사합니다.