Files
ds_new_user_analy/retention_analysis.md
Gnill82 174e41c5b7 리텐션 분석 스크립트 최초 커밋
Add retention analysis configuration file
- Introduced `retention_analysis_config.json` to define settings for retention analysis.
- Configured analysis settings including correlation threshold, top features, and minimum sample size.
- Specified retention groups for analysis.
- Listed columns to be excluded from the analysis.
- Defined key metrics for day 0 analysis.
- Set output preferences for saving results in various formats.
2025-08-30 21:21:35 +09:00

20 KiB
Raw Permalink Blame History

Retention Analysis Script Documentation

개요

retention_analysis.py는 던전 스토커즈 게임의 신규 유저 리텐션 분석을 위한 고도화된 Python 분석 도구입니다. 이 스크립트는 통계적 방법론을 기반으로 신규 유저의 행동 패턴을 심층 분석하여 리텐션에 영향을 미치는 핵심 지표를 식별하고, 특히 D0(첫날) 이탈 문제에 대한 실행 가능한 인사이트를 제공합니다.

프로젝트 배경 및 필요성

현재 던전 스토커즈는 **D0 이탈률이 65.9%**로 매우 높아 서비스 지속성에 심각한 위협이 되고 있습니다. 모바일 게임 업계 평균 D0 이탈률이 25-35%인 점을 고려하면, 이는 즉각적인 개선이 필요한 critical 수준입니다.

이 스크립트는 데이터 기반의 과학적 접근을 통해:

  • 리텐션 영향 요인 정량화: 어떤 지표가 유저 리텐션에 긍정적/부정적 영향을 미치는지 통계적으로 검증
  • 행동 패턴 차이 분석: D0 이탈 유저와 잔존 유저의 게임 내 행동 패턴의 핵심 차이점 파악
  • 개선 우선순위 제시: 게임 디자인 개선을 위한 데이터 기반의 구체적이고 실행 가능한 인사이트 제공
  • 예측 모델 구축: 머신러닝을 활용한 이탈 위험 예측 및 조기 경보 시스템

설치 및 환경 설정

필수 패키지 설치

# 기본 데이터 분석 패키지
pip install pandas numpy scipy matplotlib seaborn

# 머신러닝 패키지
pip install scikit-learn

# 진행률 표시 및 유틸리티
pip install tqdm

# 선택적: 고급 분석을 위한 추가 패키지
pip install plotly jupyter ipywidgets  # 인터랙티브 시각화
pip install statsmodels               # 고급 통계 분석

프로젝트 구조

ds_new_user_analy/
├── retention_analysis.py          # 메인 분석 스크립트 (562 lines)
├── retention_analysis_config.json # 설정 파일 (분석 파라미터 관리)
├── retention_analysis.md          # 이 문서 (사용법 및 이론)
└── analysis_results/              # 분석 결과 저장 디렉토리
    ├── correlation_analysis_YYYYMMDD_HHMMSS.csv     # 상관관계 분석 결과
    ├── d0_churn_analysis_YYYYMMDD_HHMMSS.csv        # D0 이탈 분석 결과
    ├── feature_importance_YYYYMMDD_HHMMSS.csv       # 특성 중요도 분석 결과
    ├── insights_report_YYYYMMDD_HHMMSS.html         # HTML 인사이트 리포트
    └── retention_analysis_YYYYMMDD_HHMMSS.log       # 상세 실행 로그

사용법

기본 실행

# 명령행 인자로 CSV 파일 지정
python retention_analysis.py path/to/your/analysis_data.csv

# 대화형 모드 (파일 경로 입력 프롬프트)
python retention_analysis.py

실행 예시

# 절대 경로 사용 (권장)
python retention_analysis.py "E:\DS_Git\ds_new_user_analy\analysis_results\ds-new_user_analy-20250830_174158.csv"

# 상대 경로 사용
python retention_analysis.py analysis_results/ds-new_user_analy-20250830_174158.csv

입력 데이터 요구사항

스크립트가 정상 작동하기 위해 CSV 파일에 다음 컬럼들이 필수로 포함되어야 합니다:

필수 컬럼:

  • uid: 사용자 고유 식별자
  • retention_status: 리텐션 상태 (Retained_d0, Retained_d1, ..., Retained_d7+)
  • create_time: 사용자 생성 시간 (ISO 8601 형식: 2025-08-13T20:14:43+09:00)

