구글 검색광고는 왜 30일 동안 3번만 노출됐나?
검색광고 입찰가 상한은 사람이 감으로 고른 숫자 하나로 두면 안 됩니다. 채널마다 1,800원, 5,000원을 정해 두고 쓰던 방식을 버리고, 하루 예산을 목표 클릭 수로 나눈 값(두 채널 모두 2,500원)을 천장으로 삼도록 바꿨습니다. 다만 이 글의 핵심은 그 공식보다, 그 공식에 닿기까지 두 번 틀린 진단입니다.
출발점은 단순한 질문이었습니다. 구글 검색광고를 켜 두었는데 최근 30일 동안 광고가 사실상 뜨지 않았습니다. 최근 7일로 좁혀 보면 노출 3회, 클릭 0회, 소진 금액 0원이었습니다. 예산을 다 써서 멈춘 게 아니라, 돈을 한 푼도 쓰지 못한 상태였습니다.
네이버 쪽은 사정이 반대였습니다. 광고는 나가고 돈도 나갔지만, 입찰 상한이 5,000원으로 넉넉하게 열려 있어서 클릭 한 번에 4,400~4,600원을 쓰는 키워드가 섞여 있었습니다. 한쪽은 너무 못 쓰고 한쪽은 비싸게 쓰는, 방향이 서로 다른 문제 두 개가 같은 설계에서 나오고 있었습니다.
두 채널 모두 키워드 목록과 입찰 상한을 한 파일에서 관리하고, 스크립트가 그 값을 네이버·구글 광고 계정에 반영하는 구조였습니다. 콘솔에서 손으로 입찰가를 만지지 않는다는 원칙은 이미 있었습니다. 문제는 그 파일에 들어가는 숫자를 어떻게 정하느냐였습니다.

처음 잰 숫자: 노출점유율 9.99%, 놓친 노출의 90.01%는 순위 탓
먼저 구글 광고 계정에서 최근 30일 검색 노출점유율을 뽑았습니다. 광고가 나갈 수 있었던 검색 중 실제로 나간 비율이 9.99%였습니다. 놓친 노출을 이유별로 나누면 순위(입찰) 때문이 90.01%, 예산 때문이 6.80%였습니다. 예산이 모자라서가 아니라 경매에서 밀려서 못 나간다는 뜻으로 읽혔습니다.
키워드 단위로도 확인했습니다. 최근 30일 동안 노출이 한 번이라도 생긴 키워드는 39종 중 2종뿐이었습니다. 몇 개 키워드가 부진한 게 아니라, 거의 모든 키워드가 경매에 들어가지 못하고 있었습니다.
그다음 우리 파일에 적힌 「시장 CPC」 값을 들여다봤습니다. 구글 키워드 플래너 API는 키워드마다 상단 노출 입찰가 범위를 하한(low_top_of_page_bid)과 상한(high_top_of_page_bid) 두 값으로 줍니다. 우리 스크립트는 그중 하한을 시장 CPC로 저장하고 있었습니다.
| 지표 | median | max |
|---|---|---|
| 하한 low (파일에 저장하던 값) | 632원 | 1,716원 |
| 상한 high (실경쟁 상단) | 2,398원 | 8,889원 |
median 기준으로 632원 대 2,398원, 3.8배 차이입니다. 파일만 보면 상한 1,800원은 시장가 632원보다 세 배 가까이 넉넉해 보였습니다. 그런데 상단 대역으로 다시 대 보면 활성 34종 중 23종(68%)이 경쟁 대역에 못 미쳤습니다.

