A/B 테스트 도구 GrowthBook, 작은 팀이 고르고 쓰는 법

A/B 테스트와 기능 플래그 도구를 작은 팀이 고르는 기준을 정리해요. 셀프호스팅 GrowthBook 과 PostHog 의 운영 부담 비교, 플래그를 코드 밖에 두는 법, 지표를 먼저 정하는 법과 도구의 한계까지 다뤄요.

셀루모2026.10.01 · 12분 읽기
목차

가격을 두 가지로 보여 주고 어느 쪽이 더 눌리는지 보고 싶어지는 순간, A/B 테스트 도구를 찾게 돼요. 그런데 도구를 고르는 일보다 먼저 정해야 할 것들이 있어요. 이 글은 작은 팀이 실험 도구를 고르고, 실험을 믿을 수 있게 세우는 순서를 정리해요.

혹시 이런 고민 있으신가요?

  • A/B 테스트 도구를 직접 서버에 올리고 싶은데, 무엇을 같이 돌려야 하는지 감이 안 와요.
  • 기능을 켜고 끄는 값을 환경변수에 넣어 뒀더니, 바꿀 때마다 배포를 다시 해야 해요.
  • 실험은 돌렸는데 끝나고 나서야 무엇을 보고 판단할지 고민하게 돼요.

이 글을 읽으면

  • 셀프호스팅 실험 도구를 "같이 운영해야 하는 것"의 목록으로 비교해 고를 수 있어요.
  • 기능 플래그를 코드와 배포 밖에 두고, 방문자마다 같은 변형이 나오게 배정 기준을 고정할 수 있어요.
  • 실험 전에 지표와 판정 기준을 적고, 그 기준에서 필요한 트래픽을 거꾸로 계산할 수 있어요.

1단계. 도구를 운영 부담으로 비교하기

먼저 용어 두 개를 정리할게요. 기능 플래그는 코드를 다시 배포하지 않고 기능을 켜고 끄는 스위치예요. A/B 테스트는 방문자를 무작위로 나눠 서로 다른 화면을 보여 주고, 어느 쪽이 목표에 더 가까운지 숫자로 비교하는 실험이에요. 요즘 도구는 둘을 함께 다뤄요. 실험은 결국 "이 방문자에게 어떤 값의 플래그를 줄까"를 무작위로 정하는 일이니까요.

셀프호스팅, 즉 도구를 남의 클라우드가 아니라 내 서버에 직접 설치해 쓰기로 했다면, 기능 목록보다 먼저 볼 것이 있어요. 그 도구가 함께 띄우라고 요구하는 부품이에요. 부품 하나하나가 백업, 업그레이드, 장애 대응을 요구하니까요.

비교 항목PostHog 셀프호스팅GrowthBook 셀프호스팅
함께 띄우는 부품공식 문서의 예시 구성에 ClickHouse, Kafka, Zookeeper, Redis, Postgres, MinIO 가 보여요앱 외에 설정을 담는 MongoDB 하나를 요구해요
이벤트 데이터가 사는 곳도구가 자체 저장소에 모아요여러분이 이미 가진 데이터베이스에 두고, 도구는 집계 결과만 받아요
공식 지원셀프호스팅 인스턴스에는 고객 지원을 하지 않는다고 적혀 있어요이 글에서는 비교하지 않았어요

출처는 PostHog 셀프호스팅 문서, GrowthBook 셀프호스팅 문서, GrowthBook 데이터 소스 문서예요.

ClickHouse 는 대량의 이벤트를 빠르게 집계하는 분석용 데이터베이스이고, Kafka 는 쏟아지는 이벤트를 잠시 줄 세워 두는 메시지 대기열이에요. 둘 다 잘 만든 도구지만, 서버 한 대를 여럿이 나눠 쓰는 작은 팀에게는 각자 따로 돌봐야 하는 식구가 늘어나는 셈이에요.

저희는 이 표를 보고 PostHog 셀프호스팅을 뺐어요. 기록에 남은 이유는 ClickHouse 와 Kafka 의 운영 부담이었어요. 대신 GrowthBook 을 골랐고, 이벤트는 이미 운영 중인 Postgres 의 분석 전용 스키마를 데이터 소스로 연결하는 구조로 정했어요. 스키마는 한 데이터베이스 안을 나눈 방이라고 생각하면 돼요.

TIP

