Skip to main content

통합 안 된 매체 비용도 에어브릿지 대시보드에 — Self-Serve Cost Upload + 클로드 코드 자동화 실전 (3/3)

· By Simpson Gyusup Sim · 16 min read

📝 이 글은 해당 세션 전에 사전 준비 & 프리모템(premortem)을 하면서 작성되었습니다.

본 글은 3편 시리즈의 3편입니다. 1편: 클로드 코드 + 에어브릿지 MCP × API 자동화 청사진 · 2편: 클로드 코드로 OG 이미지 만들고, 에어브릿지 API로 트래킹 링크 N개 발급하기

TL;DR

  • 인플루언서 마케팅·자체 SMS·자체 메일·오프라인 행사 같은 공식 통합이 없는 매체의 비용은 마케터가 매주 엑셀에서 따로 관리하다가 ROAS 계산할 때마다 "통합 비용"을 손으로 합칩니다.
  • 에어브릿지의 Self-Serve Cost Upload API를 쓰면 CSV 한 번으로 비용·노출·클릭이 대시보드의 Cost (Channel)·Impressions (Channel)·Clicks (Channel) 메트릭에 그대로 녹습니다. 그 다음부터는 통합 ROAS가 자동입니다.
  • 이걸 클로드 코드(Claude Code) 에이전트 + cron으로 매일 새벽 돌리면, 마케터는 Google Sheet에 비용을 입력만 하면 됩니다. 나머지는 기계가 처리합니다.
  • 단, 공식 통합되어 있는 매체(예: 네이버 검색광고, Meta, Google Ads, TikTok 등)는 self-serve upload 대상이 아닙니다. 에어브릿지 정책상 차단됩니다. 가이드의 schema는 비통합 매체 시연·구현 참고용입니다.
📤 이 글 한 번에 공유하기클로드 코드 + 에어브릿지 REST API + GPT image로 즉석 발급한 트래킹 링크입니다. 채널 blog_share, 캠페인 airbridge-self-serve-cost-upload-claude-code-automation_202604_blog_share, OG 이미지는 GPT Image 2 (high, 1536×1024). 클릭은 에어브릿지 actuals 리포트에 그대로 집계됩니다.
통합 안 된 매체 비용도 에어브릿지 대시보드에 — Self-Serve Cost Upload + 클로드 코드 자동화 실전
인플루언서·자체 SMS·자체 메일·오프라인 같은 비통합 매체 비용도 시트→CSV→에어브릿지 Self-Serve Upload→MCP 검증으로 매일 새벽 자동 동기화하는 실전 파이프라인.

1. 고질병을 다시 본다

1편 매트릭스에서 짚은 고질병 5(비용·ROAS 통합)와 고질병 1(리포트 빌드·해석)이 만나는 지점입니다.

마케터는 이미 다음 두 가지를 매주 합니다. - 통합된 매체 (Meta·Google·TikTok 등)는 에어브릿지에서 자동 집계 → 대시보드 보고 - 비통합 매체 (인플루언서·자체 SMS·자체 메일·오프라인)는 별도 시트 에서 손으로 합산 → 슬랙·노션 보고

문제는 마지막에 합칠 때. 채널 단위 ROAS, 매체 믹스 기여도, ROI 등을 한 화면에서 보려면 둘이 같은 단위로 들어가 있어야 합니다. 매주 한 명이 1~3시간씩 합치는 일에 쓰입니다. 통합 매체와 비통합 매체를 같은 단위로 합치고 나면, 그 다음에 증분(Incremental) 분석이나 iROAS 비교 같은 한 단계 위 분석으로 넘어갈 수 있습니다.

해결의 핵심은 두 줄기를 같은 집결지로 모으는 일. 에어브릿지 대시보드가 그 집결지가 됩니다.

2. 자동화 흐름 한눈에

시트→CSV→multipart 업로드→status polling→대시보드 검증으로 이어지는 비통합 매체 비용 ingestion 파이프라인
[ 마케터가 시트에 비용 입력 ]
   - Google Sheet, Notion DB, Airtable 어느 거든
   - 컬럼: date, channel, currency, campaign, impressions, clicks, cost, ad_group(선택)
   │
   ▼
[ Cron 매일 06:00 KST ]
   │
   ▼
