엔지니어링


같은 요청인데 왜 다른 광고가 나올까? QA 엔지니어의 확률 추적기

한국신용데이터
2026-06-17
조회수 544


b072a016e7079.png안녕하세요. 한국신용데이터 품질개선팀 QA Engineer Yuri(김유리)입니다.

광고 QA를 처음 맡았을 때, 가장 먼저 막힌 건 기술이 아니었습니다. "맞는 결과가 무엇인가"를 정의하는 것부터 막혔습니다. 같은 요청을 보내도 매번 다른 광고가 나오는데, 한 번 봐서는 정상인지 버그인지조차 알 수 없었거든요.

그래서 검증 방법을 설계하는 과정에서, 이런 질문이 출발점이 됐습니다.

  • "이 광고가 지금 설계된 확률대로 나온 건가?"
  • "광고주가 지불한 비용만큼 정확하게 노출되고 있는 건가?"

이 질문들에 추측이 아닌 데이터로 답하기 위해, AI를 활용해서 광고 선택 로직과 통계 정합성을 검증할 수 있는 도구를 만들었습니다.


광고 플랫폼은 어떻게 동작하나?

먼저 전체 구조를 간단히 소개하겠습니다.

bd15c0f0ad446.png

캐시노트 앱의 광고 지면에서 광고 요청이 발생하면, 서빙 서버 안에서 광고 요청을 받아 광고 선택 엔진이 어떤 광고를 보여줄지를 결정합니다. 그렇게 선택된 광고 소재를 가져와 앱으로 응답합니다.

이 글에서는 이 흐름 중 광고를 어떤 확률로 선택하는지를 결정하는 광고 선택 로직을 어떻게 검증했는지에 집중해서 이야기하겠습니다.


선택 로직 검증, 확률을 데이터로 증명하는 과정

캐시노트 앱의 한 광고 지면에는 여러 광고주의 광고가 동시에 경쟁하고 있습니다. 광고주들은 "내 광고가 충분히 자주 노출되고 있는지", "내가 지불한 비용 대비 공정한 노출을 받고 있는지"가 중요합니다. 사장님(사용자) 입장에서도 같은 광고만 반복해서 보는 것보다 다양한 광고를 적절한 빈도로 보는 것이 경험상 자연스럽습니다.


이런 요구를 충족하기 위해 광고 플랫폼은 각 광고의 조건(예산, 우선순위, 목표 달성률 등)을 종합적으로 계산해서 확률 기반으로 광고를 선택합니다. 단순히 돈을 많이 낸 광고만 나오는 게 아니라, 여러 조건을 반영한 스코어에 따라 각 광고가 적절한 비율로 노출되도록 설계되어 있습니다.


QA 입장에서 이걸 검증해야 하는 이유는 명확합니다. 선택 로직이 잘못 동작하면 특정 광고주의 광고가 과다 노출되거나, 반대로 비용을 지불했는데 거의 노출되지 않는 상황이 발생할 수 있습니다. 이건 곧 광고주와의 신뢰 문제이자 매출 문제입니다.


이 선택 로직이 설계대로 동작하는지 검증하기 위해 광고 확률 예측 계산기와 JMeter 부하 테스트를 조합했습니다.

JMeter란? — 서버에 자동으로 반복적인 요청을 보내고 응답을 수집하는 오픈소스 부하 테스트 도구로 짧은 시간에 수만 건의 요청을 발생시킬 수 있어 확률 기반 시스템의 실측 분포를 모으는 데 적합합니다.

확률 기반이기 때문에 한두 번의 호출로는 검증이 불가능하고 충분한 표본을 통해 실측 분포가 기댓값에 수렴하는지 확인해야 했습니다. 광고 확률 예측 계산으로 "이론상 각 광고가 몇 %로 나와야 하는가"라는 기댓값을 먼저 구하고 JMeter로 실제 서빙 API에 수만 건의 요청을 보내서 집계한 뒤 두 값을 비교하여 편차가 허용 범위 안에 있는지를 확인하는 방식으로 검증을 진행했습니다.


왜 이런 방식으로 검증하게 됐을까?

처음부터 "광고 확률 예측 계산기 + JMeter" 조합은 아니었습니다.

처음에는 JMeter만 사용했습니다. 광고 서빙 API에 수천~수만 건의 요청을 보내고 결과 파일에서 어떤 광고가 몇 번 응답됐는지를 집계하는 방식이었습니다. 이렇게 하면 실제로 어떤 비율로 노출됐는지는 알 수 있었죠.

문제는 그다음이었습니다. 광고의 조건이 계속 바뀌면 우선순위가 조정되고, 광고가 추가/삭제되고, 예산이 변동됩니다. 조건이 바뀔 때마다 기댓값을 처음부터 다시 계산하고 JMeter 결과와 다시 비교하는 작업을 반복해야 했습니다.