새 도구를 들이기 전에 "지금 있는 데이터베이스, 캐시, 배포 도구로는 정말 안 되는가"를 한 줄로 적어 보세요. 저희는 이것을 규칙으로 두고, 이미 거절한 패키지는 목록으로 만들어 설치하려는 순간 자동으로 막히게 해 뒀어요. 한 번 내린 결정을 매번 다시 논쟁하지 않게 돼요.

2단계. 플래그는 코드와 배포 밖에 두기

기능 플래그를 환경변수, 코드 속 상수, 앱이 직접 읽는 데이터베이스 행에 두는 경우가 많아요. 셋 다 처음엔 편해요. 하지만 환경변수와 상수는 바꿀 때마다 배포가 필요하고, 누가 언제 무엇을 바꿨는지 실험 기록과 따로 놀아요. 데이터베이스 행은 배정 로직을 직접 짜야 해서, 같은 방문자에게 늘 같은 변형을 주는 일까지 떠안게 돼요.

그래서 저희는 플래그와 실험을 실험 도구에만 둬요. 환경변수에는 도구의 주소와 클라이언트 키만 넣어요. 한 서비스의 요금제 실험은 플래그 두 개로 설계했어요.

플래그타입기본값역할
요금제 화면 킬 스위치불리언꺼짐꺼지면 화면과 진입점이 모두 사라져요
가격 변형문자열 low, mid, high빈 문자열실험 규칙이 세 값을 같은 비율로 나눠요. 빈 값을 받은 방문자에게는 화면을 보여 주지 않아요

킬 스위치는 문제가 생겼을 때 기능을 한 번에 끄는 비상 스위치예요. 기본값을 빈 문자열로 둔 이유가 중요해요. 배정 없이 보인 가격은 어느 실험 집단에도 속하지 않는 노출이라, 섞이면 결과가 흐려져요. 그래서 배정이 없으면 아예 보여 주지 않는 쪽을 골랐어요.

평가 코드는 도구가 없어도 안전한 쪽으로 떨어지게 짜요. 아래는 그 방식을 일반화한 예시예요.

TS
type Cohort = { enabled: boolean; variant: "low" | "mid" | "high" | null } const OFF: Cohort = { enabled: false, variant: null } // 도구 주소나 키가 비어 있으면 네트워크를 부르지 않고 꺼짐을 돌려줘요.export async function readCohort(  visitorId: string,  config: { apiHost?: string; clientKey?: string },  evaluate: (key: string, visitorId: string) => Promise<unknown>,): Promise<Cohort> {  if (!config.apiHost || !config.clientKey) return OFF  const enabled = (await evaluate("section_enabled", visitorId)) === true  const value = await evaluate("price_variant", visitorId)  const variant = value === "low" || value === "mid" || value === "high" ? value : null  return enabled && variant ? { enabled, variant } : OFF}

TIP

플래그 평가 함수에는 테스트를 붙여 두세요. 킬 스위치가 꺼졌을 때, 켜졌지만 변형이 빈 값일 때, 같은 식별자로 여러 번 평가해도 같은 값이 나올 때, 설정 값이 비었을 때 도구를 부르지 않을 때. 이 네 경우만 지켜도 실험이 조용히 망가지는 일을 많이 막아요.

3단계. 배정 기준을 하나로 고정하기

플래그를 어디에 둘지 정했다면, 다음은 무엇으로 방문자를 나눌지예요. 이것을 배정 기준, 도구의 말로는 해시 속성이라고 불러요. 도구는 이 값을 계산식에 넣어 방문자마다 늘 같은 변형을 돌려줘요. 같은 값이 들어가면 같은 답이 나오는 주사위라고 생각하면 돼요.

그래서 기준이 흔들리면 배정도 흔들려요. 탭마다 새로 만들어지는 값을 쓰면, 새 탭을 연 방문자가 다른 가격을 보게 돼요. 가격 실험에서 이건 결과가 흐려지는 문제를 넘어, 같은 사람에게 두 가격을 보여 주는 신뢰 문제예요.

저희는 이렇게 정했어요.

  • 평가는 서버에서 해요. 요금제 화면은 검색에 걸리도록 서버에서 그리는 공개 페이지라, 브라우저가 아니라 서버가 변형을 알아야 해요.
  • 서버가 읽을 수 있는 것은 쿠키라서, 무작위 값의 방문자 식별자를 쿠키에 둬요. 자바스크립트가 읽지 못하게 하고(httpOnly), 암호화된 연결에서만 보내고(secure), 다른 사이트에서 오는 요청에는 싣지 않게(sameSite lax) 했어요. 만료는 브라우저가 허용하는 상한인 400일로 잡아, 실험 기간 동안 다시 와도 같은 변형을 보게 했어요.
  • 이 쿠키의 목적은 실험 집단을 고정하는 것 하나뿐이고, 그 사실을 개인정보처리방침에 적었어요.

