대조군 하나를 여러 실험이 나눠 써도 될까?
공유 대조군과 실험군 간 비교
대조군 하나를 실험 11개가 나눠 쓰면 트래픽은 아끼지만, 11개의 결과가 서로 묶입니다. 대조군이 우연히 낮게 나온 날에는 11개가 한꺼번에 이긴 것처럼 보이고, 그 결과는 서로 독립이 아닙니다.
들어가며
빌드 하나에 실험 11개를 같이 실었습니다. 각 실험은 한 가지 변경만 담고 있고, 비교 대상은 아무것도 바꾸지 않은 대조군 하나입니다. 대조군을 11개 두면 트래픽이 모자라기 때문입니다.
2주 뒤 보고서가 올라옵니다. 11개 중 6개가 대조군보다 유의하게 좋았습니다.
유의한 여섯 개를 다 채택해도 될까요?
이번 글에서는 대조군을 나눠 쓸 때 결과가 어떻게 묶이는지 세어 봅니다. 그리고 묶인 결과를 풀어 읽는 방법인 실험군 간 비교와 대조군 크기 배분까지 정리하겠습니다.
공유 대조군은 결과를 묶습니다
실험군 11개가 전부 효과 0인 상황을 1만 번 시뮬레이션했습니다. 그룹당 1만 명, 전환율 5%입니다. 한 번은 대조군 하나를 11개가 나눠 쓰고, 다른 한 번은 실험군마다 독립 대조군을 둡니다.
import numpy as np
from scipy.stats import norm
K, N, P, T = 11, 10_000, 0.05, 10_000 # 실험군 11개, 그룹당 1만 명, 전환율 5%, 실험 1만 회
rng = np.random.default_rng(seed=2026)
def p_values(ctrl, arms, n_c, n_a): # 각 실험군을 대조군과 비교한 양측 p값
pc, pa = ctrl / n_c, arms / n_a
pooled = (ctrl[:, None] + arms) / (n_c + n_a)
se = np.sqrt(pooled * (1 - pooled) * (1 / n_c + 1 / n_a))
return 2 * norm.sf(np.abs((pa - pc[:, None]) / se))
arms = rng.binomial(N, P, size=(T, K)) # 실험군 11개, 전부 효과 0
shared = rng.binomial(N, P, size=T) # 공유 대조군 1개
p_shared = p_values(shared, arms, N, N)
indep = rng.binomial(N, P, size=(T, K)) # 실험군마다 독립 대조군
pooled = (indep + arms) / (2 * N)
p_indep = 2 * norm.sf(np.abs((arms / N - indep / N) / np.sqrt(pooled * (1 - pooled) * 2 / N)))
for name, p in (("공유 대조군", p_shared), ("독립 대조군", p_indep)):
cnt = (p < 0.05).sum(axis=1)
print(f"{name}: 하나라도 유의 {(cnt >= 1).mean()*100:.1f}%, 3개 이상 동시 유의 {(cnt >= 3).mean()*100:.1f}%")
# 공유 대조군: 하나라도 유의 29.6%, 3개 이상 동시 유의 5.8%
# 독립 대조군: 하나라도 유의 43.4%, 3개 이상 동시 유의 1.6%
| 효과 0인 실험군 11개, 실험 1만 회 | 공유 대조군 | 독립 대조군 |
|---|---|---|
| 하나라도 유의한 실험 | 29.6% | 43.4% |
| 3개 이상 동시에 유의 | 5.8% | 1.6% |
| 5개 이상 동시에 유의 | 1.5% | 0.0% |
| 11개 전부 같은 방향 | 15.6% | 0.1% |
| 실험군 두 개의 z값 상관 | 0.49 | 0.00 |
그림 1. 대조군을 나눠 쓸 때와 따로 둘 때의 차이. 설명을 위해 만든 가상 실험입니다.
첫 줄만 보면 공유 대조군이 더 안전해 보입니다. 하나라도 유의한 실험이 29.6%로 독립 대조군의 43.4%보다 적습니다. 그런데 나머지 줄은 반대입니다. 3개 이상이 동시에 유의한 실험은 공유 쪽이 3.6배 많고, 11개가 전부 같은 방향으로 움직인 실험은 15.6%로 독립 쪽의 150배입니다.
이유는 대조군이 하나이기 때문입니다. 각 실험군의 결과는 실험군 자신의 변동과 대조군의 변동을 합친 값인데, 대조군 쪽 변동이 11개 실험군에 똑같이 들어갑니다. 그래서 실험군 두 개의 결과 사이에 상관 0.49가 생깁니다. 독립 대조군이면 0입니다.
공유 대조군에서는 실험군 11개의 결과가 독립된 증거 11개가 아니라, 대조군 하나의 변동을 공유하는 증거 11개입니다.
대조군이 우연히 낮으면 전부 이긴 것처럼 보입니다
묶임이 실제로 문제가 되는 순간은 대조군이 우연히 한쪽으로 치우친 날입니다. 1만 번 가운데 대조군 전환율이 하위 2.5%에 든 실험 213건만 따로 보면, 효과가 하나도 없는데도 평균 3.6개 실험군이 대조군보다 유의하게 좋았고, 5%의 실험에서는 11개 중 8개 이상이 유의했습니다.
| 대조군 상태 | 실험 수 | 유의한 실험군 평균 | 8개 이상 유의 |
|---|---|---|---|
| 전체 | 10,000건 | 0.6개 | 0.2% |
| 대조군이 하위 2.5%로 낮게 나온 경우 | 213건 | 3.6개 | 5% |
그림 3. 효과 0인 실험군 11개에서 대조군이 우연히 낮게 나왔을 때. 설명을 위해 만든 가상 실험입니다.
서두에서 예시로 든 보고서가 이런 경우일 수 있습니다. 11개 중 6개 승리는 6개가 각각 좋아서가 아니라 대조군 하나가 그 기간에 낮게 나와서 생긴 결과일 수 있습니다. 대조군 대비 수치만으로는 둘을 구분할 수 없습니다.
여러 실험군이 한꺼번에 이겼다는 보고는 실험군들이 좋아서가 아닌, 대조군이 낮았다는 뜻일 수 있습니다.
다른 실험군과 비교해 가려냅니다
대조군 하나의 변동을 걷어내는 가장 간단한 방법은 같은 대조군을 쓴 다른 실험군들과 비교하는 것입니다. 대조군이 낮아서 전부 이긴 것처럼 보이는 상황이라면 실험군끼리는 차이가 없습니다.
진짜 효과가 있는 실험군이라면 나머지 실험군의 평균보다도 높아야 합니다.
진짜 효과 +10%인 실험군 하나와 효과 0인 실험군 10개를 섞어 1만 번 돌리고, 두 가지 조건을 걸어 봤습니다.
| 조건 | 진짜 효과 실험군이 통과 | 효과 0 실험군이 통과 (실험군당) |
|---|---|---|
| 대조군 대비 유의 | 34.6% | 2.3% |
| 나머지 실험군 평균 대비 유의 | 58.2% | 1.5% |
| 두 조건 모두 | 29.9% | 0.5% |
그림 4. 실험군 간 비교를 추가 조건으로 걸었을 때. 그룹당 1만 명, 기저 전환율 5%, 효과 +10%는 검출력 80% 설계에 못 미치는 인원입니다. 설명을 위해 만든 가상 실험입니다.
두 조건을 모두 요구하면 효과 0인 실험군이 가짜로 통과하는 비율은 2.3%에서 0.5%로 4.6배 줄어듭니다. 진짜 효과 실험군의 통과율은 34.6%에서 29.9%로 조금 줄어듭니다. 가짜 승리를 줄이는 비용으로 진짜 승리를 일부 잃는 교환이고, 실험 11개를 동시에 돌리는 상황에서는 남는 교환입니다.
실험군 간 비교에는 전제가 하나 있습니다. 다른 실험군 대부분이 효과 없다는 가정입니다. 11개가 전부 진짜로 좋은 변경이라면 실험군 평균이 같이 올라가서 진짜 효과를 가립니다. 그래서 실험군 간 비교는 대조군 대비를 대체하는 것이 아니라 뒤에 붙이는 두 번째 관문입니다.
공유 대조군 실험의 채택 조건은 대조군보다 좋고, 다른 실험군보다도 좋을 때입니다.
대조군은 더 크게 잡습니다
대조군이 11번 비교에 쓰이는데 크기는 실험군 하나와 같다면, 대조군의 변동이 11개 비교 전부에 같은 크기로 들어갑니다. 대조군을 키우면 그 변동이 줄어들고, 같은 총 인원으로 검출력이 올라갑니다. 실험군이 k개일 때 대조군을 실험군의 √k배로 두는 것이 알려진 배분입니다[1].
| 배분 (총 120,000명, 실험군 11개) | 대조군 | 실험군당 | +10% 효과의 검출력 |
|---|---|---|---|
| 12등분 | 10,000명 | 10,000명 | 35.4% |
| 대조군을 실험군의 2배로 | 18,462명 | 9,231명 | 41.5% |
| 대조군을 실험군의 √11 ≈ 3.3배로 | 27,799명 | 8,382명 | 42.8% |
그림 5. 같은 총 인원에서 대조군 크기만 바꿨을 때. 기저 전환율 5%, 양측 α = 0.05 기준입니다.
총 인원은 그대로인데 대조군을 키우는 것만으로 검출력이 35.4%에서 42.8%로 올라갑니다. 실험군당 인원은 줄어드는데도 그렇습니다. 대조군의 변동이 모든 비교에 공통으로 들어가기 때문에, 그 변동을 줄이는 투자가 실험군 하나를 키우는 투자보다 효율이 높습니다.
공유 대조군은 비교에 쓰이는 횟수만큼 크게 잡아야 하고, 기준은 실험군 크기의 √k배입니다.
판정 규칙
| 단계 | 할 일 | 이유 |
|---|---|---|
| 설계 | 대조군을 실험군의 √k배로 배분한다 | 공통 변동을 줄인다 |
| 설계 | 실험군마다 주요 지표 하나를 미리 적는다 | 11개 실험군 × 지표 여러 개는 다중 비교가 된다 |
| 판정 | 대조군 대비 유의한 실험군을 고른다 | 첫 번째 관문 |
| 판정 | 그 실험군을 나머지 실험군의 평균과 비교한다 | 대조군 변동을 걷어내는 두 번째 관문 |
| 판정 | 유의한 실험군이 절반을 넘으면 대조군부터 의심한다 | 효과 0에서도 대조군이 낮으면 평균 3.6개가 유의하다 |
| 보고 | 승리한 실험군 수가 아니라 대조군 수치와 실험군 간 차이를 같이 적는다 | 읽는 사람이 묶임을 볼 수 있어야 한다 |
그림 6. 공유 대조군 실험의 설계와 판정 절차.
다섯 번째 줄이 실무에서 가장 자주 빠집니다. 11개 중 6개가 이겼다는 보고가 오면 6개를 축하하기 전에 대조군의 전환율이 평소 수준인지부터 봅니다. 대조군이 최근 4주 평균보다 눈에 띄게 낮다면, 그 6개는 실험군의 성과가 아니라 대조군이 낮게 나온 결과일 가능성이 큽니다[2].
공유 대조군 보고서는 실험군이 몇 개 이겼는지가 아니라, 대조군이 어디에 있었고 실험군들이 서로 얼마나 다른지로 읽습니다.
나가며
- 대조군 하나를 11개 실험군이 나눠 쓰면 결과 사이에 상관 0.49가 생깁니다. 효과가 하나도 없어도 11개가 전부 같은 방향인 실험이 15.6%이고, 독립 대조군이면 0.1%입니다.
- 대조군이 우연히 낮게 나온 날에는 효과 0인 실험군이 평균 3.6개 유의하게 이깁니다. 나머지 실험군의 평균과도 비교하는 조건을 추가하면 가짜 통과율이 2.3%에서 0.5%로 줄어듭니다.
- 같은 총 인원에서 대조군을 실험군의 √k배로 키우면 검출력이 35.4%에서 42.8%로 오릅니다. 공유 대조군은 비교 횟수만큼 커야 합니다.
용어
- 변동(표집 변동, fluctuation): 같은 조건에서 실험을 반복해도 표본마다 우연히 달라지는 값의 흔들림입니다. 통계에서는 표집 변동(sampling variation)이라고 부릅니다. 전환율 5%인 집단에서 1만 명을 뽑아도 매번 5%가 나오지 않고 4.6%에서 5.4% 사이에서 움직이는데, 그 움직임이 변동입니다.
참고
- Dunnett, C. W. (1955). A multiple comparison procedure for comparing several treatments with a control. Journal of the American Statistical Association, 50(272), 1096-1121. https://doi.org/10.1080/01621459.1955.10501294
- Kohavi, R., Tang, D., & Xu, Y. (2020). Trustworthy Online Controlled Experiments: A Practical Guide to A/B Testing. Cambridge University Press.
본문의 모든 수치는 설명을 위해 만든 가상 실험을 직접 시뮬레이션한 값입니다. 검정은 두 비율 z검정(양측, α = 0.05)이고, 실험 1만 회, 시드 2026 기준입니다. 실험군 간 비교는 해당 실험군을 나머지 10개 실험군을 합친 집단과 두 비율 z검정으로 비교했습니다. 검출력은 정규 근사로 계산했습니다. 코드 실행 환경은 Python 3.12, NumPy 2.5.3, SciPy 1.18.1입니다.