그래서 반복되는 작업을 줄이기 위해 AI를 활용해서 광고 선택 비율을 검증할 수 있는 툴을 만들었습니다. 광고 송출 로직을 그대로 구현해서 광고 정보를 불러오면 기댓값이 자동으로 계산되도록 설계했습니다. 그리고 JMeter 결과를 파싱해서 계산기의 기댓값과 자동으로 비교하도록 연동하여 수동으로 하던 "기댓값 계산 → 결과 비교" 반복 과정을 자동화했습니다.


광고 선택 확률 계산

319ab09b2779f.png

검증의 첫 단계는 "광고들의 조건에서 이론상 어떤 비율로 나와야 하는가"를 계산하는 것입니다.

확률이 결정되는 3단계를 광고 확률 예측 계산기에 구현했습니다.

1단계 - 스코어 계산

각 광고의 잔여기간율, 우선순위, 예산 사용률, 소진 방식, 목표 달성률을 점수화한 뒤 가중합산해 하나의 스코어를 만듭니다. 이 스코어를 Softmax 함수에 넣으면 확률이 됩니다.

Softmax란? — 여러 점수를 "합이 100%가 되는 확률 분포"로 변환해주는 함수입니다. 점수가 높을수록 확률이 높지만, 점수가 낮다고 0%가 되지는 않습니다. "가장 좋은 후보가 거의 다 가져가되, 나머지에게도 작은 기회를 보장하는" 확률 분배 방식이라고 보시면 됩니다.

2단계 - 외부/하우스 광고 분리

광고는 외부 광고와 하우스 광고로 나뉩니다. 둘이 같은 파이에서 경쟁하면 하우스 광고가 외부 광고의 매출을 잠식할 수 있습니다. 그래서 파이를 먼저 N:M으로 분리합니다. 외부끼리 N% 안에서 Softmax 경쟁, 하우스끼리 M% 안에서 Softmax 경쟁합니다.

3단계 - MAX/MIN 클리핑

아무리 스코어가 높아도 한 광고가 최대 확률 상한을 넘을 수 없고, 아무리 낮아도 최소 확률 하한은 보장됩니다. 특정 광고가 극단적인 독식을 방지하는 안전장치입니다.


계산기에 광고를 등록하면 아래와 같이 예측 결과가 나옵니다.

ebcc9fa7f5cca.png


수만 건의 부하 테스트로 실측값 구하기 (JMeter 활용)

계산기에서 나온 확률은 이론상의 기댓값입니다. 실제 서버가 그대로 동작하는지는 실제 요청을 수만 건 보내서 결과 분포를 측정해야 알 수 있습니다.


이를 위해 JMeter를 AI로 만든 포털에 연동했습니다.

1. 테스트 시나리오 구성

JMeter는 JMX라는 파일에 "어디에, 어떻게, 얼마나" 요청할지를 정의합니다. 광고 서빙 API로 요청을 보내는 시나리오를 JMX로 만들어두고, 포털에서 광고지면 ID만 입력하면 JMX의 URL이 자동 치환되도록 했습니다. “JMX 파일을 매번 손으로 편집하지 않는다.” 이게 첫 번째 자동화 포인트였습니다.

TPS(초당 요청 수)와 테스트 시간도 포털에서 설정합니다. (예: TPS 50, 10분 → 총 30,000건 요청.)

2.테스트 실행

JMeter가 보내는 요청은 실제 앱이 보내는 요청과 형태가 동일합니다. 서빙 API 입장에서는 어디서 온 요청인지 구분하지 못하고, 운영 환경과 동일한 비딩 로직이 그대로 적용됩니다. 그래서 여기서 얻은 실측값을 운영 동작의 근거로 활용할 수 있습니다.

3.결과 분석, 광고 소재 식별자 분포 집계

테스트가 끝나면 JTL 파일에 수만 건의 요청-응답 기록이 남아 있습니다. 이 파일을 파싱해서 "어떤 광고가 몇 번 응답받았는가"를 집계합니다.

핵심은 ccId(광고 소재 식별자) 추출 입니다. JTL에 기록된 각 요청의 URL에서 이 ccId를 추출하면 "이 요청에는 어떤 광고 소재가 선택됐는지"를 알 수 있습니다.


기댓값 vs 실측값 비교

계산기에서 구한 기댓값과 JMeter에서 구한 실측값을 나란히 놓고 비교합니다.

37a7bd9250d05.png


결과는 시간 구간별로 누적 분석하여 두 가지 차트로 보여줍니다. 예측 vs 실제 비교 차트는 노출 비율의 변화로, 각 광고의 예측 비율(실선)과 실측 비율(점선)을 시간 순서대로 겹쳐 그립니다. 아래 차트는 노출 건수의 추이로, 구간별·누적 건수를 함께 추적할 수 있습니다.

위 차트에서 보이듯 시간이 지남에 따라 비율이 기댓값에 수렴하는 과정을 관찰할 수 있습니다. 이는 버그가 아니라 표본 크기에 따른 자연스러운 변동입니다. 초반에는 표본이 적어서 편차가 크지만, 테스트가 진행될수록 안정적인 비율에 수렴합니다.

그래서 검증은 특정 시점이 아니라 충분히 쌓인 누적 결과로 판정하며, 허용 편차 역시 각 광고가 받은 노출 수에 따라 다르게 적용합니다.