권장 컬럼 (분석 품질 향상):

  • tutorial_complete: 튜토리얼 완료 여부
  • level_up_count: 레벨업 횟수
  • play_time_total: 총 플레이 시간
  • COOP_entry_count, Solo_entry_count: 게임 모드별 진입 횟수
  • death_Monster, death_Trap, death_PK: 사망 원인별 통계
  • item_gain_Equipment, gold_gain_total: 아이템/골드 획득량

데이터 형식 표준:

  • create_time은 ISO 8601 표준 형식을 사용하며 빈 값이 없음을 보장
  • 한국 시간대(+09:00) 정보를 포함하여 정확한 시간대 분석 지원
  • 모든 날짜/시간 계산은 한국 표준시(KST) 기준으로 처리

스크립트 작동 원리 및 아키텍처

전체 워크플로우

flowchart TD
    A[CSV 파일 로드] --> B[데이터 유효성 검사]
    B --> C[분석 기간 정보 추출 ISO8601]
    C --> D[기본 전처리 및 인코딩]
    D --> E[상관관계 분석 Spearman]
    E --> F[D0 이탈자 특성 분석 t-test]
    F --> G[Feature Importance Random Forest]
    G --> H[HTML 인사이트 리포트 생성]
    H --> I[결과 파일 저장 CSV/HTML/LOG]
    
    C --> J[시간대별 가입 패턴 분석]
    C --> K[요일별 가입 패턴 분석]
    J --> H
    K --> H

핵심 클래스: RetentionAnalyzer