서버가 쿠키의 방문자 식별자를 읽고, 도구 설정이 없거나 킬 스위치가 꺼졌거나 변형이 빈 값이면 꺼짐으로 떨어지고, 모두 통과하면 배정된 가격으로 화면을 그리는 순서서버에서 평가하고, 하나라도 비면 화면을 그리지 않아요

로그인 뒤에는 사용자 ID 로 바꿔 나누고 싶어질 수 있어요. 기기를 바꿔도 같은 변형을 보여 줄 수 있으니까요. 저희는 로그인 여부와 상관없이 늘 방문자 식별자 하나로만 나눠요. 로그인 순간 기준이 바뀌면 같은 사람이 다른 가격을 볼 수 있고, 한 번 받은 변형을 따로 기억해 두는 저장소를 새로 둬야 해요. GrowthBook 문서도 이렇게 대체 속성을 쓰면 일관성을 얻는 대신 통계적 엄밀성을 잃는다고 적고 있어요(스티키 버케팅 문서). 기기마다 따로 세어져야 할 방문자가 같은 변형으로 묶이기 때문이에요.

4단계. 실험 전에 지표와 판정 기준을 적기

끝난 뒤에 기준을 정하면, 나온 숫자에 맞춰 기준을 고르게 돼요. 좋은 결과가 나온 지표만 골라 보고 싶은 마음은 누구에게나 있으니까요.

그래서 시작 전에 세 가지를 적어요. 무엇을 분모로 셀지, 무엇이 성공인지, 언제까지 볼지예요. 저희의 요금제 실험은 이렇게 적었어요.

  • 분모: 배정된 가격이 실제로 화면에 그려졌다는 노출. 페이지 방문과는 따로 세요.
  • 지표: 노출 대비 클릭률, 클릭 대비 이메일 제출.
  • 판정: 실험 집단마다 클릭률 5% 이상, 제출 50건 이상, 기간 21일. 집단을 합치지 않고 따로 판정해요.

분모는 생각보다 자주 틀려요. 첫 화면 아래쪽에 가격 카드를 두고 화면이 열리자마자 노출을 보내면, 스크롤하지 않은 방문까지 노출로 세어 클릭률이 낮아 보여요. 저희는 카드가 실제로 화면에 들어올 때 한 번만 보내고, 요금제 페이지에서 본 것과 첫 화면에서 본 것을 속성으로 나눴어요.

기준을 적었다면 거꾸로 계산해 보세요. 제출 50건이 필요하고, 클릭률이 5% 이고, 누른 사람이 모두 제출한다고 가장 좋게 잡아도 집단마다 노출 1,000건이 필요해요. 집단이 셋이면 기간 안에 3,000건이에요. 이 계산이 여러분의 트래픽으로 불가능하다면, 실험을 시작하기 전에 설계를 바꿔야 한다는 신호예요.

분모, 지표, 판정 기준을 차례로 적고 필요한 노출을 거꾸로 계산해, 기간 안에 모이면 실험을 시작하고 모이지 않으면 집단 수를 줄여 설계를 바꾸는 흐름시작 전에 기준을 적고, 트래픽으로 가능한지부터 따져요

TIP

판정 기준은 비율과 절대 건수를 함께 두세요. 비율만 두면 노출 20건에 클릭 2건도 10% 로 기준을 넘어요. 건수가 함께 있으면 운 좋은 작은 숫자에 속지 않아요.

5단계. 통계가 읽을 데이터와 도구의 한계를 확인하기

GrowthBook 같은 도구는 이벤트를 스스로 모으지 않아요. 여러분의 데이터베이스에 연결해 쿼리를 보내고, 그 결과로 통계를 내요. 공식 문서도 데이터는 여러분의 저장소에 남고 집계된 통계만 도구로 간다고 설명해요(데이터 소스 문서). 이벤트 데이터를 바깥으로 내보내지 않으려는 팀에게 잘 맞는 이유예요.

