Python으로 A/B 테스트 분석하기: t-검정부터 베이지안 추론까지 통계적 유의성 검증 완벽 가이드

A/B 테스트란 무엇인가?

A/B 테스트는 두 가지 버전(A와 B)을 비교하여 어느 것이 더 나은 성과를 내는지 통계적으로 검증하는 실험 방법입니다. 웹사이트 디자인, 마케팅 캠페인, 제품 기능 등 다양한 분야에서 활용되며, 데이터 기반 의사결정의 핵심 도구입니다.

A/B 테스트의 핵심은 ‘우연히 발생한 차이’와 ‘실제 효과로 인한 차이’를 구분하는 것입니다.

t-검정을 활용한 기본 분석

t-검정이란?

t-검정은 두 그룹의 평균이 통계적으로 유의미하게 다른지 검증하는 방법입니다. A/B 테스트에서 가장 널리 사용되는 기법으로, 구현이 간단하고 해석이 직관적입니다.

import numpy as np
from scipy import stats

# A그룹과 B그룹의 전환율 데이터
group_a = np.random.binomial(1, 0.10, 1000)  # 전환율 10%
group_b = np.random.binomial(1, 0.12, 1000)  # 전환율 12%

# 독립 표본 t-검정 수행
t_stat, p_value = stats.ttest_ind(group_a, group_b)

print(f"t-통계량: {t_stat:.4f}")
print(f"p-value: {p_value:.4f}")

if p_value < 0.05:
    print("통계적으로 유의미한 차이가 있습니다.")
else:
    print("통계적으로 유의미한 차이가 없습니다.")

t-검정의 가정과 한계

가정 설명 위반 시 대응
정규성 데이터가 정규분포를 따름 샘플 크기가 크면(n>30) 중심극한정리로 완화
등분산성 두 그룹의 분산이 유사 Welch’s t-test 사용
독립성 관측값이 서로 독립적 실험 설계 단계에서 보장 필요

비율 검정: 전환율 비교의 정석

전환율이나 클릭률 같은 이진 데이터를 비교할 때는 비율 검정(proportion test)이 더 적합합니다.

from statsmodels.stats.proportion import proportions_ztest

# 각 그룹의 전환 수와 총 방문자 수
conversions = np.array([120, 145])  # A그룹 120명, B그룹 145명 전환
visitors = np.array([1000, 1000])   # 각 그룹 1000명씩

# z-검정 수행
z_stat, p_value = proportions_ztest(conversions, visitors)

conversion_rate_a = conversions[0] / visitors[0]
conversion_rate_b = conversions[1] / visitors[1]

print(f"A그룹 전환율: {conversion_rate_a:.2%}")
print(f"B그룹 전환율: {conversion_rate_b:.2%}")
print(f"p-value: {p_value:.4f}")

베이지안 추론: 확률적 관점에서의 접근

빈도주의 vs 베이지안 접근법

구분 빈도주의(t-검정) 베이지안
질문 “차이가 0이 아닐 확률은?” “B가 A보다 나을 확률은?”
결과 p-value, 유의성 여부 사후 확률 분포
해석 간접적, 이진 판단 직관적, 연속적 신뢰도
사전지식 사용 안 함 사전 분포로 반영 가능

PyMC를 활용한 베이지안 A/B 테스트

import pymc as pm
import arviz as az

# 관측 데이터
visitors_a, conversions_a = 1000, 120
visitors_b, conversions_b = 1000, 145

with pm.Model() as model:
    # 사전 분포: 전환율에 대한 믿음 (균등 분포)
    p_a = pm.Beta('p_a', alpha=1, beta=1)
    p_b = pm.Beta('p_b', alpha=1, beta=1)

    # 우도: 관측 데이터
    obs_a = pm.Binomial('obs_a', n=visitors_a, p=p_a, observed=conversions_a)
    obs_b = pm.Binomial('obs_b', n=visitors_b, p=p_b, observed=conversions_b)

    # 차이 계산
    delta = pm.Deterministic('delta', p_b - p_a)

    # MCMC 샘플링
    trace = pm.sample(2000, return_inferencedata=True)

# B가 A보다 나을 확률
prob_b_better = (trace.posterior['delta'] > 0).values.mean()
print(f"B가 A보다 나을 확률: {prob_b_better:.2%}")

베이지안 접근법은 “B가 A보다 나을 확률이 95%”처럼 비즈니스 의사결정에 직접 활용 가능한 결과를 제공합니다.

실무 적용 시 체크리스트

1. 샘플 크기 계산

실험 전에 필요한 샘플 크기를 미리 계산하여 충분한 데이터를 수집해야 합니다.

from statsmodels.stats.power import zt_ind_solve_power

# 검출하고 싶은 최소 효과 크기 (전환율 차이)
effect_size = 0.02  # 2%p 차이
baseline_rate = 0.10

# 필요한 샘플 크기 계산
required_n = zt_ind_solve_power(
    effect_size=effect_size,
    alpha=0.05,      # 유의수준
    power=0.8,       # 검정력
    alternative='two-sided'
)

print(f"그룹당 필요한 샘플 크기: {int(required_n)}")

2. 다중 검정 문제

여러 메트릭을 동시에 검정하면 위양성 오류가 증가합니다. Bonferroni 보정 등으로 유의수준을 조정해야 합니다.

  • 단일 메트릭: α = 0.05
  • 5개 메트릭 동시 검정: α = 0.05 / 5 = 0.01

3. 조기 종료의 위험

실험 중간에 결과를 확인하고 조기 종료하면 통계적 오류가 발생할 수 있습니다. Sequential testing 기법을 활용하거나, 사전에 정한 샘플 크기까지 실험을 진행해야 합니다.

도구 비교: 어떤 방법을 선택할까?

상황 추천 방법 이유
빠른 의사결정 필요 t-검정, 비율검정 계산 빠르고 해석 간단
샘플 크기가 작음 베이지안 사전 정보 활용 가능
확률적 해석 필요 베이지안 “90% 확률로 개선” 같은 직관적 해석
전환율/클릭률 비교 비율검정 (z-test) 이진 데이터에 최적화
연속형 지표 (평균 체류시간 등) t-검정 정규 분포 가정에 적합

마무리

A/B 테스트의 핵심은 올바른 통계 기법 선택충분한 데이터 수집입니다.

  • t-검정과 비율검정은 구현이 간단하고 빠르지만, 이진적 판단만 제공합니다.
  • 베이지안 추론은 직관적인 확률 해석을 제공하며, 사전 지식을 활용할 수 있습니다.
  • 실무에서는 샘플 크기 계산, 다중 검정 보정, 조기 종료 방지를 반드시 고려해야 합니다.

Python의 scipy, statsmodels, pymc 라이브러리를 활용하면 이 모든 분석을 효율적으로 수행할 수 있습니다. 데이터 기반 의사결정의 첫걸음, A/B 테스트를 지금 바로 시작해보세요!

이 글이 도움이 되셨나요? ☕

Buy me a coffee

코멘트

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다

TODAY 19 | TOTAL 19