class RetentionAnalyzer:
    """
    리텐션 분석의 메인 엔진
    - 통계적 방법론 적용
    - 결과 저장 및 시각화
    - 확장 가능한 분석 프레임워크
    "
    
    # 핵심 메서드들
    def __init__(csv_path, config_path='retention_analysis_config.json')  # 초기화
    def validate_csv()                    # 입력 데이터 검증
    def load_data()                      # 데이터 로드 및 기본 통계
    def extract_analysis_period()        # 분석 기간 및 가입 패턴 추출 (ISO 8601)
    def analyze_correlations()           # Spearman 상관관계 분석
    def analyze_d0_churners()           # D0 이탈자 vs 잔존자 비교 (t-test)
    def feature_importance_analysis()    # Random Forest 중요도 분석
    def generate_insights_report()       # HTML 리포트 생성 (콘솔로그 제외)
    def run_full_analysis()             # 전체 분석 파이프라인 실행

데이터 구조 및 전처리

1. Retention Status 순서형 인코딩:

# 문자열 리텐션 상태를 순서형 수치로 변환
retention_groups = ['Retained_d0', 'Retained_d1', ..., 'Retained_d7+']
df['retention_encoded'] = df['retention_status'].map(
    {status: i for i, status in enumerate(retention_groups)}
)
# 결과: Retained_d0=0, Retained_d1=1, ..., Retained_d7+=7

이 인코딩을 통해 리텐션 단계 간의 순서 관계를 보존하면서 수치 분석이 가능해집니다.

2. 분석 기간 정보 추출 (create_time 기반):

# ISO 8601 형식 시간 데이터 처리
create_times = pd.to_datetime(df['create_time'], format='ISO8601')

# 한국 시간대 기준 분석
korea_dates = create_times.dt.tz_convert('Asia/Seoul').dt.date
korea_hours = create_times.dt.tz_convert('Asia/Seoul').dt.hour
korea_weekdays = create_times.dt.tz_convert('Asia/Seoul').dt.dayofweek

# 가입 패턴 분석
daily_signups = korea_dates.value_counts().sort_index()     # 일별 가입자
hourly_signups = korea_hours.value_counts().sort_index()    # 시간대별 가입자
weekday_signups = korea_weekdays.value_counts().sort_index() # 요일별 가입자

3. 결측값 처리 전략:

  • 상관관계 분석: 각 지표별로 pairwise deletion (해당 지표만 결측값 제거)
  • Feature Importance: Zero imputation (게임 내 활동 없음으로 해석)
  • 그룹 비교: Complete case analysis (양쪽 그룹 모두 유효한 값만 사용)
  • 시간 데이터: ISO 8601 표준으로 완전한 데이터 보장

통계적 분석 방법론

1. 상관관계 분석 (Spearman Rank Correlation)

목적: 각 게임 내 지표와 리텐션 단계 간의 단조 관계를 정량화

왜 Spearman을 선택했는가?

  • retention_status가 순서형 변수 (d0 < d1 < d2 < ... < d7+)
  • 비모수적 방법으로 분포 가정이 불필요
  • 이상치에 덜 민감
  • 비선형 단조 관계도 감지 가능

수학적 배경: Spearman 상관계수 ρ는 다음과 같이 계산됩니다:

ρ = 1 - (6 × Σd²) / (n × (n² - 1))

여기서:

  • d: 각 관측값의 두 변수 순위 차이
  • n: 샘플 크기

코드 구현:

from scipy.stats import spearmanr

for col in numeric_columns:
    # 결측값 제거
    valid_data = df[[col, 'retention_encoded']].dropna()
    
    # 최소 샘플 크기 확인 (기본값: 10)
    if len(valid_data) >= min_sample_size:
        corr, p_value = spearmanr(
            valid_data[col], 
            valid_data['retention_encoded']
        )
        
        # 통계적 유의성 검정 (α = 0.05)
        is_significant = p_value < 0.05

결과 해석:

  • ρ > 0: 해당 지표 값이 높을수록 더 오래 게임 플레이 (긍정적)
  • ρ < 0: 해당 지표 값이 높을수록 빨리 이탈 (부정적)
  • |ρ| > 0.3: 중간 정도의 관계
  • |ρ| > 0.5: 강한 관계

2. 그룹 비교 분석 (Welch's t-test)

목적: D0 이탈 그룹과 잔존 그룹 간의 평균 차이를 통계적으로 검정

Welch's t-test를 선택한 이유:

  • 등분산성 가정이 불필요 (두 그룹의 분산이 달라도 됨)
  • 샘플 크기가 달라도 안정적
  • 게임 데이터에서 흔히 발생하는 이분산성 문제 해결

통계적 가설:

  • H₀(귀무가설): μ₁ = μ₂ (두 그룹의 평균이 같다)
  • H₁(대립가설): μ₁ ≠ μ₂ (두 그룹의 평균이 다르다)

코드 구현:

from scipy import stats

# D0 이탈자와 잔존자 데이터 분리
d0_users = df[df['retention_status'] == 'Retained_d0']
retained_users = df[df['retention_status'] != 'Retained_d0']

for metric in key_metrics:
    d0_data = d0_users[metric].dropna()
    retained_data = retained_users[metric].dropna()
    
    # Welch's t-test 수행
    t_stat, p_value = stats.ttest_ind(
        d0_data, 
        retained_data, 
        equal_var=False  # 등분산 가정 안 함
    )
    
    # 실용적 차이 계산 (효과 크기)
    d0_mean = d0_data.mean()
    retained_mean = retained_data.mean()
    diff_percentage = ((retained_mean - d0_mean) / (d0_mean + 0.0001)) * 100

결과 해석:

  • p-value < 0.05: 통계적으로 유의한 차이 존재
  • 차이율 100% 이상: 잔존자가 이탈자보다 2배 이상 높은 지표
  • Cohen's d 효과 크기: |d| > 0.8 (큰 효과), 0.5-0.8 (중간), 0.2-0.5 (작은 효과)

3. 특성 중요도 분석 (Random Forest)

목적: 다변량 환경에서 리텐션 예측에 가장 중요한 변수들을 식별

Random Forest의 장점:

  • 비선형 관계 포착: 복잡한 게임 내 상호작용 모델링
  • 변수 간 상호작용: A와 B의 조합 효과 자동 탐지
  • 과적합 방지: 배깅과 랜덤 서브스페이스 기법 사용
  • 안정성: 아웃라이어에 견고함
  • 해석 가능성: 각 변수의 기여도 정량화

중요도 계산 원리: 각 변수의 중요도는 해당 변수가 모든 트리에서 불순도 감소에 기여한 평균값입니다:

Importance(v) = (1/T) × Σ[t=1 to T] Σ[s∈Splits(v,t)] p(s) × ΔI(s)

여기서:

  • T: 트리 개수
  • p(s): 분할 s에 도달하는 샘플 비율
  • ΔI(s): 분할 s에서의 불순도 감소량

코드 구현:

from sklearn.ensemble import RandomForestClassifier

# 데이터 준비
X = df[feature_columns].fillna(0)  # Zero imputation
y = df['retention_encoded']        # 타겟 변수

# Random Forest 모델 설정
rf = RandomForestClassifier(
    n_estimators=100,    # 트리 개수 (안정성과 성능 균형)
    random_state=42,     # 재현 가능성
    n_jobs=-1,           # 병렬 처리
    max_depth=None,      # 트리 깊이 제한 없음 (자연스러운 중단)
    min_samples_split=2, # 최소 분할 샘플 수
    min_samples_leaf=1   # 최소 리프 샘플 수
)

# 모델 학습
rf.fit(X, y)

# 중요도 추출
importance_scores = rf.feature_importances_

결과 해석:

  • 0.1 이상: 매우 중요한 변수 (핵심 개선 타겟)
  • 0.05-0.1: 중요한 변수 (보조 개선 요소)
  • 0.01-0.05: 보통 중요 (모니터링 지표)
  • 0.01 미만: 낮은 중요도 (우선순위 후순위)

고급 분석 기법 및 확장

1. 통계적 검증 강화

다중 비교 문제 해결:

from statsmodels.stats.multitest import multipletests

# Bonferroni 또는 FDR 보정 적용
p_values = [result['p_value'] for result in analysis_results]
rejected, p_corrected, _, _ = multipletests(p_values, method='fdr_bh')

효과 크기 계산:

# Cohen's d 계산
def cohens_d(group1, group2):
    pooled_std = np.sqrt(((len(group1) - 1) * group1.var() + 
                         (len(group2) - 1) * group2.var()) / 
                        (len(group1) + len(group2) - 2))
    return (group1.mean() - group2.mean()) / pooled_std

2. 심층 세그멘테이션 분석

클러스터링 기반 유저 타입 분류:

from sklearn.cluster import KMeans
from sklearn.preprocessing import StandardScaler

# 특성 정규화
scaler = StandardScaler()
scaled_features = scaler.fit_transform(df[numeric_columns])

# K-means 클러스터링
kmeans = KMeans(n_clusters=5, random_state=42)
df['user_segment'] = kmeans.fit_predict(scaled_features)

# 세그먼트별 리텐션 패턴 분석
segment_retention = df.groupby(['user_segment', 'retention_status']).size()

3. 시계열 분석 및 트렌드

일별/주별 리텐션 트렌드:

# 코호트 분석
df['signup_date'] = pd.to_datetime(df['signup_date'])
df['cohort'] = df['signup_date'].dt.to_period('W')  # 주간 코호트

cohort_retention = df.groupby('cohort')['retention_encoded'].describe()

설정 파일 상세 설명

retention_analysis_config.json

{
    "analysis_settings": {
        "correlation_threshold": 0.05,      // 통계적 유의수준 (Type I 오류율)
        "top_n_features": 20,               // 결과 표시할 상위 중요 변수 개수
        "min_sample_size": 10,              // 분석 최소 샘플 크기 (신뢰성 확보)
        "effect_size_threshold": 0.1        // 실용적 유의성 최소 효과 크기
    },
    
    "retention_groups": [                   // 리텐션 단계 정의 및 순서
        "Retained_d0", "Retained_d1", "Retained_d2", "Retained_d3",
        "Retained_d4", "Retained_d5", "Retained_d6", "Retained_d7+"
    ],
    
    "exclude_columns": [                    // 분석에서 제외할 메타데이터 컬럼
        "uid", "retention_status", "retention_encoded", 
        "country", "nickname", "auth_id", "create_time"
    ],
    
    "key_metrics_for_d0_analysis": [        // D0 분석 핵심 지표 (도메인 지식 기반)
        "tutorial_complete",                // 온보딩 완료도
        "level_up_count",                  // 성장 경험
        "play_time_total",                 // 참여도
        "COOP_entry_count", "Solo_entry_count",  // 게임 모드 선호
        "death_Monster", "death_Trap", "death_PK",  // 실패 경험
        "item_gain_Equipment", "gold_gain_total"    // 보상 경험
    ],
    
    "output_settings": {
        "save_csv": true,                   // 원시 데이터 CSV 저장
        "save_html": true,                  // HTML 리포트 저장 (기본 출력)
        "save_console_log": true,           // 디버깅용 로그 저장
        "timestamp_format": "%Y%m%d_%H%M%S" // 파일명 타임스탬프 형식
    }
}

출력 결과 해석 가이드

상관관계 분석 결과

긍정적 상관관계 (양의 값) 해석:

shop_sell_count: 0.428 (p < 0.001)

→ 아이템 판매 활동이 활발한 유저일수록 더 오래 게임을 플레이하는 경향 → 액션 아이템: 거래 시스템 개선, 마켓플레이스 UX 향상

부정적 상관관계 (음의 값) 해석:

dungeon_first_result: -0.173 (p < 0.01)  

→ 첫 던전에서 실패한 유저일수록 빨리 이탈하는 경향
액션 아이템: 초심자 던전 난이도 조정, 실패 시 보상 시스템

Feature Importance 결과

중요도 점수별 액션:

  • 0.1 이상 (매우 중요): 즉시 개선 프로젝트 착수
  • 0.05-0.1 (중요): 다음 분기 개선 계획에 포함
  • 0.01-0.05 (보통): 정기 모니터링 대상
  • 0.01 미만 (낮음): 우선순위 후순위

D0 분석 결과

차이율별 해석 및 액션:

tutorial_complete: 
  - D0 평균: 0.23, 잔존 평균: 0.89, 차이: 287%

→ 튜토리얼 완료가 리텐션에 결정적 영향
즉시 액션: 튜토리얼 완료율 개선 프로젝트

가입 패턴 분석 결과

시간대별 분석:

가입 집중 시간: 20시 (1,250명)

→ 저녁 시간대에 가입이 집중됨을 의미 → 마케팅 액션: 해당 시간대 타겟팅 광고 집중

요일별 분석:

가입 집중 요일: 토요일 (3,200명)

→ 주말에 신규 가입이 활발함 → 운영 액션: 주말 이벤트 및 서버 안정성 강화

문제 해결 및 최적화

일반적인 오류와 해결책

1. 메모리 부족 오류

# 청크 단위 처리
chunk_size = 50000
for chunk in pd.read_csv(filepath, chunksize=chunk_size):
    process_chunk(chunk)

2. 인코딩 오류

# UTF-8 인코딩 명시적 지정
df = pd.read_csv(filepath, encoding='utf-8-sig')

3. 성능 최적화

# 데이터 타입 최적화
df['user_level'] = df['user_level'].astype('int16')  # 메모리 절약
df['is_premium'] = df['is_premium'].astype('bool')   # 불린 최적화

대용량 데이터 처리

샘플링 전략:

# 층화 샘플링 (각 리텐션 그룹에서 동일 비율 추출)
from sklearn.model_selection import train_test_split

sampled_data, _ = train_test_split(
    df, 
    test_size=0.7,  # 30%만 사용
    stratify=df['retention_status'],  # 층화
    random_state=42
)

비즈니스 임팩트 및 ROI

개선 우선순위 매트릭스

               높은 임팩트     낮은 임팩트
높은 구현비용    [계획 검토]     [보류]
낮은 구현비용    [즉시 실행]     [빠른 승리]

A/B 테스트 설계

분석 결과를 바탕으로 한 개선안은 반드시 A/B 테스트를 통해 검증:

# 실험 설계 예시
control_group = new_users.sample(frac=0.5, random_state=42)
treatment_group = new_users.drop(control_group.index)

# 개선 효과 측정
improvement = (treatment_retention - control_retention) / control_retention
statistical_power = calculate_power(effect_size, alpha=0.05, sample_size=len(control_group))

결론 및 향후 개선

retention_analysis.py 스크립트는 단순한 데이터 분석을 넘어서, 게임 서비스 개선을 위한 의사결정 지원 시스템의 역할을 합니다.

핵심 가치:

  1. 과학적 접근: 통계적으로 검증된 방법론으로 신뢰할 수 있는 인사이트 제공
  2. 실행 가능성: 분석 결과가 구체적인 개선 액션으로 연결
  3. 확장성: 새로운 분석 기법과 지표를 쉽게 추가 가능
  4. 자동화: 정기적인 분석과 모니터링을 통한 지속적 개선
  5. 시간대 인사이트: 가입 패턴 분석으로 마케팅/운영 최적화 지원

2024년 8월 업데이트 내용:

  • HTML 리포트: 마크다운에서 전문적인 HTML 형식으로 변경
  • 분석 기간 정보: ISO 8601 형식 create_time 기반 자동 추출
  • 시간대 분석: 한국 시간 기준 시간대별/요일별 가입 패턴 분석
  • 콘솔로그 분리: HTML 리포트에서 콘솔로그 제거, 상세 분석 데이터 중심으로 개편
  • 데이터 품질 강화: 표준 시간 형식 지원으로 분석 정확도 향상

향후 발전 방향:

  • 실시간 대시보드 연동 (가입 패턴 실시간 모니터링)
  • 예측 모델 고도화 (딥러닝 활용)
  • 개인화된 리텐션 전략 추천 (시간대별 타겟팅)
  • 자동화된 A/B 테스트 파이프라인
  • 가입 패턴 기반 마케팅 최적화 시스템

정기적인 분석을 통해 게임 개선 효과를 측정하고, 새로운 문제점을 조기에 발견하여 서비스의 지속 가능한 성장에 기여할 수 있습니다.