[ 에이전트 — Sheet → CSV 변환 ]
   - 어제까지의 데이터만
   - 컨벤션·금지어·타입 검증
   - 신규 채널 발견 시 사람 알림
   │
   ▼
[ 에어브릿지 REST API ] POST /self-serve-data/v1/ad-spend/requests
   - multipart/form-data로 CSV 업로드
   - request_id 반환
   │
   ▼
[ 에이전트 — Status Polling ]
   - GET /self-serve-data/v1/ad-spend/requests/{request_id}
   - uploaded → validated → ingested → succeeded
   - failed 시 reason 분석 → 사람 알림
   │
   ▼
[ 에어브릿지 MCP ] get_actuals_report로 검증
   - 어제 비용 (Cost (Channel)) 정상 집계 확인
   - anomaly (전일 대비 ±N%) 감지 시 사람 알림
   │
   ▼
[ 슬랙 보고 ]
   - 어제 비통합 매체 비용 합계
   - 통합 매체와 합산한 매체 믹스 (가시성)
   - anomaly 있는 매체 강조

3. 1단계 — Sheet 스키마 설계

에어브릿지의 Self-Serve Cost Upload는 다음 컬럼을 받습니다 (필수와 선택).

컬럼 타입 필수 설명
date string YYYY-MM-DD 비용 발생일. 앱 타임존 기준. 미래 날짜 불가
channel string 매체 이름. 공식 통합된 채널명은 사용 불가. 영문 소문자·언더스코어 권장
currency string ISO 4217 3자리 대문자. e.g. KRW, USD
campaign string 캠페인명. 컨벤션 적용
impressions int 노출. 콤마 사용 금지
clicks int 클릭. 콤마 사용 금지
cost float 비용. 콤마 사용 금지
ad_group, ad_creative, term, country, os_name string 선택 구체화 시 powerful

데이터의 식별 키(date, channel, campaign) 3종 조합. 같은 키로 두 번 업로드하면 마지막 업로드가 덮어씁니다. 즉 수정도 곧 재업로드. 이 점이 자동화 설계에 큰 영향을 줍니다 — idempotent하게 매일 같은 슬라이딩 윈도우(예: 어제 1일치 또는 어제까지 7일치)를 다시 올려도 안전합니다.

3-1. 시트 권장 구조 (예시)

date channel currency campaign impressions clicks cost ad_group
2026-04-28 influencer_youtube KRW spring_2026_megainflu 120000 4500 3500000 yt_megainflu
2026-04-28 influencer_instagram KRW spring_2026_microinflu 85000 3100 1800000 ig_microinflu
2026-04-28 internal_sms KRW spring_2026_loyal_sms 0 12500 750000 sms_loyal
2026-04-28 offline_event KRW spring_2026_seoulmeetup 0 0 5000000 offline_seoul
(가상 데이터 명시) 위 표의 모든 수치는 시연용 가상값 입니다.

channel 이름 컨벤션은 다음 패턴을 권장합니다. - influencer_{platform} — 인플루언서 마케팅 - internal_{channel} — 자사 보유 채널 (sms, email, push, kakao_msg 등) - offline_{type} — 오프라인 (event, ooh, partnership 등) - partner_{name} — 제휴/공동 마케팅

offline_event처럼 노출·클릭이 무의미한 경우 0 입력. 비용만 집계됩니다. 그래도 cost는 반드시 양수로.

4. 2단계 — Sheet → CSV 변환 (LLM 에이전트의 사전 검증)

LLM 에이전트가 시트를 읽고 CSV로 직렬화하기 전에 다음 검증을 합니다.

# 의사 코드 — 실제 환경에서는 시트 SDK + Anthropic SDK 등 결합
def validate_rows(rows):
    integrated_channels = load_integrated_channels()  # 에어브릿지 공식 통합 채널 목록 (캐시)
    seen_keys = set()
    errors = []

    for r in rows:
        key = (r.date, r.channel, r.campaign)

        # 중복 키
        if key in seen_keys:
            errors.append(("DUP_KEY", r))
        seen_keys.add(key)

        # 미래 날짜
        if r.date > today_in_app_tz():
            errors.append(("FUTURE_DATE", r))

        # 통합된 채널 사용 시도
        if r.channel in integrated_channels:
            errors.append(("INTEGRATED_CHANNEL", r))

        # 통화 코드
        if r.currency not in ISO_4217:
            errors.append(("BAD_CURRENCY", r))

        # 음수 또는 비숫자
        if r.cost < 0 or not is_int(r.impressions) or not is_int(r.clicks):
            errors.append(("BAD_NUMBER", r))

    return errors

