pile·
DB / 데이터·매드업매드업·

어서 와, 광고 데이터 수집은 처음이지? (feat. kraken)

매드업이 광고 매체 API 의 호출 제약("10초에 1회") 아래에서 수백 개 광고주 데이터를 제때 모으려고 만든 수집 플랫폼 '크라켄' 이야기다. 제약이 왜 골치인지를 단계별로 쌓아 보인 뒤, Redis Stream 기반의 병렬 수집 구조와 아키텍처를 공개한다.

핵심 포인트
  • 매체 사이트에서 사람이 data export 를 클릭하는 방식은 시간이 들 뿐 아니라 필터 조건 실수로 데이터가 달라질 위험이 있다.
  • API 제약은 rate limit·call limit 형태로 명세에 있지만, "짧은 시간에 여러 요청 불가" 처럼 애매하거나 조치에 필요한 정보를 안 주는 경우도 많다.
  • 진짜 문제는 시간 제약과 페이지네이션이 겹칠 때다. 1,000개 데이터를 100개씩 받으면 10회 호출이 필요하고, 10초 간격이면 그것만 1분 40초다.
  • 한 광고주에 60분이 걸리면 10개 광고주는 산술적으로 600분이다. 광고주가 기하급수적으로 느는 상황에서 순차 수집은 성립하지 않았다.
  • 결과적으로 해당 매체에서 평소 5~10% 발생하던 수집 에러 비율이 0% 가 됐다.
상세 정리
  • 동시 요청이 왜 필요한지부터 설명한다. 광고주가 넷이어도 각자 운영하는 캠페인이 여러 개면 받아야 할 리포트는 10개가 되고, 이런 식으로 500개까지 늘어난다.
  • 여기에 전환 데이터처럼 값이 나중에 확정되는 특성 때문에 당일분만이 아니라 과거 데이터도 다시 수집해야 한다.
  • 단순 throttling 이 답이 아닌 이유: 시간 간격을 두는 것은 좋은 아이디어지만, 페이지네이션 때문에 "다음 페이지" 를 넘기는 데도 10초가 필요하다.
  • 게다가 리포트 종류마다 제약이 다르다. 캠페인 리포트와 광고그룹 리포트의 호출 간격과 1회 수신량(20개)이 각각 다르며, 매체 업데이트로 언제든 바뀔 수 있다.
  • 크라켄의 발상: API 종류마다 독립적으로 계속 호출하는 병렬 구조다. 크라켄의 다리 하나가 API 종류 하나이고 빨판 간격이 호출 제약 시간에 대응한다. 수집한 정보는 나중에 한 번에 취합하므로 광고 계정 종류는 중요하지 않다.
  • 다리 증설이 곧 확장이다. 새 API 수집이 필요하면 stream key 를 추가로 정의한다. endpoint·query param 이 달라 구현은 필요하지만 확장을 염두에 두고 설계해 붙이기 어렵지 않다.
  • 인프라: 전부 AWS ECS 로 구성했고, 매체와 직접 통신해야 해서 인스턴스를 Public subnet 에 둔다. Private subnet + NAT 는 data transfer 비용을 감수해야 한다.
  • 컴포넌트는 셋이다. 호출 제약을 조절하는 것, 수집을 담당하는 것, 무중단을 위한 checker 다. 모두 파이썬이며 GitHub Actions 로 자동 배포한다.
  • 수집 대상 광고주 정보는 RDS 에서 관리하고, Event Driven 방식으로 Kraken stream 을 통해 요청이 들어온다.
  • 기술 선택 근거: Kafka 도 후보였지만 당장 필요한 것은 정상 수집 여부를 알리는 message ack 뿐이라 AWS ElastiCache for Redis 의 stream 타입으로 충분했다.
  • Redis Stream 의 상태 흐름을 짚는다. 들어온 메시지는 상태가 없다가, 꺼내지면 pending, 처리가 끝나면 ack 로 마킹되며, 이후 삭제할 수 있다. 이 상태 기록으로 수집 성공을 판단한다.
  • 실패 복구: 매체 서버 오류 등으로 중간에 문제가 나면 ack 가 처리되지 않으므로, 이를 감시하던 checker 애플리케이션이 지정 횟수만큼 재시도한다.
  • 수집이 끝나면 정보는 상위 플랫폼인 프리즘(DMP)의 stream 으로 전달된다.
  • 남은 난제를 마지막에 밝힌다. A 리포트를 받으려면 B 가, B 를 받으려면 C 가 필요한 경우가 있어 다리들이 완전히 독립적이지 않으며, 크라켄의 핵심 기술은 사실 그 인과관계 처리에 있다.
  • 글의 수치는 이해를 돕기 위해 각색됐음을 밝힌다(실제로는 캠페인 리포트가 5개씩·5초에 1회).
왜 읽나외부 API 의 rate limit 때문에 수집 파이프라인이 병목인 데이터 엔지니어에게, 제약을 우회하지 않고 구조로 흡수하는 설계를 보여준다.
매드업
매드업 블로그
원문은 여기서 이어서 읽을 수 있어요
원문 읽기
읽음 (0)

이 글과 비슷한

  1. DB / 데이터·여기어때 (GC컴퍼니)여기어때 (GC컴퍼니)·

    분석가가 직접 만든 마케팅 자동화 시스템 — 오디언스 빌더 제작기

    여기어때 데이터 분석팀(UB팀)이 개발 경험 없이 AI 에이전트 바이브 코딩으로 마케팅 자동화 시스템 '오디언스 빌더'를 구축한 과정이다. SQL 없이 UI에서 타겟 조건을 설정하면 BigQuery에서 수천만 행 대상자를 추출해 Kafka·S3를 통해 마케팅 도구로 전달하는 파이프라인을 직접 만들어, 캠페인 준비 시간을 2~3일에서 10분으로 단축했다.

    요약 이어보기
    #data-pipeline#kafka#postgres+2
  2. DB / 데이터·vercel-blogVercel Blog·

    모든 Vercel 빌드를 지탱하는 데이터베이스 마이그레이션 이야기

    Vercel이 빌드 웜 풀(warm pool) 상태 데이터를 Redis에서 DynamoDB로 마이그레이션한 과정을 다룬다. 빌드 풀의 청구 매핑 데이터가 Redis 장애 시 복구 불가능하다는 구조적 위험이 이주를 결정한 핵심 이유였고, 24/7 프로덕션 트래픽 속에서 다운타임 없이 5단계 점진적 전환을 완료했다.

    요약 이어보기
    #database-migration#zero-downtime#redis+2
  3. DB / 데이터·channel-talk채널톡·

    DynamoDB 핫 파티션을 해결하는 3가지 방법 (3): 조회를 인덱스 테이블로 옮기기

    채널톡이 DynamoDB 핫 파티션을 해결하려 GSI를 별도 인덱스 테이블로 떼어낸 연재의 마지막 편으로, 조회 경로를 GSI에서 인덱스 테이블로 옮긴 과정을 다룬다. 2편에서 쓰기 파이프라인이 완성돼 WriteThrottleEvents가 월 110만 회에서 0회가 됐지만, 조회 코드가 여전히 GSI를 읽고 있어 GSI를 지울 수 없었다. GSI가 읽기에서 대신해주던 키 해석·정확 일치·삭제 필터·페이지 채우기를 사내 공통 라이브러리의 조회 규칙으로 흡수해, 호출부는 GSI든 인덱스 테이블이든 같은 코드를 쓰게 만들었다.

    요약 이어보기
    #migration#dynamodb#hot-partition+5