수집 파이프라인 (데이터)
AI팀 핸드오프 — 트렌드 데이터를 어떻게 수집하고 무엇을 저장하는지.
수집 파이프라인 — 수집 방식 & 저장 데이터 (AI팀 핸드오프)
대상: 수집된 트렌드 데이터를 분석·리포트에 활용할 AI팀. 요지: 유튜브 키워드 트렌드를 매일(24시간 주기) 수집해 PostgreSQL youtube_trend 테이블에 적재합니다. 수집·저장은 glowb-python-api(sns-crawler-python)가 담당합니다.
1. 무엇을 수집하나
분야(카테고리)별 키워드로 YouTube를 검색해 그 분야에서 지금 뜨는 영상을 수집합니다. 각 영상에는 분야·광고여부·쇼츠여부·조회수·속도(급상승 근사)가 붙습니다.
- 분야 슬롯:
BEAUTY · FASHION · TRAVEL(현재 3개 분야만 수집. IT·HEALTH는 필요 시 재추가) - 광고여부(ad_flag):
X= 분야 키워드만(일반 인기) /O= 분야 +협찬|공구(협찬·공동구매) - 길이(is_shorts):
true= 쇼츠(≤180초) /false= 일반영상 - → 분야마다 (광고 O/X) × (쇼츠/일반) 4버킷
2. 어떻게 수집하나 (방법)
YouTube Data API v3 search.list → videos.list 2단계.
- 분야 슬롯마다 검색 쿼리 2개 — 광고X = 분야 한글 복합어(예: BEAUTY
메이크업튜토리얼|화장법|겟레디윗미|...), 광고O =<분야앵커> 협찬|공구(예:뷰티 협찬|공구).|= OR. 단일/영문 단어는 글로벌 영상이 상위를 차지해 한글 복합어로 한국 콘텐츠만 남깁니다. - 각 쿼리를 길이별(
videoDuration=short|long)로 검색:order=viewCount,publishedAfter=최근 7일,regionCode=KR,relevanceLanguage=ko,maxResults=50. - videoId를
videos.list(전 part)로 보강 → 조회수·좋아요·댓글·길이·태그·토픽. - velocity = 조회수 ÷ 게시 후 경과일 → 수집 시점 급상승 근사치.
스케줄: glowb-server가 매일 02:00 KST(24시간 주기) Kafka(YOUTUBE_TREND_COLLECT)로 트리거 → POST /api/youtube/trend/collect → RQ 워커가 수집·적재. (플랫폼 간 동일 주기로 맞춤 — 인스타 API 비용 고려.) 재수집은 UK 기준 upsert(갱신)하며, 이때 직전 수집 대비 조회수 증가분을 view_delta에 롤링 기록(급상승 신호). 수집일이 바뀌면 새 행.
3. 저장 데이터 — PostgreSQL youtube_trend
한 행 = (수집일 × 지역 × 분야 × 광고여부 × 영상). 앱 시작 시 자동 생성.
| 컬럼 | 타입 | 의미 |
|---|---|---|
surrogate_key | BIGINT PK | 자동증가 |
collected_date | DATE | 수집일(KST) |
region | VARCHAR | 지역(KR) |
keyword_slot | VARCHAR | 분야(BEAUTY/FASHION/TRAVEL) |
source | VARCHAR | 'SEARCH' |
ad_flag | VARCHAR | 'O'(협찬/공구) / 'X'(일반) |
is_shorts | BOOL | 쇼츠(≤180초) |
rank | INT | 검색 순위(조회수순) |
video_id | VARCHAR | 영상 ID |
title / description | TEXT | 제목·설명 |
channel_id / channel_title | VARCHAR | 채널 |
category_id | VARCHAR | 영상 자체 categoryId(검색 분야와 별개) |
published_at | TIMESTAMPTZ | 게시일 |
view_count / like_count / comment_count | BIGINT | 지표 |
duration_sec | INT | 길이(초) |
velocity | FLOAT | views/day (급상승 근사) |
view_delta | BIGINT | 직전 수집(≈하루 전) 대비 조회수 증가분(급상승 신호). 첫 수집 null |
prev_view_count | BIGINT | 직전 스냅샷 조회수 |
snapshot_count | INT | 해당 일자 스냅샷 갱신 횟수 |
last_snapshot_at | TIMESTAMPTZ | 마지막 수집 갱신 시각 |
default_audio_language | VARCHAR | 음성 언어(예: ko). ⚠️음악 아님 |
has_paid_placement | BOOL | 공식 "유료광고 포함" 플래그(참고용, 한국 콘텐츠엔 거의 0) |
made_for_kids | BOOL | 아동용 |
tags / topic_categories | JSONB | 태그 / 위키 토픽(주제) |
raw | JSONB | videos.list 원본(미파싱 필드 보존) |
sound_title / sound_artist | TEXT/VARCHAR | 쇼츠 음원 곡명·아티스트(외부 API YT-API 보강, 쇼츠만·오리지널이면 null) |
sound_source_video_id / sound_token | VARCHAR/TEXT | 사운드 원본 영상 id · 채택수 조회 토큰 |
sound_checked_at | TIMESTAMPTZ | 사운드 조회 시각(영상당 1회, 재조회 스킵용) |
created_at / updated_at | TIMESTAMPTZ | 적재 시각 |
유니크 키: (collected_date, region, keyword_slot, ad_flag, video_id).
4. 조회 API (서빙 = glowb-server)
FE-facing 조회는 glowb-server가 PostgreSQL을 직접 읽어 서빙한다(팀 원칙: 서빙은 백엔드). records(테이블) · report(4버킷) · stats(요약) · collect(수동 트리거). 상세는 이 섹션의 각 문서 참고.
파이썬(sns-crawler-python)에도 동일 조회 EP가 있으나 그건 AI팀 내부용이며, FE는 glowb-server를 호출한다.
5. 한계 (반드시 인지)
- 음원 = 쇼츠만: 공식 YouTube Data API는 음원을 안 줌. 쇼츠 음원은 외부 API(RapidAPI YT-API)로 보강(
sound_*). 🔴단 롱폼 영상·오리지널 사운드는 식별 불가(사운드 어트리뷰션은 Shorts가 라이브러리 곡을 쓸 때만 존재, 그 외엔 자기참조 →sound=null). 음원 조회는 영상당 1회(재수집해도 재호출 안 함). - 급상승 신호: 이제
view_delta(직전 수집 대비 조회수 증가분)가 실측 급상승 신호.velocity(views/day)는 게시 후 평균 근사치라 보조. - 보관 제한: ToS상 원본 30일 초과 보관 금지.
- 분야 3개: 현재 BEAUTY/FASHION/TRAVEL만 수집(IT·HEALTH 제외).
- 글로벌 누수 주의: 키워드 변경 시 한글 복합어로(단일/영문 단어는 글로벌 유입). 검증 = 제목 한글 비율.
6. 활용 힌트
- "지금 뜨는 분야별 쇼츠" =
records?slot=BEAUTY&is_shorts=true&sort=velocity - "협찬(광고) 트렌드" =
ad_flag=O필터 (오리지널 사운드 협찬은 곡명 없음) - 급상승 랭킹 =
view_delta내림차순(직전 수집 대비 조회수 증가분). 또는 여러 날 누적 Δ로 자체 계산 - "지금 뜨는 사운드" = 쇼츠
sound_title빈도 집계(오리지널 제외) - 내용(후킹·특징) 분석 =
video_url을 Gemini에 직접 입력(공개 영상, URL 접근 가능) - 주제 클러스터링 =
topic_categories(위키 토픽) +category_id