Vercel Cron Jobs: 중복 없이 매일 Sume API 호출하기

Vercel cron job이 라우트에 GET을 보내면 라우트가 날짜 기반 Idempotency-Key로 Sume API를 호출하므로, 중복 호출이 두 번 과금될 수 없습니다.

읽는 시간 5분Sume
전체 글

Vercel cron job에서 API를 호출하려면 vercel.json에 crons 항목을 추가하세요. 그러면 Vercel이 프로덕션 배포의 해당 경로로 HTTP GET을 보내고, 여러분의 라우트가 API를 호출합니다. 매일 만드는 Sume 영상이라면 라우트가 날짜로 만든 Idempotency-Key와 함께 Format 실행 하나를 POST하므로, Vercel이 같은 예약 회차를 두 번 전달해도 두 번째 POST는 두 번째 실행을 시작하거나 과금할 수 없습니다.

Vercel 관련 내용은 Vercel의 Cron Jobs, Cron Jobs 관리, 사용량과 요금 페이지에서, Sume 관련 내용은 Format 호출하기 (영문)와 Scheduled에서 가져왔습니다. 모두 2026-09-27에 확인했습니다. Sume에는 Vercel 전용 커넥터가 없으며, cron 라우트는 HTTPS로 직접 호출합니다. 시계 말고는 작업을 일으키는 것이 없다면 Sume 자체의 Scheduled 기능이 여러분의 코드 없이 저장된 자동화를 정해진 주기로 실행합니다. AI 영상 에이전트 스케줄 실행을 참고하세요.

Vercel cron job은 내 라우트를 어떻게 호출하나요?

cron 항목마다 path와 schedule을 지정합니다. 예를 들어 매일 05:00 UTC라면 { "crons": [{ "path": "/api/cron/daily-video", "schedule": "0 5 * * *" }] }처럼 씁니다. 각 요청의 user agent는 vercel-cron/1.0이며, 호출을 트리거한 표현식은 x-vercel-cron-schedule 헤더에 담깁니다.

Vercel의 Cron Jobs, Cron Jobs 관리, Cron Jobs 사용량과 요금 기준, 2026-09-27 확인.
속성Vercel 동작
요청프로덕션 배포 URL의 path로 보내는 HTTP GET
시간대항상 UTC
Hobby하루 최대 한 번, 더 잦으면 배포 실패. 예약한 시각이 속한 한 시간 안 어느 때든 실행
Pro와 Enterprise최대 분당 한 번까지. 예약한 분 안에 실행
실행 시간Vercel Functions와 같은 한도
실패한 호출재시도하지 않음
전달best effort 방식. 회차가 누락되거나 두 번 이상 호출될 수 있음
리다이렉트따라가지 않음

다른 사람이 cron 라우트를 호출하지 못하게 하려면 어떻게 하나요?

프로젝트에 CRON_SECRET 환경 변수를 추가하세요. Vercel은 16자 이상의 무작위 문자열을 권장합니다. Vercel은 작업을 호출할 때 이 값을 Bearer 접두사와 함께 Authorization 헤더에 담아 보내므로, 라우트는 둘을 비교해 일치하지 않으면 401로 응답합니다. SUME_API_KEY도 프로젝트 환경 변수에 두고 서버에서만 쓰세요. 클라이언트 JavaScript나 NEXT_PUBLIC_* 변수에는 절대 넣지 마세요.

라우트는 Sume API에 무엇을 보내나요?

POST /v1/formats/{handle}/{slug}/runs 요청 하나입니다. 본문에는 instruction, input, previous_run_id, attachments 중 적어도 하나가 있어야 합니다. 키와 본문을 모두 날짜만으로 만들어, 같은 날 다시 호출되더라도 똑같은 요청을 보내게 하세요.

