Skip to Content

02. A/B 테스팅 (Experiments)

고급2시간

1. 개요 및 시나리오

상황: 마케팅 팀이 새로운 랜딩 페이지(B안)를 만들었습니다. “기존 페이지(A안)보다 전환율이 2% 올랐어요!”라고 기뻐합니다.

하지만 당신은 침착하게 묻습니다.

“표본 수는 몇 명이었나요? 그 2% 상승이 우연일 확률(P-value)은 얼마인가요?”

A/B 테스트는 비즈니스 의사결정의 꽃입니다. 이번 챕터에서는 **비율 검정(Proportions Z-test)**과 **표본 크기 계산(Power Analysis)**을 배웁니다.


2. 데이터 준비

A/B 테스트 로그 데이터가 없으므로, 기존 데이터에서 성별을 A/B 그룹이라고 가정하고 시뮬레이션해봅니다.

  • Group A: 남성 (Male)
  • Group B: 여성 (Female)
  • Conversion: 구매 여부 (주문 이력이 있으면 1, 없으면 0)
from statsmodels.stats.proportion import proportions_ztest import numpy as np # ... BigQuery client setup

3. 비율 검정 (Proportions Z-test)

전환율(Conversion Rate)과 같은 비율을 비교할 때 사용합니다.

❓ 문제 1: 그룹 간 전환율 비교

Q. 남성과 여성의 구매 전환율(전체 가입자 중 구매자 비율)을 구하고, 두 비율의 차이가 유의미한지 검정하세요.

💡

Hint: COUNT(DISTINCT user_id)로 전체 모수를 구하고, LEFT JOIN orders로 구매자를 셉니다.

정답 코드 보기

# 1. 데이터 집계 query = """ SELECT u.gender, COUNT(DISTINCT u.user_id) as total_users, COUNT(DISTINCT o.user_id) as purchasers FROM `your-project-id.retail_analytics_us.src_users` u LEFT JOIN `your-project-id.retail_analytics_us.src_orders` o ON u.user_id = o.user_id GROUP BY u.gender """ df = client.query(query).to_dataframe().set_index('gender') # 2. 통계량 추출 (성공 횟수, 시행 횟수) count = df['purchasers'].values # [남성구매자수, 여성구매자수] nobs = df['total_users'].values # [남성전체, 여성전체] # 3. Z-test z_stat, p_val = proportions_ztest(count, nobs) print(f"남성 전환율: {count[0]/nobs[0]:.4f}") print(f"여성 전환율: {count[1]/nobs[1]:.4f}") print(f"P-value: {p_val:.4f}") if p_val < 0.05: print("✅ 전환율 차이가 유의미합니다.")
실행 결과
Error: name 'client' is not defined

4. 표본 크기 계산 (Sample Size & Power)

테스트를 하기 전에 가장 먼저 해야 할 질문입니다.

“몇 명한테 실험해야 믿을 만한 결과가 나오나요?”

너무 적으면 효과가 있어도 못 찾고(False Negative), 너무 많으면 돈 낭비입니다.

❓ 문제 2: 필요한 표본 수 계산

Q. 현재 전환율이 10%라고 할 때, 이를 11%로 개선(1%p 상승)하는 것을 감지하려면 그룹당 몇 명이 필요한가요? (유의수준 α=0.05\alpha=0.05, 검정력 Power=0.8 기준)

💡

Hint: statsmodels.stats.power.NormalIndPower를 사용하거나 proportion_effectsize를 구해야 합니다.

정답 코드 보기

import statsmodels.stats.api as sms from statsmodels.stats.proportion import proportion_effectsize # 1. 효과 크기(Effect Size) 계산 p1 = 0.10 # 기존 p2 = 0.11 # 목표 effect_size = proportion_effectsize(p1, p2) # 2. 표본 수 계산 required_n = sms.NormalIndPower().solve_power( effect_size=effect_size, power=0.8, alpha=0.05, ratio=1 ) print(f"필요한 그룹당 표본 크기: {int(np.ceil(required_n))}명") print(f"총 필요 표본 크기: {int(np.ceil(required_n)) * 2}명")
실행 결과
필요한 그룹당 표본 크기: 14745명
총 필요 표본 크기: 29490명

💡 파라미터 설명

  • Alpha (α\alpha): 1종 오류 확률 (보통 0.05). “효과 없는데 있다고 할 확률”
  • Power (1β1-\beta): 검정력 (보통 0.8). “효과가 있을 때 진짜 찾을 확률”
  • Effect Size: 감지하고자 하는 차이의 크기 (클수록 적은 표본으로도 찾음)

5. 실험 설계 시 주의사항 (Common Pitfalls)

코딩만큼 중요한 것이 설계입니다.

  1. Peeking Problem (엿보기):

    • 실험 도중에 “어? P-value 0.04네요, 멈춥시다!”라고 하면 안 됩니다.
    • 사전에 정한 표본 수(N)를 채울 때까지 기다려야 합니다.
  2. SRM (Sample Ratio Mismatch):

    • 50:50으로 나눴는데, 결과가 1000명 vs 950명이다?
    • 트래픽 할당 시스템에 버그가 있거나, 특정 그룹에서 데이터 누락이 발생한 것입니다.
    • 테스트 결과 무효!

💡 요약

  • 비율 검정: 클릭률, 전환율 등 0/1 데이터 비교
  • Power Analysis: 실험 시작 전 필수 단계 (“몇 명 필요해?”)
  • A/B 테스트는 과학입니다: 감(Feeling)이 아니라 데이터로 의사결정하세요.

다음 챕터에서는 상관관계와 회귀분석을 통해 변수 간의 숨은 관계를 찾아봅니다.

Last updated on

🤖AI 모의면접실전처럼 연습하기