# Retention Analysis Script Documentation ## 개요 `retention_analysis.py`는 던전 스토커즈 게임의 신규 유저 리텐션 분석을 위한 고도화된 Python 분석 도구입니다. 이 스크립트는 통계적 방법론을 기반으로 신규 유저의 행동 패턴을 심층 분석하여 리텐션에 영향을 미치는 핵심 지표를 식별하고, 특히 D0(첫날) 이탈 문제에 대한 실행 가능한 인사이트를 제공합니다. ## 프로젝트 배경 및 필요성 현재 던전 스토커즈는 **D0 이탈률이 65.9%**로 매우 높아 서비스 지속성에 심각한 위협이 되고 있습니다. 모바일 게임 업계 평균 D0 이탈률이 25-35%인 점을 고려하면, 이는 즉각적인 개선이 필요한 critical 수준입니다. 이 스크립트는 데이터 기반의 과학적 접근을 통해: - **리텐션 영향 요인 정량화**: 어떤 지표가 유저 리텐션에 긍정적/부정적 영향을 미치는지 통계적으로 검증 - **행동 패턴 차이 분석**: D0 이탈 유저와 잔존 유저의 게임 내 행동 패턴의 핵심 차이점 파악 - **개선 우선순위 제시**: 게임 디자인 개선을 위한 데이터 기반의 구체적이고 실행 가능한 인사이트 제공 - **예측 모델 구축**: 머신러닝을 활용한 이탈 위험 예측 및 조기 경보 시스템 ## 설치 및 환경 설정 ### 필수 패키지 설치 ```bash # 기본 데이터 분석 패키지 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 # 상세 실행 로그 ``` ## 사용법 ### 기본 실행 ```bash # 명령행 인자로 CSV 파일 지정 python retention_analysis.py path/to/your/analysis_data.csv # 대화형 모드 (파일 경로 입력 프롬프트) python retention_analysis.py ``` ### 실행 예시 ```bash # 절대 경로 사용 (권장) 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) 기준으로 처리 ## 스크립트 작동 원리 및 아키텍처 ### 전체 워크플로우 ```mermaid 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 ```python 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 순서형 인코딩:** ```python # 문자열 리텐션 상태를 순서형 수치로 변환 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 기반):** ```python # 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: 샘플 크기 **코드 구현:** ```python 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₁(대립가설): μ₁ ≠ μ₂ (두 그룹의 평균이 다르다) **코드 구현:** ```python 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에서의 불순도 감소량 **코드 구현:** ```python 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. 통계적 검증 강화 **다중 비교 문제 해결:** ```python 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') ``` **효과 크기 계산:** ```python # 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. 심층 세그멘테이션 분석 **클러스터링 기반 유저 타입 분류:** ```python 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. 시계열 분석 및 트렌드 **일별/주별 리텐션 트렌드:** ```python # 코호트 분석 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 ```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. 메모리 부족 오류** ```python # 청크 단위 처리 chunk_size = 50000 for chunk in pd.read_csv(filepath, chunksize=chunk_size): process_chunk(chunk) ``` **2. 인코딩 오류** ```python # UTF-8 인코딩 명시적 지정 df = pd.read_csv(filepath, encoding='utf-8-sig') ``` **3. 성능 최적화** ```python # 데이터 타입 최적화 df['user_level'] = df['user_level'].astype('int16') # 메모리 절약 df['is_premium'] = df['is_premium'].astype('bool') # 불린 최적화 ``` ### 대용량 데이터 처리 **샘플링 전략:** ```python # 층화 샘플링 (각 리텐션 그룹에서 동일 비율 추출) 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 테스트를 통해 검증: ```python # 실험 설계 예시 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 테스트 파이프라인 - 가입 패턴 기반 마케팅 최적화 시스템 정기적인 분석을 통해 게임 개선 효과를 측정하고, 새로운 문제점을 조기에 발견하여 서비스의 지속 가능한 성장에 기여할 수 있습니다.