대조군 없이 광고 증분 측정하기
광고 플랫폼 기준 가입 단가가 거의 같던 두 시장이 광고를 꺼 보니 실제 단가에서는 세 배 가까이 차이 났습니다. 한 시장에서 광고가 데려왔다고 집계된 가입자 대부분이 광고를 꺼도 그대로 들어왔기 때문이에요.
이 차이는 모든 유료 광고를 2주 동안 끈 뒤에야 드러났는데 측정 조건은 좋지 않았습니다. 광고는 같은 날 밤 국가별로 몇 분 간격을 두고 모두 꺼져서 광고를 켜 둔 채 비교할 시장이 하나도 남지 않았어요. 서비스도 그 2주 동안 평소처럼 돌아갔습니다. 한 국가에서는 광고와 무관한 바이럴로 가입이 튀었고 대행사가 운영하던 채널 하나는 며칠 늦게 꺼졌어요. 깔끔하게 나눈 A/B 테스트 대신 매일 무언가 바뀌는 운영 환경 한가운데서 광고 효과만 골라내야 했습니다.
제가 가장 먼저 다시 정한 대상은 지표였어요. 광고를 끄면 측정 지표부터 오염되기 때문이에요(1번). 광고 외 사건이 섞인 날짜를 걷어낸 뒤(2번) 대조군 대신 “광고를 켰다면 나왔을 숫자”를 추정했어요(3번). 계산 기준을 고정한 다음(4번) 결과를 검증했습니다(5번).
1. 측정 지표: 광고를 꺼도 흔들리지 않는 숫자
광고 효과를 볼 때 보통 먼저 여는 숫자는 어트리뷰션 툴의 Paid(광고 유입) 가입 수예요. 어트리뷰션 툴은 가입자가 어떤 광고를 보고 들어왔는지 이어 주는 도구인데 광고를 끄면 이 분류부터 흔들립니다. 광고가 꺼진 뒤에 들어온 사람은 전부 Organic(자연 유입)으로 잡히니까 원래 Paid로 세던 사람 중 일부가 Organic으로 자리만 옮겨요. 이 상태에서 Paid만 보면 감소가 실제보다 커 보이고 Organic만 보면 자연 유입이 늘어 보입니다.
이 오염을 피하려고 Paid와 Organic을 합친 일별 전체 계정 생성 수를 지표로 정했어요. 합계로 보면 분류만 옮겨 간 사람은 그대로 남고 광고가 사라져서 실제로 안 들어온 사람만 빠집니다. 국가와 OS마다 돌리던 광고 구성이 달랐기 때문에 이 합계는 국가×OS(iOS, Android) 셀 단위로 따로 집계했어요. 지표가 정해지자 다음 문제는 어느 날짜의 숫자를 쓸지였습니다.
2. 측정 구간: 광고 말고 다른 요인이 섞인 날짜를 뺀다
광고를 끈 날 유입이 바로 0이 되진 않아요. 전날 광고를 본 사람이 다음 날 설치하기도 해서 끈 날(D0)과 다음 날(D+1)에는 광고 효과가 아직 남습니다. 이 이틀을 잔존 구간으로 빼고 D+2부터 D+14까지를 측정 구간으로 잡았어요.
측정 구간 안에서는 광고 말고 다른 요인이 가입 수를 움직이지 않게 막아야 했습니다. 서비스를 멈추지는 못해도 가입 화면처럼 신규 유입을 직접 움직이는 제품 변경은 측정 기간 뒤로 미뤘어요. 가입 화면이 바뀐 주에 가입이 줄면 원인이 광고인지 화면인지 가를 방법이 없기 때문입니다. 미리 막지 못한 사건은 날짜를 옮겨서 피했어요. 바이럴 급증과 늦게 꺼진 채널이 측정 초반과 겹쳐서 측정 시작일을 전 국가 공통으로 며칠 늦췄습니다.
이렇게 정리한 구간의 실측치는 광고가 없을 때 들어오는 수준을 보여 줍니다. 광고 효과를 알려면 이 실측치와 비교할 기준이 하나 더 필요했어요.
3. 반사실(Counterfactual) 추정: 대조군 없이 “광고를 켰다면”을 계산하기
반사실(Counterfactual)이란
반사실(counterfactual)은 “그 일이 일어나지 않았다면 어땠을까”에 해당하는 결과예요. 광고 효과는 광고를 집행한 결과와 같은 시기에 광고를 집행하지 않았다면 나왔을 결과의 차이로 정의됩니다. 이번 경우에 대입하면 광고를 끈 2주의 실제 가입 수와 같은 2주 동안 광고를 계속 켰다면 나왔을 가입 수의 차이가 광고 효과예요. 이 중 실제로는 일어나지 않은 뒤쪽 결과가 반사실입니다.
반사실은 직접 관측하지 못합니다. 같은 2주를 광고를 켠 채로 한 번, 끈 채로 한 번 살아 볼 방법이 없으니까요. 통계학에서는 이 문제를 인과추론의 근본 문제(fundamental problem of causal inference)라고 불러요.
A/B 테스트는 이 문제를 푸는 가장 흔한 방법입니다. 무작위로 나눈 대조군이 실험군의 반사실 역할을 하니까 두 그룹의 차이를 그대로 효과로 읽어요. 대조군이 없을 때는 반사실을 데이터로 추정해야 하는데 이 방법을 반사실 분석(counterfactual analysis)이라고 합니다. 과거 추세나 비슷하게 움직이는 다른 시장, 요일 패턴 같은 정보로 “개입이 없었다면 나왔을 숫자”를 만들고 그 숫자를 실측과 비교하는 방식이에요.
1차는 단순하게, 2차는 정교하게
AI에게 측정 설계를 물었을 때 첫 제안도 대조군을 만드는 쪽이었어요. 채널을 하나씩 끄거나 한 나라는 광고를 켜 두자는 안이었는데 광고가 이미 다 꺼진 상황에는 맞지 않았습니다. 대조군 없이 반사실을 추정하는 방법을 다시 묻자 이번엔 인과추론 기법 이름이 설명 맨 앞에 나왔어요. 이 숫자를 같이 볼 사람은 마케팅팀이었기에 “이건 연구가 아니라 실무다”라고 되돌렸습니다. 누구나 검산하는 단순한 방법은 1차로 쓰고 정교한 모델은 2차 본분석으로 미뤘어요.
1차 반사실은 OFF 직전 4주와 8주의 같은 요일 평균이에요. 월요일 기대값이 지난 4주(또는 8주) 월요일 가입 수의 평균이 되는 식인데 가입은 요일마다 크게 달라서 요일을 맞추지 않으면 비교가 틀어집니다. 평균을 내기 전에 OFF 기간에 다시 일어나지 않을 날도 걸러냈어요. 8주 구간에 낀 짧은 바이럴 기간은 기대값만 부풀리기 때문에 뺐고 요일별 최댓값과 최솟값도 하나씩 빼고 평균을 냈습니다. 기준 기간을 4주로 잡느냐 8주로 잡느냐에 따라서도 반사실이 달라져서 두 결과를 나란히 적고 하나의 값이 아닌 범위로 읽었어요. 두 기준의 차이가 큰 셀일수록 추정의 오차도 크다고 봤습니다.
2차 본분석에는 구글이 공개한 오픈소스 패키지 CausalImpact를 쓰기로 했어요. 베이지안 구조적 시계열(Bayesian structural time series) 모델로 반사실을 만드는 도구입니다. 광고를 끄기 전 기간에 우리 가입 수와 함께 움직이던 다른 숫자(보조 지표)를 학습한 뒤 OFF 기간의 보조 지표 값을 넣어 “광고를 켰다면 나왔을 우리 가입 수”를 예측해요.
이 방식에서는 보조 지표가 반사실의 품질을 결정합니다. 보조 지표가 광고의 영향을 받으면 모델이 광고 효과까지 원래 흐름으로 학습해 버리니까 광고와 무관하면서 우리 숫자와 같이 움직이는 숫자만 골랐어요.
- 원래 광고를 하지 않던 권역의 계정 생성 수. 광고 없이도 계절과 트렌드를 우리 숫자와 공유해서 사실상 대조군 역할을 대신합니다. 권역별 가중치는 모델이 OFF 이전 구간의 적합도로 정하고 광고 국가와 닮은 권역일수록 큰 가중치가 붙어요.
- 요일과 공휴일 목록. 요일 패턴과 연휴 효과를 통제합니다.
- 설치 수와 가입 후 행동 지표는 일부러 뺐다. 광고에 직접 반응하는 숫자라서 보조 지표로 넣으면 광고 효과가 반사실 안으로 새어 들어가요.
학습 기간도 결과를 바꾸는 변수라서 8주와 12주, 16주를 비교하고 OFF 이전 구간을 가장 잘 맞히는 길이로 정하기로 했습니다. 1차 결과에는 이 본분석이 끝날 때까지 잠정치라고 표시했어요.
4. 계산 기준: 분모와 용어부터 고정한다
반사실이 나오면 남은 일은 나눗셈인데 여기서 시간을 가장 많이 잃었습니다. 귀속 실적과 감소분, 증분 중 무엇을 분모로 쓸지 정하기 전에 계산부터 시작했어요. 분모를 바꿀 때마다 단가와 과기여, 비율, 라벨을 전부 다시 계산해야 했습니다. “베이스라인”이라는 단어도 엉켰어요. 계획서에서는 OFF 기간 실측치를 뜻했는데 1차 분석에서는 OFF 전 4주 평균을 뜻했습니다.
재작업 끝에 정의를 아래처럼 고정했어요. 예시 숫자는 설명용 가상값입니다.
| 이름 | 정의 | 예시 |
|---|---|---|
| 광고비 | 기준 기간의 광고비 | 100만 원 |
| 기존 추정 (A) | 광고가 켜졌을 때 Paid로 잡힌 가입 수 | 250명 |
| 반사실 가입 수 (B) | 광고를 계속 켰다면 나왔을 전체 가입 수 | 1,000명 |
| 실측 가입 수 (C) | OFF 기간의 실제 전체 가입 수 | 900명 |
| 실제 감소분 (B−C) | 광고가 실제로 데려오던 사람 수 | 100명 |
- 과기여 = A − (B−C) = 150명. 원래 자연 유입인데 광고로 잡힌 사람 수입니다.
- 실질 기여율 = (B−C) ÷ A = 40%. Paid로 잡힌 가입 중 광고가 실제로 데려온 비율이에요.
- 장부상 CPA = 광고비 ÷ A = 4,000원.
- 실질 단가 = 광고비 ÷ (B−C) = 10,000원.
- 갭 = 실질 단가 ÷ 장부상 CPA = 2.5배.
A는 광고 플랫폼이 말하는 광고 효과이고 B−C는 반사실과 비교해서 얻은 실제 광고 효과예요. 둘의 차이가 클수록 갭이 커지고 갭이 클수록 광고가 자연 유입을 자기 몫으로 셌다는 뜻입니다.
5. 결과와 검증: 공유한 뒤에도 숫자는 흔들렸다
이 기준으로 국가×OS 셀을 계산하자 갭이 크게 갈렸어요. 광고 플랫폼 숫자를 거의 그대로 믿어도 되는 1배 근처의 셀부터 몇 배에 이르는 셀까지 나왔습니다. 단가가 비슷하던 두 시장의 격차도 이 계산에서 확인했어요. 전체로 보면 Paid로 잡힌 가입 중 3~4할이 광고 없이도 들어오는 사람이었습니다.
숫자를 그대로 믿기 전에 두 가지를 더 확인했어요. 첫째는 데이터 길이였습니다. 사흘치로 계산했을 때는 광고를 껐는데도 실측이 반사실보다 높은 셀이 나왔어요. 일주일치가 쌓이자 이 셀도 감소로 돌아섰습니다. 둘째는 계산 실수였어요. 첫 공유 뒤 회의를 마치고 숫자를 다시 보다가 한 국가의 iOS 데이터에서 계산 오류를 찾았습니다. 같은 수정을 다른 국가에도 적용하자 전체 숫자가 조금씩 움직였고 다음 날 바뀐 숫자와 이유를 같이 다시 공유했어요.
6. 남은 한계와 결과를 쓴 범위
이렇게 다듬어도 반사실은 실측이 아닌 추정치라서 문서에는 상한 추정이라고 적었어요. 모든 채널을 동시에 껐으니 채널별 효과도 이 테스트로는 나뉘지 않았습니다. 채널별 효과는 매체를 하나씩 다시 켜면서 재기로 했어요.
OFF를 더 이어 가자는 의견도 나왔습니다. 연장하면 광고 없는 수준이 더 정확히 보이지만 그동안 신규 가입 감소가 이어져요. 주요 국가의 수준은 이미 확인했으니 소셜 광고 하나부터 다시 켜고 켜는 매체마다 증분을 재기로 했습니다.
한계는 나중에 하나 더 찾았어요. 한 국가는 OFF 직전까지 인지도를 쌓는 노출형 캠페인을 크게 돌렸는데 노출형 광고의 효과는 며칠에서 몇 주 늦게 나타납니다. 광고를 끈 뒤에도 쌓인 인지도로 자연 유입이 이어졌어요. 이 유입이 광고가 없을 때의 수준으로 잡히면서 이 국가의 광고 효과는 실제보다 작게 측정됐습니다. 이틀로 잡은 잔존 구간이 노출형 캠페인에는 짧았던 셈이라 이 국가의 결과는 예산 축소 근거로 쓰지 않았어요.