4-1. Human-in-the-loop 지점

검증 결과가 경고(warning)와 오류(error)로 나뉩니다.

  • 오류 (e.g. 통합 채널 사용 시도, 미래 날짜, 음수 비용): 업로드 즉시 차단 → 슬랙에 마케터 멘션 → 사람이 시트 수정 후 다음 사이클에서 재시도
  • 경고 (e.g. 전일 대비 비용 ±50% 이상 변동 같은 anomaly): 업로드는 진행하되 슬랙에 알림 → 사람이 맞다고 confirm 또는 수정 결정
  • 신규 채널 발견 (e.g. 어제까지 없던 influencer_threads가 처음 등장): 업로드 진행하지만 슬랙에 명시적 멘션 → 사람 승인. 첫 등장 채널은 컨벤션·정책 적용 대상

이 3단계 분기가 마케팅 자동화에서 가장 자주 무너지는 지점입니다. 모든 걸 자동으로 흘러보내면 사람이 모르는 사이에 잘못된 데이터가 누적됩니다. 모든 걸 사람 승인 대기로 두면 자동화의 효용이 사라집니다. 위 3분기가 우리가 권하는 균형점입니다.

💡 암묵지 → 명시지 한 번 더 — 위 경고 임계값 (예: ±50%), 오류 차단 룰, 신규 채널 정책은 모두 우리 회사 마케터의 머릿속에서 끌어낸 결과 여야 합니다. 1편에서 정리한 Cognitive Task Analysis 3주 인터뷰 트랙 으로 임계값을 숫자로 박아두면, 같은 ±50% 이상 변동이라도 시즌 정상진짜 anomaly를 구분합니다. 그렇지 않으면 에이전트의 권고는 일반론이고, 마케터는 다시 검토 합니다.

5. 3단계 — REST API multipart upload

검증 통과 후 CSV로 직렬화하고 multipart로 업로드합니다.

import FormData from "form-data";
import fetch from "node-fetch";

async function uploadAdSpend(csvBuffer, apiToken) {
  const form = new FormData();
  form.append("file", csvBuffer, {
    filename: `ad_spend_${dayjs().format("YYYYMMDD")}.csv`,
    contentType: "text/csv"
  });

  const res = await fetch(
    "https://api.airbridge.io/self-serve-data/v1/ad-spend/requests",
    {
      method: "POST",
      headers: {
        "Authorization": `Bearer ${apiToken}`,
        ...form.getHeaders()
      },
      body: form
    }
  );

  if (!res.ok) {
    const err = await res.text();
    throw new Error(`Upload failed: ${res.status} ${err}`);
  }
  return await res.json();  // { request_id, ... }
}
⚠️ Self-Serve API는 Owner / In-house Marketer 권한의 토큰만 받습니다. 대행사·하위 권한 토큰은 거부됩니다. CI 환경에는 Owner 전용 봇 계정 토큰을 분리해 두는 것을 권합니다.

1회 요청당 최대 10,000행 / 1MB. 큰 시트는 자동으로 chunk 분할이 필요합니다.

6. 4단계 — Status Polling

Self-Serve 업로드는 비동기. request_id를 받은 뒤 다음 상태로 이동합니다.

상태 설명 자동화 분기
uploaded 서버에 파일 업로드 완료 계속 polling
validated 파일 포맷 검증 완료 계속 polling
ingested DB에 ingest 완료 계속 polling
succeeded 리포트에서 조회 가능 (최대 10분 소요) 다음 단계로
failed 처리 실패. reason 필드 확인 후 사람 알림 LLM이 reason 해석 후 슬랙 보고
async function pollStatus(requestId, apiToken, maxWaitMs = 15 * 60 * 1000) {
  const start = Date.now();
  while (Date.now() - start < maxWaitMs) {
    const res = await fetch(
      `https://api.airbridge.io/self-serve-data/v1/ad-spend/requests/${requestId}`,
      { headers: { "Authorization": `Bearer ${apiToken}` } }
    );
    const json = await res.json();
    const status = json.task?.status;
    if (status === "succeeded") return json;
    if (status === "failed") throw new Error(`Failed: ${json.reason}`);
    await sleep(15_000);  // 15초 간격
  }
  throw new Error("Timeout polling status");
}