QA 관점의 테스트 케이스

선택 로직 검증은 두 가지 관점으로 나눠서 진행했습니다. 하나는 운영자가 광고 지면의 구성을 바꿨을 때 비율이 의도대로 재분배되는지, 다른 하나는 테스트가 흐르는 동안 시간·예산·목표 수치가 변하면서 비율이 시계열로 어떻게 움직이는지입니다.


1.광고 지면 구성에 따른 검증

광고 지면에 새 광고가 추가되거나 기존 광고가 종료되면 나머지 광고들의 비율이 재분배됩니다. 광고 3개로 측정한 뒤 1개를 추가해 다시 측정해서, 단순히 "새 광고가 나오는가"가 아니라 "나머지 광고 비율이 예측대로 줄어들었는가"에 대한 검증이 필요합니다.

광고 옵션을 바꾸는 경우도 마찬가지입니다. 우선순위를 "보통"에서 "긴급"으로 올리면 스코어가 변하고 노출 확률도 따라 변해야 하므로, 변경 전후로 각각 계산기 기댓값과 JMeter 실측값을 비교합니다.

2.광고 요청 반복에 따른 시계열 검증

시계열 검증은 "변화가 일어나는 시점 전후로 비율이 의도대로 움직이는가"를 확인합니다. JMeter를 수십 분 단위로 길게 돌리며, 짧은 간격으로 누적된 비율 변화 차트로 양상을 관찰합니다.

먼저 시간 경과에 따른 변화가 있습니다. 광고의 운영기간이 끝나갈수록 잔여기간율이 줄어들고, 이에 따라 스코어와 노출 확률도 변하도록 설계되어 있습니다. 운영기간이 짧게 남은 광고를 포함시켜 누적 차트에서 비율이 예측대로 변하는지 확인합니다.

예산 소진에 따른 변화도 있습니다. 예산이 소진된 광고는 더 이상 노출되지 않아야 하고 남은 파이는 다른 광고들에게 재분배되어야 합니다. 예산이 적은 광고를 포함한 상태에서 장시간 테스트를 돌려 소진 시점 이후 해당 광고 비율이 0%로 떨어지고 다른 광고 비율이 올라가는지를 확인합니다.

마지막으로 목표 달성률에 따른 변화입니다. 광고에는 일별/전체 목표 노출 수치가 있어 달성률이 올라갈수록 과다 노출이 억제되도록 설계되어 있습니다. 목표 수치가 낮은 광고를 포함시켜, 달성률이 0% → 100%로 차오르는 동안 해당 광고 비율이 점진적으로 감소하는지를 시간 구간별로 확인해야 합니다.


광고 조건은 계속 바뀝니다. 새 광고가 들어오고, 예산이 줄고, 우선순위가 조정됩니다. 이 시나리오들을 바뀔 때마다 반복 검증할 수 있었던 건, 기댓값 계산부터 결과 비교까지 자동화되어 있었기 때문입니다.


마치며

이 도구를 만들기 전에는 "광고 노출 비율이 맞는 건가요?"라는 질문에 "여러 번 확인해봤는데 대략 맞는 것 같습니다"라고 대답할 수밖에 없었습니다. 지금은 확률 예측 계산기와 JMeter 결과를 나란히 놓고 "기댓값 38.7% 대비 실측값 38.4%, 편차 -0.3%로 허용 범위 안에 있습니다"라고 숫자로 답할 수 있습니다.


이 과정에서 AI의 역할이 컸습니다. 광고 선택 확률 계산기 자체를 AI를 활용해서 구현했고, 광고 송출 로직의 스코어 공식, Softmax 계산, 그룹 분리, 클리핑까지 복잡한 로직을 빠르게 도구화할 수 있었습니다. 수동으로 했다면 로직을 이해하고 구현하는 데만 상당한 시간이 걸렸을 텐데, AI를 활용하여 작업하면서 결과를 검토하는 방식으로 개발 속도와 정확성을 동시에 높일 수 있었습니다. 


요즘 QA 영역에서도 AI를 활용하는 사례가 빠르게 늘고 있습니다. 테스트 케이스 생성, 로그 분석, 이상 탐지 등 다양한 곳에 AI가 쓰이고 있죠. 저는 "검증 도구 자체를 AI로 만든다"는 방향이었습니다. QA 엔지니어가 도메인 지식(광고 선택 로직이 어떻게 동작하는지)을 갖고 있고, AI가 그것을 도구로 빠르게 구현해주면 검증의 속도와 깊이가 동시에 올라갑니다.


확률 기반 시스템의 QA에서 가장 중요한 건, "맞는 것 같다"를 "맞다"로 만들어가는 과정이라고 생각합니다. 기댓값을 먼저 구하고, 충분한 표본으로 실측하고, 둘을 비교하는 이 흐름은 광고가 아니더라도 추천, 랭킹 등 확률이 관여하는 시스템이라면 동일하게 적용할 수 있을 거라 생각합니다.






7 0

월간 인기글