개인의 기록
  • 소개
  • 프로젝트
  • 글
  • 링크

© 2026 newgirok

← YouTube Shorts 자동화

데이터 갱신 — 폴링 제거와 Analytics 버그

2026년 7월 26일
webAnalyticsYouTube API

완료되거나 실패한 Job도 30초마다 계속 폴링하고 있었다. 조회수 갱신 때문에 넣어둔 건데, 굳이 그렇게 자주 두들길 필요가 없었다.

HomeClient/JobDetailPage — refetchInterval 정리

   refetchInterval: (query) => {
     const job = query.state.data;
     if (!job) return 2000;
-    if (job.status === 'COMPLETED' || job.status === 'FAILED') return 30000;
+    if (job.status === 'COMPLETED' || job.status === 'FAILED') return false;
     return 2000;
   },

대신 채널 페이지 마운트 시 10분마다 sync-videos를 한 번씩 호출해서 조회수·비공개·삭제 상태를 갱신하는 방식으로 바꿨다.

useEffect(() => {
  if (!activeChannelId) return;
  const timer = setInterval(() => {
    apiPost(`/channels/${activeChannelId}/sync-videos`, {}, userHeaders)
      .then(() => queryClient.invalidateQueries({ queryKey: ['jobs', activeChannelId] }))
      .catch(() => {});
  }, 10 * 60 * 1000);
  return () => clearInterval(timer);
}, [activeChannelId, queryClient]);

처리 중인(PENDING 등) Job은 여전히 2초 폴링 유지. 안 끝난 것만 자주 보고, 끝난 건 탭 포커스 시에만 자동 재조회하도록 정리했다.

Analytics API — ids 파라미터로 한나절 삽질

sync-videos를 자주 호출하게 되면서 Analytics 동기화가 계속 실패하고 있다는 걸 눈치챘다. ChannelAnalytics 테이블에 데이터가 안 쌓이고 있었다.

원인을 보니 ids: channel=={youtubeId} 형식이 문제였다. 이 형식은 CMS 환경 전용이라 일반 OAuth 토큰으로는 400 에러가 난다. 근데 이 에러가 .catch(warn)으로 조용히 무시되고 있어서 알아채기 어려웠다.

 const res = await ytAnalytics.reports.query({
-  ids: `channel==${youtubeId}`,
+  ids: 'channel==MINE',

channel==MINE으로 고쳤더니 이번엔 에러는 안 나는데 값이 전부 0이었다. MINE은 로그인된 Google 계정의 기본 채널 데이터를 반환하는데, 연결된 채널이 브랜드 계정이면 로그인 계정과 다르니까 항상 0이 나온 거다. 결국 원래대로 되돌렸다.

 const res = await ytAnalytics.reports.query({
-  ids: 'channel==MINE',
+  ids: `channel==${youtubeId}`,

400 에러가 나던 진짜 이유는 파라미터 형식이 아니라 YouTube Analytics API 자체가 아직 활성화 안 돼있었던 거였다. API를 활성화하고 나니 channel=={youtubeId} 형식이 맞는 방식이었다.

원인을 못 찾아서 중간에 응답에 에러를 임시로 노출시켜 디버깅했다.

log.info({ channelId, youtubeId, rowCount: rows.length, sampleRow: rows[0] ?? null }, 'Analytics API 응답');

정렬 방향도 하나 고쳤다. getAnalytics가 오래된 날짜부터 30개를 가져오고 있어서, 데이터가 30일 넘게 쌓이면 최신 데이터가 잘려나가는 문제가 있었다. desc로 최신 30일을 가져온 다음 화면에 표시할 땐 다시 reverse()로 시간순 정렬했다.

← 이전 글대시보드 UX — 업로드 한도 상향과 썸네일 플레이스홀더
다음 글 →웹 리팩터 — useYoutubeConnect 훅 분리