7. 5단계 — MCP로 actuals 리포트 검증

업로드 성공 후 그날 cost가 실제로 dashboard에 반영되었는지 MCP로 즉시 검증합니다.

자연어로 호출 시:

"demokr 앱의 어제 날짜, channel별 Cost (Channel)·Impressions (Channel)·Clicks (Channel)을 표로. 어제 self-serve로 올린 4개 채널 (influencer_youtube, influencer_instagram, internal_sms, offline_event) 모두 0이 아닌 값을 가지는지 검증."

MCP는 metadata→report 체인으로 다음을 호출합니다. 1. get_actuals_metrics_metadatacost_channel, clicks_channel, impressions_channel 키 확인 2. get_actuals_group_by_metadatachannel 키 확인 3. get_actuals_report — 어제 날짜, 4개 채널 필터, 위 메트릭 호출

응답을 받아 LLM이 다음을 판단합니다.

  • 4개 채널 모두 cost > 0인가? (offline은 cost만 양수, 나머지 0 허용)
  • 어제 시트에 입력한 합계와 일치하는가? (채널별 cost 합산 비교, ±1% 허용 오차)
  • 어제 대비 ±N% anomaly 채널 있는가?

판단 결과가 모두 정상이면 슬랙 보고. 하나라도 어긋나면 사람 멘션.

8. 결과 — 30일치 자동 동기화 시연 (가상)

워크샵 데모용 샌드박스에 30일치 가상 데이터를 hourly로 흘려넣고 위 자동화를 돌려보았습니다.

  • 시트 입력 (가상 데이터):
  • 4개 채널 × 30일 = 120행
  • influencer_youtube: 일평균 비용 350만원, 노출 12만, 클릭 4.5천
  • influencer_instagram: 일평균 180만원, 노출 8.5만, 클릭 3.1천
  • internal_sms: 일평균 75만원, 노출 0, 클릭 1.25만
  • offline_event: 30일 중 4일만 발생 (이벤트일), 회당 500만원
  • 자동 업로드 사이클:
  • 매일 06:00 KST 트리거
  • 평균 처리 시간 (validation → upload → polling → MCP 검증 → 슬랙): 3분 40초
  • 사람 개입: 30일 중 4회 (신규 채널 등록 1회, anomaly 감지 3회)

결과 확인 — MCP 자연어 질의:

"4월 한 달간 비통합 매체 합산 비용·노출·클릭을 표로. 통합 매체 (Meta·Google·TikTok)와 합쳤을 때 매체 믹스(%)를 cost 기준으로."
매체 그룹 합산 비용 비중
통합 매체 (Meta·Google·TikTok) 290억원 96.4%
비통합 매체 (인플루언서·SMS·오프라인) 11억원 3.6%
(가상 데이터 명시) 모든 수치는 시연용 샌드박스 데이터입니다.

9. 도입 시 주의사항

  1. 공식 통합 채널은 self-serve upload 대상 아님 — 네이버 검색광고, Meta, Google Ads, TikTok 등은 에어브릿지가 자체 OAuth/공식 API로 연동을 제공합니다. self-serve로 올리려 하면 거부됩니다. 통합 가능한 매체부터 통합하고, 그 외만 self-serve로.
  2. idempotent 설계 — 같은 (date, channel, campaign) 키는 마지막 upload가 덮어씁니다. 매일 어제 1일치만 올리지 말고 최근 7일을 매번 다시 올리는 패턴이 안전합니다 (지연 보정).
  3. 데이터 삭제는 영(0) 업로드 — 잘못 올린 데이터를 빼려면 같은 키로 impressions=0, clicks=0, cost=0을 다시 올립니다. 이게 self-serve의 삭제 메커니즘입니다.
  4. channel 이름 일관성 — 한 번 정한 채널명은 절대 바꾸지 마세요. 바꾸는 순간 이전 데이터가 다른 채널처럼 집계됩니다. 변경이 필요하다면 기존 채널 영(0) 업로드 → 새 채널명으로 re-upload 한 사이클이 필요합니다.
  5. OS 이름은 정확히 Android / iOS — 케이스 센서티브. 잘못 쓰면 행이 분리됩니다.

