광고 예산 페이싱은 캠페인의 일예산을 시간대별로 균등하게 소진하는 기능이다. 광고주가 노출 가능한 시간 안에서 예산을 안정적으로 쓰고 싶을 때 선택한다.
기존 방식은 한 마디로 모든 캠페인에 같은 규칙 을 적용하는 구조였다. 캠페인 특성과 무관하게 같은 출발선에서 시작하고, 소진 정도에 따라 일률적으로 노출 확률을 조정했다. 단순했지만 캠페인 특성이 크게 갈리는 환경에서는 잘 작동하지 않았다. 어떤 캠페인은 시간 초기에 예산을 빠르게 다 태웠고, 어떤 캠페인은 초기 캡에 막혀 미소진되었다.
단일 규칙으로 모든 캠페인을 동일하게 다루는 것 자체가 한계였다. 이 기능을 캠페인별 학습과 실시간 보정 의 2계층 제어 구조로 재설계했다.
단일 규칙의 한계
기존 구조의 약점은 명확했다. 모든 캠페인이 같은 출발선에 섰다. 캠페인의 특성은 평균이 아니라 분포로 존재하고, 시간대마다·환경마다 계속 바뀐다. 평균을 가정한 단일 규칙은 분포의 양 끝에서 깨졌다 — 빠르게 소진되는 쪽도 미소진되는 쪽도 같은 규칙으로는 흡수되지 않는다.
같은 확률을 적용한다는 것은 캠페인의 특성을 무시한다는 뜻이다.
2계층 구조
해법을 단일 계층 안에서 풀려고 했을 때 모순에 부딪혔다. 빠르게 반응하면 노출이 출렁였고, 느리게 반응하면 예산 미스가 누적됐다. 잦은 확률 변동은 광고주 입장에서 노출이 불안정해 보였고, 큰 단위로만 확률을 잡으면 그 사이의 트래픽 변동을 흡수할 수 없었다.
그래서 두 계층으로 나눴다.
Slow controller. 큰 시간 단위로 캠페인의 과거 소진 양상을 분석해 다음 구간의 기준선을 도출한다.
Fast controller. 짧은 시간 단위로 예상 대비 실제 소진을 비교해 남은 차이를 흡수한다.
slow controller 는 “이 캠페인이 어떤 페이스로 가야 하는가” 라는 가설을 갱신한다. fast controller 는 “지금 실제 페이스가 그 가설을 벗어나는가” 를 점검한다. 두 제어기의 시간 스케일이 책임을 자연스럽게 갈랐다.
기준선과 보정의 분리
핵심은 보정의 크기에 있다. slow controller 가 기준선을 잡지 못하면 fast controller 는 매번 큰 폭으로 확률을 흔들어야 한다. 기준선이 정확할수록 보정량은 작아진다. 작은 보정은 노출 안정성을 해치지 않으면서 단기 충격만 흡수한다.
기준선 자체는 측정 기반이다. 직전 구간에서 어떤 페이스로 움직였는지가 다음 구간의 시드가 된다. 측정-적용-측정의 단순 루프다.
여기에는 익숙한 함정이 따라온다. 측정값이 없을 때. 직전 구간 동안 노출이 거의 없어 측정 자체가 비는 캠페인이 있다. 이때는 측정 기반 보정 대신 외부에서 기본값을 주입해야 한다. 광고 도메인의 페이싱에서만 만나는 문제가 아니라 일반 제어 시스템의 cold-start 와 같은 결의 문제다.
적용 후
같은 시간대, 같은 캠페인 묶음으로 비교했을 때 세 가지 변화가 두드러졌다. 초기 집중 소진이 완화됐고, 시간 초기의 노출 폭주가 잦아들었으며, 미소진 캠페인의 소진율이 올랐다. 세 변화는 같은 원인의 다른 표현이다 — 고정 규칙에서 캠페인별 학습으로 옮긴 효과.
회고
이 작업의 가장 큰 결정은 두 계층으로 나눈 것 자체였다고 본다. 단일 계층 안에서 학습과 보정을 동시에 하려고 했다면 매번 확률이 흔들렸을 것이고, 큰 단위로만 잡았다면 단기 충격을 흡수하지 못했을 것이다. 시간 스케일이 다른 두 신호를 두 제어기로 분리한 것이 자연스러운 책임 분리였다.
control loop 이라는 언어가 광고 도메인에서도 그대로 맞아 떨어진다는 것이 흥미로웠다. 제어공학에서 다루는 cold-start, integrator windup, 측정 결손 같은 문제가 광고 페이싱에도 똑같이 나타났다. 도메인이 달라도 같은 형태의 문제가 반복되는 자리에서는 같은 언어를 빌려오는 게 사고를 덜 흔들리게 만든다고 봤다.
다음에 비슷한 결을 만난다면 — 측정 신호의 시간 스케일이 두 개 이상으로 갈리는 자리에서 — 처음부터 계층을 나눠보려 한다.