React Query 폴링: 작업이 끝나면 refetchInterval 멈추기

React Query의 refetchInterval로 영상 Job을 폴링하세요. 백엔드를 호출하고, API가 제안하는 간격만큼 기다리다가, Job이 종료되면 false를 반환하면 됩니다.

읽는 시간 5분Sume
전체 글

React Query(TanStack Query)로 폴링하려면 useQuery에 refetchInterval을 설정하세요. 값은 밀리초 단위 숫자, 쿼리를 받아 다음 대기 시간을 반환하는 함수, 또는 폴링을 멈추는 false입니다. AI 영상 Job이라면 Job이 종료 상태가 되는 즉시 false를 반환하고 그 전에는 API가 제안하는 간격만큼 기다리며, queryFn은 영상 API가 아니라 여러분의 백엔드를 가리키게 하세요. API 키는 서버에 있어야 하기 때문입니다.

TanStack 관련 내용은 폴링 가이드, UseQueryOptions 레퍼런스, 중요한 기본값 문서에서, Sume 관련 내용은 Job과 결과 (영문), 인증, Sume API 레퍼런스에서 가져왔습니다. 모두 2026-09-27에 확인했습니다. Sume에는 React 패키지가 없습니다. 브라우저는 여러분의 백엔드를 호출하고, 백엔드가 HTTPS로 Sume를 호출합니다.

영상 API 대신 왜 내 백엔드를 폴링하나요?

키를 브라우저로 보낼 수 없기 때문입니다. Sume 문서는 브라우저와 모바일 클라이언트가 API 키를 붙여 주는 백엔드를 호출해야 하며, 키는 프론트엔드 JavaScript나 모바일 앱에 절대 두면 안 된다고 안내합니다. 그렇게 하지 않으면 어떻게 되는지는 브라우저에서 Sume API 호출 시 CORS 오류에서 다룹니다. 여러분의 상태 라우트는 요청을 검증하고 로그인한 사용자가 그 Job의 소유자인지 확인한 뒤, 키로 GET /v1/jobs/{id}/status를 읽고 페이로드의 data 객체를 반환합니다. POST /v1/videos로 시작한 Job도 여기서 읽을 수 있습니다.

Job이 끝나면 폴링을 어떻게 멈추나요?

간격 함수가 묻는 두 가지 질문에 상태 페이로드가 모두 답합니다. terminal은 멈출지 여부를, next_poll_after_seconds는 얼마나 기다릴지를 알려 줍니다. 페이로드의 나머지는 영상 생성 Job 상태 API 폴링하기에서 다룹니다. TanStack의 폴링 가이드도 작업을 폴링할 때 같은 형태를 씁니다. false를 반환하면 간격 타이머가 해제되고, 나중에 함수가 다시 숫자를 반환하면 폴링이 저절로 재개됩니다.

TanStack의 폴링, UseQueryOptions, 중요한 기본값 문서와 Sume API 레퍼런스의 Job 상태 스키마 기준, 2026-09-27 확인.
옵션 또는 필드출처역할
refetchIntervalTanStack Query밀리초 또는 쿼리를 받는 함수. false면 폴링 중지. 기본값 false
refetchIntervalInBackgroundTanStack Query기본값 false. 탭이 백그라운드에 있는 동안 폴링 일시 중지
retryTanStack Query실패한 쿼리는 기본적으로 클라이언트에서 지수 백오프로 3회 재시도
terminalSume Job 상태Job이 완료, 실패, 취소 중 하나로 끝나 폴링을 멈춰도 될 때 true
next_poll_after_secondsSume Job 상태다음 폴링 전 권장 최소 대기 시간. 종료 후에는 null
result_readySume Job 상태/result가 결과를 반환할 수 있을 때만 true
import { useQuery } from "@tanstack/react-query";

type JobStatus = {
  sume_status: "queued" | "processing" | "completed" | "failed" | "canceled";
  terminal: boolean;
  result_ready: boolean;
  next_poll_after_seconds: number | null;
};

export function useVideoJob(jobId: string) {
  return useQuery({
    queryKey: ["video-job", jobId],
    queryFn: async (): Promise<JobStatus> => {
      const res = await fetch(`/api/video-jobs/${jobId}`); // your backend
      if (!res.ok) throw new Error(`status read failed: ${res.status}`);
      return res.json();
    },
    refetchInterval: (query) => {
      const job = query.state.data;
      if (job?.terminal) return false; // completed, failed or canceled
      return (job?.next_poll_after_seconds ?? 5) * 1000;
    },
  });
}

Job이 끝나면 컴포넌트는 무엇을 해야 하나요?

terminal이 true가 되면 sume_status에 따라 분기하세요.

  • completed: result_ready가 true가 되면 백엔드가 GET /v1/jobs/{id}/result를 읽어 컴포넌트에 미디어 URL을 넘기게 하세요.
  • failed 또는 canceled: 결과 라우트는 이런 Job에 409 job_not_completed로 응답하므로, 백엔드는 대신 GET /v1/jobs/{id}에서 오류를 읽습니다.
  • 두 경우 모두 간격 함수가 이미 false를 반환했으므로 폴링 요청이 더 나가지 않습니다.

탭이 숨겨지거나 폴링이 실패하면 어떻게 되나요?

refetchIntervalInBackground: true를 설정하지 않으면 탭이 백그라운드에 있는 동안 폴링이 일시 중지됩니다. Job은 멈추지 않습니다. 클라이언트가 지켜보기를 멈춰도 Job은 취소되지 않고 계속 실행되며 계속 과금됩니다. 다음 폴링이 이어서 Job 상태를 가져옵니다.

실패한 queryFn은 쿼리가 오류를 보고하기 전에 재시도되며, 상태 읽기에서 받은 429나 5xx는 작업이 아니라 읽기가 실패했다는 뜻입니다. 모든 탭은 여러분 서버의 키를 거쳐 폴링하며, 읽기에는 키마다 별도의 분당 예산이 있고 그 크기는 쓰기 예산의 마흔 배입니다. next_poll_after_seconds를 따르고 숨겨진 탭의 폴링을 멈추면 그 트래픽이 줄어듭니다.

대신 롱 폴링, SSE, WebSocket을 쓸 수 있나요?

Sume API에서는 쓸 수 없습니다. 현재 Developer API에는 SSE나 WebSocket 전송이 없으며, GET /v1/jobs/:id/events는 스트림이 아니라 pull 스냅샷입니다. 가장 가까운 것은 제출할 때 쓰는 sync 모드나 그 별칭인 subscribe로, 최대 30초 동안 한 번 기다리는 방식인데 영상 Job은 대개 그보다 오래 걸립니다. 푸시가 필요하면 Job과 함께 webhook_url(POST /v1/videos에서는 callback_url)을 보내 Job이 끝날 때 Sume가 서버에 알리게 하고, 서버는 앱이 이미 쓰는 방식으로 브라우저에 알리게 하세요. 그동안 무엇을 보여 줄지는 AI 영상 생성 API 진행 상황 업데이트에서 다룹니다.

출처

관련 글

연동 카테고리의 다른 글

연동 글 전체 보기

작성자 Sume