YouTube Data API 쿼터 초과를 피하는 방법 (700개 쇼츠 수집 사례)

  처음에는 단순히 API 몇 개 호출하면 끝날 줄 알았다.

UGREEN DXP4800PLUS NAS 위에서 유튜브 쇼츠 자동화 시스템을 구축하면서 YouTube Data API를 쓰기 시작했는데, 실제로 운영해보니 쿼터 관리가 더 큰 문제였다. YouTube Data API를 사용해 쇼츠 수집기나 트렌드 분석 시스템을 만들다 보면 쿼터(Quota) 부족 오류를 한 번쯤 겪게 된다. 하루 10,000유닛이면 사실상 무제한이라고 생각했는데, 글로벌 AI 키워드를 몇 개 추가하고 나서 하루도 지나지 않아 쿼터 부족 오류가 발생했다.

로그를 확인해보니 범인은 search.list였다. 같은 API라도 videos.list는 1유닛인데 search.list는 100유닛이다. 이 차이를 이해하기 전까지는 쿼터가 왜 사라지는지 전혀 감이 오지 않았다.

약 700개 영상, 4만 개 이상의 스냅샷을 수집하는 과정에서 부딪힌 쿼터 제한과 해결 방법을 정리한다.


YouTube Data API 기본 제한 사항

YouTube Data API v3는 무료로 제공되지만 일일 쿼터(Quota)가 존재한다.

기본 할당량: 하루 10,000 유닛

주요 API별 소비 유닛:

  • videos.list: 1 유닛
  • search.list: 100 유닛
  • channels.list: 1 유닛

search.listvideos.list보다 100배 비싸다. 처음에 이걸 몰라서 쿼터를 빠르게 소진했다.


실제로 겪은 문제들

문제 1: search.list 남용으로 쿼터 소진

초기 수집기는 이런 구조였다.

# 초기 구조 - 쿼터 낭비
search_results = search.list(q="쇼츠", type="video")  # 100 유닛
for video in search_results:
    detail = videos.list(id=video.id)  # 1 유닛씩

search.list를 매번 호출하니 하루 만에 쿼터가 바닥났다. 100건 검색하면 10,000유닛을 단번에 소진하는 구조였다.

videos.listchart=mostPopular 파라미터로 전환했다. 인기 영상 50개를 1유닛으로 가져올 수 있다.

# 개선된 구조 - 쿼터 절약
popular = videos.list(
    part="snippet,statistics,contentDetails",
    chart="mostPopular",
    regionCode="KR",
    maxResults=50
)  # 1 유닛으로 50개

문제 2: 수집은 되는데 AI/IT 콘텐츠가 없음

한국 급상승만 수집하니 약 500개 영상 중 AI_AUTOMATION 클러스터가 단 1개였다. 한국 유튜브 급상승은 드라마, 연예, 뉴스가 압도적이다.

글로벌 키워드 검색을 추가했다. 단, search.list는 쿼터 소모가 크므로 수집 주기를 조정했다.

# 글로벌 AI/IT 키워드 추가
AI_KEYWORDS = ["ChatGPT shorts", "Claude AI", "n8n automation"]
IT_KEYWORDS = ["tablet review shorts", "mini PC shorts", "NAS setup"]

ai_items = await collect_global_keywords(AI_KEYWORDS)
it_items = await collect_global_keywords(IT_KEYWORDS)

결과: AI_AUTOMATION 1개 → 61개, IT_DEVICE 0개 → 89개

문제 3: 스냅샷 수집과 성장률 계산

단순히 현재 조회수를 저장하는 것이 아니라 시간에 따른 변화량을 추적해야 했다. 처음에는 매번 전체 영상을 새로 수집했는데 이러면 쿼터가 부족했다.

기존 영상은 별도 배치로 갱신하는 방식으로 바꿨다.

async def refresh_existing_snapshots(session, limit=100):
    # 25분 이상 갱신되지 않은 영상 최대 100개 선택
    rows = session.execute("""
        SELECT video_id FROM videos
        WHERE last_updated < NOW() - INTERVAL '25 minutes'
        ORDER BY last_updated ASC
        LIMIT 100
    """)
    # 50개씩 배치로 videos.list 호출
    for batch in chunks(video_ids, 50):
        stats = videos.list(id=",".join(batch))

50개를 한 번에 조회하면 1유닛. 100개를 조회해도 2유닛이다.


API 쿼터를 아끼기 위해 수집 주기를 분리한 이유

가장 효과적이었던 방법은 수집 주기를 두 단계로 나누는 것이었다.

글로벌 키워드 수집은 search.list를 사용하기 때문에 쿼터 소모가 크다. 반면 기존 영상의 스냅샷 갱신은 videos.list만 쓰면 되므로 훨씬 저렴하다. 이 둘을 같은 주기로 돌리면 불필요한 쿼터 낭비가 생긴다.

# 30분마다 실행
# 매시 0~29분: 글로벌 키워드 수집 포함 (쿼터 소모 큼)
# 매시 30~59분: 기존 영상 스냅샷 갱신만 (쿼터 소모 적음)

from datetime import datetime
run_global = datetime.now().minute < 30

if run_global:
    ai_items = await collect_global_keywords(AI_KEYWORDS)
    it_items = await collect_global_keywords(IT_KEYWORDS)
else:
    ai_items = it_items = []
    print("[collector] 글로벌 수집 스킵 (쿼터 절약)")

글로벌 수집 추가 후 안정적으로 운영 중인 수집 현황


실제 운영 결과

현재 시스템은 UGREEN DXP4800PLUS NAS에서 30분 주기로 동작하고 있다.

  • 수집 영상: 약 700개
  • 저장 스냅샷: 4만 개 이상
  • API 사용량: 하루 약 4,000~5,000유닛
  • 사용률: 할당량의 약 40~50%
  • 수집 주기: 30분

초기에는 쿼터 부족 오류가 반복적으로 발생했지만, search.list 사용 빈도를 줄이고 수집 주기를 분리한 후에는 안정적으로 운영되고 있다.


현재 수집 구조 요약

30분마다 실행
Tier 0: 한국 급상승 50개 (1유닛)
Tier 0: 쇼츠 검색 50개 (100유닛)
Tier 1: 글로벌 AI/IT 키워드 (격번, 약 800유닛)
기존 영상 100개 스냅샷 갱신 (2유닛)
성장률 계산 → 클러스터 분류

하루 약 4,000~5,000유닛 소비. 10,000유닛 한도의 절반 이하로 안정적이다.


YouTube Data API 사용 시 핵심 정리

  • search.list 사용을 최소화한다 (100유닛)
  • videos.list + chart=mostPopular를 활용한다 (1유닛)
  • 배치 조회를 활용한다 (50개를 한 번에 = 1유닛)
  • 수집 주기를 분리해 불필요한 호출을 줄인다

관련 글

댓글

이 블로그의 인기 게시물

UGREEN DXP4800PLUS NAS로 유튜브 쇼츠 자동화 시스템 구축기 (Docker · FastAPI · PostgreSQL · Edge-TTS)

FastAPI app.mount 사용 후 API가 404가 되는 이유와 해결 방법