A/B 테스트 마스터 노트 시리즈 2편. 좋은 테스트는 좋은 설계에서 시작 — 가설 형식과 귀무가설, 연속형 지표를 이진 지표로 변환하는 기법, 페이지·디바이스 타겟팅, 50/50 vs 10/90 분할 전략, 그리고 No Dead Ends UX 원칙까지 코드와 함께 풀어 갑니다.
이 글은 A/B 테스트 마스터 노트 시리즈의 두 번째 편입니다. 1편(입문)에서 대조군·전환율·유의성을 잡았다면, 이번엔 본격 테스트 설계예요. 막연히 "이걸 바꿔보자"는 접근은 의미 없는 데이터를 만들거나, 실패했을 때 다음 단계를 알 수 없게 만들어요.
이번 편에서 다루는 건 다섯 가지 — 가설 형식·지표 선택·타겟팅·트래픽 분할·No Dead Ends 원칙. 이 다섯 가지가 잡혀야 3편 시스템 구축, 4편 실제 사례에서 코드가 의미를 갖습니다.
처음 테스트 설계가 어렵게 느껴지는 이유
이유는 두 가지예요.
첫째, "무엇을 테스트할지" 정하는 것보다 "어떤 지표로 성공을 판단할지"가 훨씬 어렵습니다. 평균 주문 금액을 지표로 잡으면 한 명의 대형 주문이 데이터를 망가뜨리고, LTV(고객 생애 가치)를 잡으면 측정에 1년이 걸려요. 짧은 기간에 안정적으로 측정 가능한 지표를 고르는 게 거의 모든 설계의 핵심입니다.
둘째, 편향(bias)이 의외의 자리에서 들어옵니다. 모든 페이지에서 실험을 실행하면 의도하지 않은 페이지의 데이터가 섞이고, 데스크톱 전용 기능을 모바일에서도 노출하면 결과가 오염되고, 결과 보고 종료 시점을 정하면 Peeking Problem(조기 종료 문제)이 생겨요.
해결법은 두 가지. 첫째, 모든 지표를 "측정 가능 기간"과 "이상치 안정성" 두 축으로 평가하세요. LTV는 둘 다 떨어지고, "1개 초과 구매 여부" 같은 이진 지표는 둘 다 높습니다. 둘째, 종료 기준을 시작 전에 정하세요. 결과를 보고 결정하는 게 가장 흔한 함정이에요.
가설 — 검증 가능한 질문으로 만들기
A/B 테스트 가설은 다음 형태여야 해요.
만약 [변경 사항]을 하면, [이유] 때문에, [측정 가능한 결과]가 발생할 것이다.
세 부분이 다 있어야 합니다.
나쁜 가설 vs 좋은 가설
나쁨:
- "빨간 버튼이 파란 버튼보다 좋을 것이다." (근거 없음, 지표 없음)
- "홈페이지를 단순하게 만들면 좋아질 것이다." (측정 불가, 모호함)
좋음:
- "장바구니 추가 시 장바구니 슬라이드를 자동으로 열면, 사용자가 결제 버튼을 더 빨리 발견하여 구매 전환율이 증가할 것이다."
- "상품 이미지 아래 재고 부족 메시지를 표시하면, 탐색 단계에서 긴박감이 생겨 클릭률과 구매율이 증가할 것이다."
좋은 가설은 테스트가 실패해도 무엇을 배웠는지 명확해요. "긴박감 + 탐색 단계 노출"이라는 메커니즘이 효과가 없다는 걸 안 거니까, 다음에는 다른 메커니즘을 시도할 수 있습니다.
귀무가설 — 보수적으로 시작
통계적으로 올바른 A/B 테스트는 귀무가설(Null Hypothesis, H₀) 설정에서 출발합니다.
귀무가설 H₀: 새로운 장바구니 UI가 구매 전환율에 영향을 미치지 않는다.
대립가설 H₁: 새로운 장바구니 UI가 구매 전환율을 증가시킨다.
테스트 목표: 통계적 유의성을 통해 H₀를 기각하고 H₁을 채택
핵심은 새 버전이 더 낫다는 걸 스스로 증명해야 한다는 점이에요. 증명되기 전까진 기존 버전을 유지하는 게 안전합니다. 법정 비유로 — 무죄 추정이 기본, 검사가 합리적 의심을 넘는 증거를 제시할 때만 유죄 판결.
지표 선택 — 가장 어려운 결정
좋은 지표의 세 조건
지표는 다음 세 기준을 통과해야 해요.
(1) 가장 짧은 시간 안에 측정 가능
- LTV는 1년 이상 걸려 단기 테스트에 부적합
- "방문 간격 시간"·"주당 방문 횟수"는 단기간에 효과 파악 가능
(2) 비즈니스 목표와 직접 연결
- 이커머스: 구매 전환율, 평균 주문 금액, 재구매율
- 소셜 미디어: 일일 활성 사용자, 콘텐츠 공유 수
- SaaS: 무료 → 유료 전환율, 기능 활성화율
(3) 외부 요인에 쉽게 왜곡되지 않음
- 수익(Revenue) 직접 측정 = 대형 주문 하나가 전체 데이터 왜곡
- "1개 초과 구매 여부" 같은 안정적인 이진 지표 권장
연속형 → 이진 지표 변환 기법
이게 설계의 핵심 기술 중 하나예요. 측정하기 어려운 연속형 지표를 다루기 쉬운 이진 지표로 변환합니다.
문제 상황: 평균 장바구니 크기를 지표로 쓰고 싶지만, 시스템은 사용자 수와 이벤트 완료 수만 추적 가능.
해결: "1개 초과 구매 여부"라는 이진 이벤트 도입.
// 결제 완료 시점에 실행되는 코드
function onOrderSubmit() {
// 기본 구매 이벤트
track('purchase');
// 조건부 지표: 장바구니에 2개 이상 담은 경우만
if (cart.items.length > 1) {
track('More than one item');
}
}
이 방식의 장점:
- 기존 통계 계산 시스템 수정 불필요
- 이상치(Outlier)에 강건 (100개 구매해도 1번만 카운트)
- 어떤 A/B 테스트 플랫폼에서도 그대로 사용 가능
여기서 시험 함정이 하나 있어요. 수익을 직접 지표로 삼으면 한 명의 $5,000 주문이 변형 그룹의 평균 수익을 폭등시킵니다. 그게 "변형이 좋아서"가 아니라 그냥 우연히 그 그룹에 큰 손님이 떨어진 거예요. 이진 변환은 이 함정을 한 번에 해결합니다.
다중 지표 모니터링 — 단일 지표의 함정
일반 교과서는 "하나의 지표만 사용하라"고 권장하지만, 실무에서는 종종 반대로 갑니다. 하나만 보면 다른 핵심 지표가 희생되는 걸 놓쳐요.
실제 발생 가능한 시나리오:
- 목표 지표 "2개 이상 구매 비율": +15% 상승 (성공처럼 보임)
- 부작용 "전체 구매 완료율": -20% 하락 (실제로는 손해)
분석: 모달이 너무 복잡해 오히려 구매 이탈 유발
결론: 절대적 의미에서 테스트 실패
권장: 주요 목표 지표 12개 + 핵심 KPI 감시 지표 23개를 함께 추적.
타겟팅 — 어디서 실험을 실행할 것인가
모든 페이지에서 테스트를 실행할 필요는 없어요. 특정 URL이나 디바이스에서만 활성화하면 노이즈가 줄고 결과가 명확해집니다.
페이지 타겟팅
// 결제 완료 페이지에서만 활성화
const checkoutSuccessTest = {
active: true,
targeting: {
path: {
match: 'checkout\/success' // 정규식 — /는 \/로 이스케이프
}
},
activateOnPageView: true,
variations: {
original: [],
showVoting: [/* 투표 데이터 */]
}
};
// 상품 페이지에서만 갤러리 테스트
const galleryTest = {
targeting: {
path: {
match: /product/ // /product/가 포함된 URL에서만
}
}
};
디바이스 타겟팅
마우스 오버 효과는 데스크톱에서만 작동해요. 화면 너비로 판단하면 함정에 빠집니다.
// 화면 너비 기반 — 부정확
// iPad 가로 모드는 너비가 넓지만 마우스 없음
const isDesktopByWidth = window.innerWidth >= 900;
// User-Agent 기반 — 더 정확
const isDesktop = !window.navigator.userAgent.match(/iPhone|iPad|Android/);
// 실험 설정에 적용
const mouseOverTest = {
targeting: {
path: { match: /category/ }, // 카테고리 페이지
device: isDesktop // 데스크톱만
}
};
여기서 시험 함정이 하나 있어요. iPad 가로 모드는 화면 너비가 1024px이라 데스크톱처럼 보이지만 터치 디바이스라 마우스 호버가 없어요. User-Agent 기반 판별이 더 정확합니다.
수동 활성화 (Manual Activation)
페이지 뷰가 아닌 특정 API 호출 시점이나 사용자 행동 시점에 실험을 활성화하고 싶을 때.
async function getProducts() {
const products = await api.fetchProducts();
// 상품 데이터를 받아온 시점에 실험 활성화
// 페이지가 바뀌어도 일관되게 적용됨
activateExperiment('product_name_test');
const processedProducts = runExperiment('product_name_test', products);
return processedProducts;
}
장점 — 페이지가 바뀔 때마다 재실행되지 않고, 실제로 데이터가 필요한 시점에만 정확히 실행됩니다.
트래픽 분할 전략
50/50 — 가장 일반적
function pickVariation() {
return Math.random() < 0.5 ? 'variation_b' : 'original';
}
새로운 변형의 효과를 빠르게 파악하기 위해 균등 분할.
10/90 — 위험 관리
위험도가 높거나 아직 검증되지 않은 기능은 소수에게만 먼저 노출.
function pickVariation() {
return Math.random() < 0.1 ? 'new_checkout' : 'original';
}
// 점진적 롤아웃: 10% → 25% → 50% → 100%
// 문제 생겨도 90%는 안전
다중 변형(Multivariate)
function pickVariation() {
const r = Math.random();
if (r < 0.33) return 'variation_a';
if (r < 0.66) return 'variation_b';
return 'original';
}
여기서 시험 함정이 하나 있어요. 변형이 많을수록 각 그룹의 사용자 수가 줄어 통계적 유의성에 도달하는 데 더 오래 걸립니다. 3개 변형이면 같은 데이터를 모으는 데 1.5배 시간이 필요해요. 가능하면 핵심 변형 1개만 테스트하는 게 효율적.
샘플 크기 — 충분한 데이터
최소 100건 전환 룰
최소 100건의 전환(Conversion)이 발생한 후에야 통계적 유의성을 신뢰합니다. 이유는 1편에서 본 동전 비유와 같아요. 초기 데이터에서 나타나는 유의성은 매우 불안정해서 시간이 지나면 사라질 수 있습니다.
직관 비유:
- 동전 3번 던져 앞 3번 → 앞면만 나오는 동전? NO
- 동전 1000번 던져 앞 700번 → 편향된 동전? YES
A/B 테스트도 마찬가지:
- 10명 중 7명 변형 선택 → 신뢰 불가
- 1000명 중 600명 변형 선택 → 신뢰 가능
트래픽 수준별 신뢰 수준 조정
작은 사이트에서 95% 신뢰 수준은 도달에 수개월 걸려요. 현실적 기준을 정합니다.
| 트래픽 (일 방문자) | 권장 신뢰 수준 | 비고 |
|---|---|---|
| 100명 이하 | 75~80% | 결제 핵심 기능 변경 금지, UI 색상 등만 |
| 1,000~10,000명 | 90% | 일반 |
| 100,000명+ | 95%+ | 표준, 다중 테스트 동시 진행 가능 |
No Dead Ends — UX 설계 원칙
이게 설계 단계에서 꼭 짚고 가야 할 원칙이에요. 사용자가 어떤 행동을 완료한 후 "할 일이 없는 상태"로 방치되어서는 안 된다는 것.
가장 큰 Dead End의 예 — 결제 완료 페이지.
일반적인 결제 완료 페이지:
"주문이 완료되었습니다. 곧 확인 이메일을 받으실 겁니다."
문제: 사실상 "이제 이메일을 확인하러 우리 사이트를 떠나세요"
해결 아이디어:
- 신제품 미리보기 + 투표 → 이메일 알림 구독 유도
- 관련 상품 추천 → 추가 구매 유도
- 소셜 공유 → 구전 마케팅
- 리뷰 작성 요청 → UGC 수집
핵심 — 어떤 행동을 유도하든 사용자를 사이트 안에 머물게 하는 것.
이 원칙을 검증하는 테스트의 지표 선택도 중요해요.
| 지표 | 측정 가능? | 적합도 |
|---|---|---|
| LTV (고객 생애 가치) | 1년+ | 부적합 |
| 재구매율 | 수개월 | 단기 부적합 |
| 방문 간격 시간 | 수일 | 적합 |
| 주당 방문 횟수 | 즉시 | 적합 |
4편(실제 사례)에서 결제 완료 페이지 투표 컴포넌트로 이 원칙을 코드로 풀어 갑니다.
Peeking Problem — 조기 종료 함정
테스트 진행 중에 결과를 자주 들여다보다가 통계적 유의성이 잠깐 나타났을 때 바로 종료하는 실수예요.
나쁜 예:
- 테스트 시작 후 2시간 경과
- 변형 전환율 25% (대조군 15%)
- 통계적 유의성: 85% 달성
- 결정: "변형이 이겼다! 바로 적용!"
좋은 예:
- 최소 100건 전환 또는 1주일 이상 경과
- 주중/주말 트래픽 패턴 모두 포함
- 그 후에 통계적 유의성 확인
여기서 정말 중요한 시험 함정 — 테스트 시작 전에 종료 기준(목표 신뢰 수준·최소 샘플 크기·기간)을 정해 둬야 합니다. 결과를 보면서 종료 시점을 결정하면 그게 바로 Peeking Problem이에요. 5편(통계 심화)에서 베이지안 접근이 이 문제를 어떻게 해결하는지 다룹니다.
가설 없는 테스트 — 가장 흔한 실수
"그냥 이것저것 바꿔보자"는 접근은 결과가 좋아도 왜 좋아졌는지, 다음에 무엇을 해야 하는지 알 수 없게 만들어요. 가설 없는 테스트는 데이터를 모은 게 아니라 노이즈를 모은 것입니다.
지나치게 많은 변형 동시 테스트
나쁜 예:
- Variation A: 버튼 색상
- Variation B: 버튼 텍스트
- Variation C: 버튼 위치
- Variation D: 버튼 크기
문제: 어떤 변경이 효과를 만들었는지 알 수 없음
각 그룹 사용자 수 1/4로 줄어 유의성 도달 오래 걸림
좋은 예: 하나의 핵심 변경만 테스트
효과 확인 후 다음 요소 테스트
시험 직전 한 번 더 — 자주 헷갈리는 함정 모음
여기까지가 2편의 핵심입니다. 시험 직전 또는 실무에서 헷갈릴 때 다시 펼쳐 볼 수 있게 압축 노트로 마무리할게요.
- 가설 형식 = 변경 + 이유 + 측정 가능 결과
- 귀무가설 H₀ = 효과 없다 (보수적 기본 가정)
- 새 버전이 더 낫다는 걸 스스로 증명 해야
- 좋은 지표 = 빠른 측정 + 비즈니스 연결 + 외부 요인 안정
- LTV·재구매율 = 단기 테스트 부적합
- 연속형 → 이진 변환 ("1개 초과 구매 여부")
- 이진 지표는 이상치에 강건
- 단일 지표 함정 = 목표 +15%인데 KPI -20%
- 주요 지표 + 핵심 KPI 감시 지표 함께 추적
- 페이지 타겟팅 —
match: /product/정규식 - 디바이스 타겟팅 — User-Agent 기반 (화면 너비 X)
- iPad 가로 모드 = 너비 넓지만 마우스 없음
- 수동 활성화 — API 호출 시점에 실험 적용
- 50/50 분할 = 가장 일반적
- 10/90 분할 = 위험 관리, 점진적 롤아웃
- 다중 변형은 통계 유의성 도달 오래 걸림 — 핵심 1개만
- 최소 100건 전환 후 유의성 신뢰
- 트래픽별 신뢰 수준 — 작으면 75~80%, 크면 95%+
- No Dead Ends — 행동 완료 후 다음 행동 유도
- 결제 완료 페이지 = 가장 큰 Dead End
- No Dead Ends 지표 = 방문 간격 시간·주당 방문
- Peeking Problem = 결과 보고 종료 시점 결정 X
- 종료 기준은 시작 전에 미리 정함
- 가설 없는 테스트 = 노이즈 수집
- 변경 변수는 한 번에 하나만 (다중 변경은 효과 출처 불명)
시리즈 다른 편
같은 시리즈의 다른 글들도 같은 톤으로 묶어 정리되어 있어요. 2편에서 잡은 설계 도구 위에 3편 시스템 구축이 그대로 올라갑니다.
- 1편 — A/B 테스트 입문 (대조군·전환율·유의성)
- 2편 — 테스트 설계 (현재 글)
- 3편 — A/B 테스트 시스템 (Feature Flag·실험 플랫폼)
- 4편 — 실제 사례 분석 (5가지 패턴)
- 5편 — 통계 심화 (카이제곱·베이지안·다중 비교)
- 6편 — 구현 패턴 (React·Node·Pandas)
- 7편 — 베스트 프랙티스 (실험 문화·흔한 실수)
공식 문서: Optimizely Sample Size Calculator에서 자신의 트래픽에 맞는 샘플 크기를 계산할 수 있어요.
다음 글(3편)에서는 백엔드 추적 서버·이벤트 수집·통계 계산까지 포함한 A/B 테스트 시스템을 Node.js와 Express로 직접 구축해 봅니다. 여기서부터 실제 코드가 본격적으로 등장해요.