10. Routines + Managed Agents 패턴 정리

중앙의 시계를 둘러싼 4개 에이전트(기어·터미널·스택)가 정기 트리거 따라 오케스트레이션되는 컨셉

이 흐름의 자동화 단계마다 적합한 패턴이 다릅니다 — 1편 §4에서 정리한 4가지 패턴 중 RoutinesManaged Agents 가 핵심입니다. 각각의 운영 모델은 Anthropic Claude Code RoutinesAnthropic Managed Agents 개요를 참고하세요. 다음 표는 본 파이프라인에 두 패턴을 어떻게 배치하는지 정리한 것입니다.

단계 패턴 책임자
매일 06:00 트리거 Routines (cron) 시스템
Sheet → CSV 직렬화 LLM 에이전트 (도구 호출) 시스템
컨벤션·금지어·타입 검증 LLM 에이전트 + 룰 엔진 시스템
신규 채널 등록 Managed Agent → 사람 승인 사람
Anomaly 감지 LLM 에이전트 → 사람 알림 사람
API multipart upload API 호출 시스템
Status polling API 호출 시스템
MCP actuals 검증 MCP 호출 시스템
정기 슬랙 보고 LLM 에이전트 시스템
정책·룰 변경 PR 리뷰 사람

핵심은 데이터·정책의 변화는 사람의 손을 거친다. 반복 작업은 기계의 손으로. 이게 1편에서 정리한 5가지 human-in-the-loop 원칙의 실전 적용입니다.

💡 회사 컨텍스트 주입의 실전 효과 — 1편 §5에서 정리한 회사별 컨텍스트의 4축사업 캘린더사내 의사결정 룰이 이 파이프라인의 anomaly 감지에 직결됩니다. 화장품 D2C라면 "올영 메가세일 주간(매달 셋째주)에는 SMS·메일 비용이 평소의 2~3배까지 정상" 이라는 룰을, 게임 D2C라면 "신규 패치 launch week에는 인플루언서 비용 스파이크 정상" 이라는 룰을 에이전트의 RAG 코퍼스에 박아두면, 같은 ±50% 비용 변동이라도 시즌 정상진짜 anomaly를 구분합니다. 이게 비싼 검색엔진 단계에서 진짜 자동화 단계로 넘어가는 분기점입니다.

11. CTA

비통합 매체가 매주 골치라면, 우리 팀의 그로스 스프린트에서 위 흐름을 1주 PoC + 2주 운영 안정화로 깔아드릴 수 있습니다. 첫 1주 안에 어제 비통합 매체 비용이 슬랙으로 자동 보고되는 상태를 만드는 게 목표입니다. 문의는 retn.kr/contact.

마치며

마케팅 자동화에서 완전 자동화는 환상입니다. 진짜 가치는 사람이 의사결정에 시간 쓸 수 있게 만드는 일 입니다. 에어브릿지의 Self-Serve API + MCP + LLM 에이전트 + cron 4가지를 묶으면, 마케터는 시트에 비용을 입력하고 anomaly를 confirm만 하면 됩니다. 나머지 일은 그 사이에 끝납니다.

3편 시리즈를 여기까지 읽어주셔서 감사합니다. 1편 클로드 코드 + 에어브릿지 MCP × API 자동화 청사진 과 2편 블로그 1편을 채널별 트래킹 링크 N개로 도 함께 봐주시면 청사진과 실전이 연결됩니다.

📚 더 읽어보기


참고 - Airbridge, Self-Serve Data Upload (REST): https://help.airbridge.io/en/references/self-serve-data.md - Airbridge, 네이버 검색 광고 (공식 통합 가이드, schema 참고용): https://help.airbridge.io/ko/guides/naver-sa - Airbridge, Actuals Report (REST): https://help.airbridge.io/en/references/actuals-report.md

About the author

Simpson Gyusup Sim
Updated on 2026년 5월 29일
무엇이든 물어보세요! 👋
15분 미팅 예약