세운 가설: 입찰가 상한 1,800원이 경쟁 대역을 못 따라간다
숫자가 이렇게 나오자 가설은 자연스럽게 하나로 모였습니다. 시장가를 하한으로 잘못 재는 바람에 1,800원이라는 상한이 넉넉하다고 착각했고, 그 결과 입찰가가 경쟁 대역보다 낮아서 광고가 뜨지 않는다는 가설입니다. 노출점유율 손실의 90.01%가 순위 탓이라는 숫자가 이 가설을 강하게 받쳐 줬습니다.
이 가설에서 나온 처방도 분명했습니다. 구글은 기준 지표를 하한에서 상한(high_top_of_page_bid)으로 바꾸고, 캠페인 천장을 1,800원에서 올린다는 처방입니다. 그리고 채널마다 숫자 하나를 사람이 고르던 방식 자체를 버리기로 했습니다.
구글의 상단 입찰가는 「이 값은 내야 상단에 뜬다」는 이겨야 하는 값이고, 네이버의 최소노출가(min_bid)는 「이 값이면 겨우 노출된다」는 바닥값입니다. 성격이 반대인 두 지표에 같은 방식의 상한을 씌우면 한쪽은 늘 넘치고 한쪽은 늘 모자랍니다. 그래서 채널별로 기준 지표를 분리하기로 했습니다.
네이버 쪽에서는 가설을 하나 더 세웠다가 곧 버렸습니다. 처음에는 「네이버 키워드별 실적은 API로 조회할 수 없다」고 판단해 정책 초안에 「네이버 실적 미계측」이라고 적었습니다. 이 가설이 어떻게 틀렸는지는 다음 절에서 다룹니다.
두 가설은 어디서 틀렸나?
먼저 틀린 쪽은 네이버 실적 가설입니다. 네이버 검색광고 /stats API를 호출하면 본문 없는 HTTP 400이 돌아왔고, 이걸 API의 한계로 읽었습니다. 같은 가설로 5회를 다시 던졌지만 응답 본문이 비어 있다는 사실조차 확인하지 않았습니다.
광고주센터에서 보이는 게 API로 안 될 리 없다.
이 지적을 받고 요청을 다시 뜯어보니 원인은 URL 인코딩이었습니다. 쿼리 파라미터에 JSON 값({, [, ")을 인코딩 없이 붙이면 네이버는 본문 없이 400을 돌려줍니다. 인코딩을 넣자 정상으로 조회됐고, 호출 함수가 dict 파라미터를 직접 받도록 고쳐 같은 실수를 막았습니다.
조회해 보니 네이버 30일 실적은 노출 93,406회, 클릭 199회, 비용 101,167원, 평균 CPC 508원, 전환 0건이었습니다. 「미계측」이라고 적었던 자리가 실제 숫자로 채워지면서, 네이버 상한을 내릴지 말지를 감이 아니라 실적으로 판단할 수 있게 됐습니다.
두 번째로 틀린 쪽은 더 큰 가설, 곧 「구글 광고가 입찰가 부족으로 안 뜬다」는 진단이었습니다. 이건 일주일 뒤인 7월 26일에 드러났습니다. 구글 캠페인의 입찰 전략이 TARGET_SPEND(클릭수 최대화)로 잡혀 있었고, 이 전략에서는 우리가 키워드마다 넣은 입찰가를 경매가 아예 무시합니다.
그러니 1,800원이든 2,500원이든 키워드 입찰가를 아무리 조정해도 결과는 바뀌지 않았습니다. 노출점유율 손실이 「순위 때문」으로 찍힌 것도, 우리가 낮게 넣은 값 때문이 아니라 캠페인이 그 값을 쓰지 않았기 때문이었습니다. 입찰 전략을 수동 CPC(MANUAL_CPC)로 바꾸는 것이 진짜 수리였습니다.

진짜 원인: 입찰 전략 설정, 그리고 상한을 읽지 않는 반영 코드
7월 27일에 한 번 더 파고들었습니다. 계기는 「파일에 적힌 CPC 추정치가 실측보다 낮은데, 왜 같은 실패가 반복되느냐」는 질문이었습니다. 조사해 보니 이 질문의 전제부터 틀렸습니다. 추정치는 낮지 않았습니다.
7월 20일 처방대로 구글 입찰가는 시장 범위 상단(google_cpc_high)에서 나오고 있었고, 실측 CPC는 그 입찰가와 거의 같았습니다. 예를 들어 카카오톡챗봇 키워드는 입찰가 11,960원에 실측 CPC 11,266원이었습니다. 우리가 낸 값을 우리가 다시 확인했을 뿐입니다. 7월 26일과 27일 이틀 동안 88,599원이 이런 식으로 나갔습니다.
결함은 두 가지였습니다. 첫째, 잘못된 진단으로 올려 둔 보상값이 원인을 고친 뒤에도 그대로 남았습니다. 입찰 전략을 수동 CPC로 바꾸자 경매가 드디어 키워드 입찰가를 읽기 시작했고, 하필 그때 읽힌 값이 부풀린 상단가였습니다. 진짜 원인을 고칠 때 보상값을 함께 되돌리지 않은 것이 빈틈이었습니다.
둘째는 더 근본적이었습니다. 키워드 목록 파일을 만드는 빌더의 bid_caps() 함수가 채널별 상한(naver_bid_cap, google_bid_cap)을 계산해 저장하는데, 실제로 광고 계정에 값을 넣는 두 스크립트가 그 값을 읽지 않고 각자 다시 계산하고 있었습니다.
- google_ad_manager.py 160번째 줄 — min(google_cpc_high, GOOGLE_CAP) 로 따로 계산
- naver_ad_manager.py 98번째 줄 — min(min_bid × 1.2, NAVER_CAP) 로 따로 계산
- 네이버 쪽은 현재 입찰가가 최소노출가보다 낮을 때만 올리는 단방향 구조라, 한 번 오른 입찰가가 내려올 경로가 없었다
결과적으로 bid_caps()에 어떤 정책을 넣어도 라이브 광고에는 하나도 반영되지 않았습니다. 같은 값을 두 곳에서 따로 계산하는 이중 출처 구조였고, 정책 문서와 실제 광고 계정이 따로 움직였습니다. 설정은 바꿨는데 화면은 그대로인 문제를 다른 맥락에서 다룬 글로 설정을 바꿔도 반영되지 않던 이유가 있습니다.

조치: 입찰가 상한을 사람이 고르지 않고 예산에서 나눈다
조치는 두 단계로 나갔습니다. 7월 20일에는 상한을 정하는 규칙 세 가지를 문서로 정하고, 7월 27일에는 입찰 기준 자체를 바꾸고 이중 출처를 없애는 네 번째 규칙을 더했습니다.
첫째 규칙은 채널별 지표를 맞추는 일입니다. 네이버는 최소노출가 × 1.2를 기준으로 삼습니다. 마진 1.2를 올리지 않은 데도 근거가 있습니다. 클릭과 비용 대부분을 만드는 광고 그룹은 이미 평균 2.8위, 3.3위, 4.0위로 상위에 떠 있어 올릴 이유가 없고, 15.1위, 15.8위로 순위가 낮은 그룹은 CTR이 0.01% 수준이라 입찰을 올려도 회수가 어렵습니다.
둘째 규칙이 이 글 제목의 공식입니다. 절대 천장 = 하루 예산 ÷ 목표 일일 클릭 수. 구글은 하루 5,000원에 목표 2클릭, 네이버는 하루 20,000원에 목표 8클릭이라 두 채널 천장이 모두 2,500원으로 모입니다. 「하루 최소 이만큼은 클릭이 나와야 신호가 된다」는 요구를 예산으로 나눈 값이라, 예산이 바뀌면 천장도 따라 움직입니다.
| 채널 | 하루 예산 | 목표 일일 클릭 | 천장 | 이전 상한 |
|---|---|---|---|---|
| 구글 | 5,000원 | 2클릭 | 2,500원 | 1,800원 |
| 네이버 | 20,000원 | 8클릭 | 2,500원 | 5,000원 |
천장을 넘는 키워드는 끕니다. 클릭 한 번에 천장 이상을 내야 하는 키워드는 지금 예산으로 하루 1~2클릭도 얻기 어려워서, 켜 두면 예산만 먹고 신호는 나오지 않습니다.
셋째 규칙은 이 천장이 임시라는 선언입니다. 광고 유입의 유료 전환이 0건이라 아직 클릭 한 번의 가치를 계산할 수 없습니다. 유료 전환이 5건, 또는 광고를 거친 리드가 30건 쌓이면 허용 고객획득비용 × 클릭→유료 전환율로 천장을 다시 계산하기로 했습니다. 그 전에 감으로 상한을 올리는 일은 규칙 위반으로 봅니다.
넷째 규칙(7월 27일)은 기준을 「시장가」에서 「우리 계정이 실제로 내야 하는 값」으로 바꾼 것입니다. 구글은 품질평가점수를 반영한 계정 필요입찰가(position_estimates.top_of_page_cpc_micros)를, 네이버는 최소노출가를 쓰고, 둘 다 min(필요값 × 1.2, 가치 천장, 예산 천장)으로 자릅니다. 품질평가점수가 없는 신규 키워드만 시장 상단가로 폴백합니다.
같은 날 두 반영 스크립트가 빌더가 저장한 상한 값만 읽도록 고쳤습니다. 계산은 한 곳에서만 하고, 반영 쪽은 그 값을 소비만 합니다. 다시 갈라지지 않도록 회귀 테스트 5건을 붙였습니다.
검토하고 버린 대안도 둘 있습니다. 하나는 시장 상단가 기준을 그대로 두는 안이었는데, 원인이 사라진 뒤에도 보상값을 남겨 둘 근거가 없어 버렸습니다. 다른 하나는 반영 스크립트는 건드리지 않고 bid_caps()의 규칙만 문서로 정리하는 안이었습니다. 이렇게 하면 이중 출처가 그대로 남아 다음 정책 변경도 똑같이 무시당하므로 역시 버렸습니다.

재측정 결과: 구글 입찰 합계 124,620원에서 86,093원으로
재측정은 두 번 했습니다. 7월 20일 규칙을 적용하기 전에 한 번, 7월 27일 기준을 바꾼 뒤에 한 번입니다.
7월 20일 적용분을 실제 광고 계정에 반영한 결과 네이버 11건을 끄고 구글 19건을 바꿨으며(캠페인 천장 1,800원 → 2,500원 포함), 파일과 라이브 계정 사이 불일치 점검에서 차이는 0건이었습니다. 구글은 활성 34종 중 천장 2,500원을 넘는 16종을 끄고 18종만 남겼습니다. 꺼진 쪽의 상위는 홈페이지제작비용 8,889원, 1인법인설립 7,963원, 병원홈페이지제작 7,143원 같은 키워드였습니다.
남은 18종의 경쟁 상단 median은 760원이었습니다. 그래서 같은 하루 예산 5,000원으로 하루 약 6.6클릭을 기대할 수 있다고 계산했습니다. 이 6.6클릭은 입찰가만으로 계산한 추정이지 실측 클릭이 아닙니다. 게다가 이때는 아직 입찰 전략 문제가 드러나기 전이라, 이 추정의 전제 일부가 나중에 무너졌습니다.
네이버는 실적으로 확인했습니다. 천장이 5,000원에서 2,500원으로 내려가면 끄게 되는 키워드와 남는 키워드의 실적을 같은 조회 안에서 나란히 놓았습니다.
| 구분 | 키워드 | 노출 | 클릭 | 비용 |
|---|---|---|---|---|
| 유지 | 23종 | 9,031회 | 52회 | 18,611원 |
| 끔 | 14종 | 1,043회 | 5회 | 22,505원 |
끄는 쪽이 비용의 54.7%를 쓰면서 클릭은 8.8%만 만들었습니다. 앱제작비용은 3클릭에 13,403원(CPC 4,468원), AI콘텐츠는 1클릭에 4,646원, 부가세신고방법은 1클릭에 4,456원이었습니다. 캠페인 평균 CPC 508원과 비교하면 이 구간만 도드라지게 비쌌습니다. 천장 기준으로 끄는 10종의 검색량은 전체 활성의 4.7%(10,050 / 214,890)라, 나머지 95.3%에 예산을 남기는 편이 낫다고 판단했습니다.
천장 기준으로 꺼진 네이버 키워드와 당시 최소노출가 기준 입찰가는 AI도입 4,810원, 앱제작비용 4,800원, AI콘텐츠 4,650원, 업무효율화 4,070원, AI비서 4,060원, 사무자동화 3,640원, 부가세신고방법 3,520원, 엑셀자동화 3,130원, 법인세신고기한 2,620원, 종합소득세신고방법 2,600원입니다. 4,810원짜리 키워드는 4클릭이면 하루 예산 20,000원을 다 씁니다.

7월 27일 기준 교체 뒤 구글 입찰가 합계는 124,620원에서 86,093원으로 31% 줄었습니다. 필요입찰가를 받아 온 키워드 중에는 콜드메일이 7,695원에서 712원으로, 최대 91%까지 내려간 경우도 있었습니다. 모든 변경이 지출을 줄이는 방향이었습니다.

남는 한계: 전환 0건에서 입찰가 상한은 어디까지 믿을 수 있나?
가장 큰 한계는 전환 데이터가 없다는 점입니다. 네이버 30일 199클릭, 101,167원에 전환 0건입니다. 지금 천장 2,500원은 돈을 버는 최적값이 아니라 「이 정도 클릭은 모아야 배울 수 있다」는 학습 예산의 천장입니다. 광고 전환율을 다른 각도에서 살펴본 글로 검색광고 전환율 벤치마크가 있습니다.
두 번째는 네이버 키워드 단위 실적의 기간입니다. 같은 쿼리에서 기간만 바꿔 보니 캠페인 단위는 30일까지, 광고 그룹·키워드 단위는 약 3일까지만 온전했습니다. 54.7%라는 비용 비중은 같은 조회 안의 상대 비교라 방향은 맞지만, 절대 기간은 30일보다 짧습니다.
| 조회 기간 | 캠페인 노출 | 그룹 합계 노출 |
|---|---|---|
| 1일 | 17,636 | 17,636 (일치) |
| 3일 | 52,090 | 52,090 (일치) |
| 7일 | 89,042 | 65,688 (잘림) |
| 30일 | 93,406 | 65,688 (고정) |
세 번째, 구글 키워드 품질평가점수가 전부 0(데이터 없음)이었습니다. 입찰가만으로 순위를 얻을 수 있는지 아직 모릅니다. 노출이 다시 쌓이고 30일 뒤에 점수를 다시 조회하기로 했습니다. 네 번째, 네이버 7일 캠페인 노출 89,042회 중 그룹 합계는 65,688회라 나머지가 어느 키워드에서 나왔는지 확인하지 못했습니다.
다섯 번째는 사업 쪽 한계입니다. 홈페이지 제작, AI 개발, AI 마케팅처럼 AI 대행 성격의 키워드는 시장가가 천장의 3~12배라 검색광고에서는 사실상 빠졌습니다. 이 키워드로 다시 들어가려면 입찰가를 만지는 게 아니라 하루 예산을 올리는 결정을 해야 하고, 그러면 공식이 천장을 알아서 다시 계산합니다.
마지막으로 절차의 한계도 남겼습니다. 7월 27일 실반영은 사전 승인 없이 진행됐습니다. 지출을 줄이는 방향이라 되돌리지는 않았지만, 사후 승인을 받는 항목으로 따로 기록했습니다. 우리 회사의 광고 운영이나 입찰 구조를 같이 점검하고 싶다면 상담으로 연락 주세요.