// app/api/cron/daily-video/route.ts
export async function GET(request: Request) {
  const cronSecret = process.env.CRON_SECRET;
  if (!cronSecret || request.headers.get("authorization") !== `Bearer ${cronSecret}`) {
    return new Response("Unauthorized", { status: 401 });
  }
  const day = new Date().toISOString().slice(0, 10); // UTC, like the schedule
  const res = await fetch("https://api.sume.com/v1/formats/acme/product-promo/runs", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.SUME_API_KEY}`,
      "Content-Type": "application/json",
      "Idempotency-Key": `daily-promo-${day}`, // one run per UTC day
    },
    body: JSON.stringify({
      instruction: `Make the daily promo video for ${day}.`, // date only
      generation_spend_cap_usd: 3,
      communication: { webhook_url: "https://example.com/api/sume-webhook" },
    }),
  });
  const { data, error } = await res.json(); // 202 new run, 200 replay
  if (!res.ok) return Response.json(error, { status: res.status });
  await saveDailyRun(day, data.id); // your database
  return Response.json({ runId: data.id, replay: data.idempotency_hit });
}

Vercel이 같은 회차를 두 번 호출하면 어떻게 되나요?

Vercel은 cron 전달이 가끔 같은 예약 회차를 두 번 이상 호출할 수 있다고 밝히며, 작업을 멱등하게 만들라고 요청합니다. 날짜 키가 Sume 생성 요청을 멱등하게 만듭니다. 키 전반은 AI 영상 API 멱등성 키에서 다룹니다. 라우트는 실행되는 시점의 날짜를 읽으므로 스케줄을 UTC 자정 근처에 두지 마세요. Hobby에서는 호출이 예약한 시각이 속한 한 시간 안 어느 때든 일어날 수 있습니다.

Vercel의 Cron Jobs 관리와 Sume의 Format 호출하기 (영문) 기준, 2026-09-27 확인.
상황Sume의 응답
Vercel이 그날의 회차를 한 번 더 호출함같은 키, 같은 본문: 원래 실행과 idempotency_hit: true가 담긴 200. 두 번째 실행도, 두 번째 청구도 없음
두 호출이 같은 순간에 Sume에 도착함하나가 이기고, 다른 하나는 재시도할 수 있는 409 idempotency_key_in_use를 받음. 1초쯤 기다렸다가 다시 보내면 원래 실행을 받음
본문에 타임스탬프나 무작위 값이 들어 있음같은 키, 다른 본문: 409 idempotency_conflict. 아무것도 실행되지 않음
첫 생성 요청이 실패함(402, 503, …)키가 해제되었으므로 그 키로 보내는 다음 호출이 그날의 실행을 시작할 수 있음

Vercel이 하루를 놓치면 어떻게 하나요?

Vercel은 실패한 cron 호출을 재시도하지 않으며, 일시적인 네트워크 오류 때문에 예약된 요청이 함수에 아예 도달하지 못할 수도 있습니다. Vercel이 권하는 방법은 조정(reconciliation)입니다. 각 회차가 마지막으로 성공한 회차 이후 밀린 작업을 처리하게 하는 것입니다.

  • 위 라우트처럼 날짜별로 그날의 실행 ID(data.id)를 저장하세요.
  • 호출될 때마다 저장된 실행이 없는 날을 찾고, 아직 영상이 필요한 날은 그날 고유의 키와 본문으로 제출하세요.
  • 어떤 날이 이미 실행됐는지는 키가 아니라 저장된 ID로 판단하세요. 실행이 실패한 날에는 날짜에 직접 올리는 버전을 붙인 키 같은 새 키가 필요합니다. 이전 키는 이미 받은 영수증에 묶여 있기 때문입니다.

cron 함수에서 기다리지 않고 영상을 받으려면 어떻게 하나요?

Cron job은 Vercel Functions와 같은 실행 시간 한도(기본 300초)를 따르고, 영상을 만드는 실행은 초가 아니라 분 단위로 걸리므로, 라우트는 Sume가 실행을 수락하자마자 반환합니다. 본문의 communication.webhook_url은 실행이 완료되거나 실패할 때 서명된 format.run.terminal POST를 한 번 보내 달라는 요청입니다. 이를 받는 라우트는 Vercel 함수 타임아웃과 영상 생성에서 보여 주며, 실행의 result_url 읽기가 백업입니다.

출처

관련 글

연동 카테고리의 다른 글

연동 글 전체 보기

작성자 Sume