대신 연결은 여러분이 해야 해요. 저희는 분석 전용 스키마만 읽을 수 있는 계정으로 연결하도록 설계했어요. 실험 도구가 사용자 표나 결제 표까지 읽을 이유는 없으니까요. 그리고 도구는 이벤트를 저장하지 않으니, 페이지뷰는 웹 분석 도구가, 가설이 걸린 이벤트는 자체 수집 API 가 맡는 식으로 역할을 먼저 나눠 두는 게 좋아요.

실제로는 데이터 소스 등록에 데이터베이스 접속 정보가 들어가서 사람이 직접 넣어야 했고, 그 전까지 실험은 지표 없이 켜 두었어요. 지표 자체는 이미 실험의 가설 칸과 기획 문서에 적어 두었기 때문에, 판정은 같은 스키마를 읽는 쿼리로 대신할 수 있었어요.

참고

킬 스위치를 켜기 전에 지표를 붙이면 잃는 표본이 없어요. 이미 실험 시작일이 잡혀 있다면, 스위치를 켤 때 새 단계를 시작해 꺼져 있던 기간이 결과에 섞이지 않게 하세요.

도구가 해 주지 못하는 일도 분명해요.

  • 트래픽을 대신 만들어 주지 않아요. 방문자가 적으면 두 집단의 차이가 우연인지 효과인지 구분되지 않을 수 있어요. 집단을 나눌수록 한 집단에 돌아가는 방문자가 줄어서 더 그래요. 저희가 가격 집단을 셋에서 늘리지 않고, 네 개 이상은 범위에서 뺀 이유예요.
  • 무엇을 실험할지 정해 주지 않아요. 한 서비스에서는 보정 설정의 기본값을 실험으로 고르려던 계획을, 트래픽이 먼저라며 미뤘어요. 다른 서비스는 검증할 변형이 없어서 플래그 자체를 넣지 않았어요.
  • 이벤트가 틀리면 통계도 틀려요. 분모와 분자를 정확히 보내는 일은 여전히 여러분 코드의 몫이에요.
  • 도구의 설정 저장소도 운영 대상이에요. 플래그와 실험 설정이 MongoDB 에 있으니, 그 볼륨의 백업도 챙겨야 해요. 저희도 아직 데이터베이스 덤프만 매일 백업하고, 이 볼륨은 백업 계획에 올려 둔 상태예요.

자주 묻는 질문

Q1. 방문자가 적은데 A/B 테스트를 해도 되나요?

해도 되지만, 시작 전에 4단계의 거꾸로 계산부터 해 보세요. 기간 안에 필요한 노출이 모이지 않을 것 같다면 집단 수를 줄이거나, 한 가지 안만 보여 주고 반응을 재는 방식이 더 나을 수 있어요. 결과가 나와도 표본이 작으면 결론이 아니라 다음 실험의 가설로 다루는 게 안전해요.

Q2. 기능 플래그를 환경변수로 두면 뭐가 그렇게 문제인가요?

켜고 끌 때마다 배포가 필요하고, 무작위 배정이나 같은 사람에게 같은 값을 주는 일을 직접 짜야 해요. 무엇보다 문제가 생겼을 때 바로 끄는 킬 스위치 역할을 못 해요. 환경변수에는 도구 주소와 키처럼 "어디에 물어볼지"만 두는 게 좋아요.

Q3. 셀프호스팅 대신 클라우드 버전을 쓰면 운영 부담이 사라지지 않나요?

운영 부담은 줄어요. 다만 이벤트 데이터가 여러분 인프라 밖으로 나가게 돼요. 저희는 이벤트 데이터를 외부로 보내지 않는다는 원칙이 있어서 클라우드 버전은 비교하지 않았어요. 이런 원칙이 없다면 클라우드와 셀프호스팅을 같은 표에 놓고 비교해 보세요.

정리

  • 셀프호스팅 실험 도구는 기능보다 함께 운영해야 할 부품의 목록으로 먼저 비교해요.
  • 배정 기준은 서버가 읽는 방문자 식별자 하나로 고정하고, 로그인 전후로 바꾸지 않아요.
  • 플래그는 실험 도구에 두고, 도구가 없거나 배정이 비면 꺼짐으로 떨어지게 짜요.
  • 분모, 지표, 판정 기준, 기간을 시작 전에 적고, 그 기준에서 필요한 트래픽을 거꾸로 계산해요.
  • 도구는 통계를 계산할 뿐, 트래픽과 정확한 이벤트와 설정 백업은 여전히 여러분의 몫이에요.

좋은 실험 도구보다 먼저 필요한 것은, 끝나기 전에 적어 둔 한 줄의 판정 기준이에요.

이어서 읽기 좋은 글