AI 활용

Cloudflare Workers Cron Triggers 상한은 무료 5개·유료 250개: 공식 문서로 보는 4가지 우회법

Cloudflare Workers Cron Triggers 상한은 무료 5개·유료 250개: 공식 문서로 보는 4가지 우회법

좋은 아침입니다. まさきん입니다.

Cloudflare Workers 공식 문서에는 무료 플랜의 Cron Triggers 상한이 5개로 정해져 있습니다. 저도 집안 자동화를 무료 플랜으로 꾸려 가다가 얼마 전 이 상한에 걸렸습니다. 그때 빠져나간 방법을 공식 정보와 함께 정리해 두려고 합니다.

※기사 공개 시점의 정보입니다. 최신 조건은 공식 사이트에서 확인해 주세요.

POINT
  • Workers Free에서 Cron Triggers는 계정 전체에서 5개까지입니다
  • 비슷한 용도의 시각은 식 하나로 합치고 핸들러 안에서 분기할 수 있습니다
  • 실행 트리거만 집 PC 등으로 빼면 처리는 Worker에 남겨 둘 수 있습니다
  • 밖에서 호출한다면 비밀 토큰 인증과 타임아웃 설정이 필요합니다
  • 그래도 부족하면 유료 플랜의 250개로 옮기는 게 가장 깔끔합니다

상한에 걸린 경위

건강 데이터를 알려 주는 Worker에 Cron Triggers를 3개 추가해 배포했습니다. 그랬더니 스케줄 설정만 실패했습니다. 오류 코드는 10072였고, Workers Free의 계정 상한에 걸린 게 원인이었습니다.

코드 자체의 배포는 통과했습니다. 그래서 얼핏 성공한 것처럼 보이는 게 조금 골치 아픈 점입니다. 로그를 보지 않고 내버려 뒀다면 ‘왠지 안 돌아가네’ 상태가 됐을지도 모릅니다.

무료 플랜 상한은 5개

공식 Limits 페이지를 보면 Cron Triggers 개수는 계정 단위로 정해져 있습니다. Worker 하나당이 아니라는 점이 중요합니다.

항목Workers FreeWorkers Paid
Cron Triggers 개수(계정 전체)5250
Cron 실행 시 CPU 시간10ms30초(1시간 미만 간격) / 15분(1시간 이상 간격)
HTTP 실행 시 CPU 시간10ms최대 5분(기본 30초)
요청 수하루 10만까지(UTC 0시에 초기화)월 1,000만까지 요금에 포함

집 자동화는 작은 Worker를 용도별로 나누기 쉽습니다. Worker 하나에 스케줄을 2~3개씩 두면 5개는 금방 찹니다. 저도 정신 차려 보니 꽉 차 있었습니다.

Cron Triggers 기본 복습

빠져나갈 방법을 생각하기 전에 사양을 확인해 둡니다. 여기를 짚어 두면 쓸 수 있는 수가 여러 가지 보입니다.

주의할 건 UTC라는 점입니다. 일본 시간은 UTC보다 9시간 빠릅니다. 아침 6시 30분에 돌리고 싶다면 UTC로는 전날 21시 30분으로 써야 합니다.

controller.cron에는 설정한 식의 문자열이 그대로 들어갑니다. 공식 문서에는 공백까지 포함해 한 글자도 틀리지 않고 일치시켜야 한다고 적혀 있습니다. 예전 방식인 event.cron으로 쓴 코드도 생각은 같습니다.

빠져나가는 법은 크게 네 가지

제가 검토한 선택지를 먼저 표로 늘어놓겠습니다.

방법절약되는 개수장점단점
(1) 여러 시각을 식 하나로 합친다큼추가 구조가 필요 없다시각 분기를 코드로 가져가야 한다
(2) 실행 트리거만 밖으로 뺀다큼빈도를 자유롭게 늘릴 수 있다외부 트리거가 멈추면 동작하지 않는다
(3) 디스패처 Worker로 모은다큼Cloudflare 안에서 끝난다한곳의 문제가 전체에 영향을 준다
(4) 유료 플랜으로 옮긴다근본 해결상한이 250개로 늘어난다월 5달러부터 비용이 든다

(1)부터 시도하고, 부족하면 (2)나 (3)으로 넘어간다. 마지막에 (4)를 생각한다. 무료 플랜으로 꾸려 간다면 이 순서가 무난할 것 같습니다.

방법 1: 시각을 식 하나로 합치기

가장 손쉬운 게 이 방법입니다. 아침과 점심에 식을 따로 써 두었다고 해 봅시다. 같은 Worker 안이라면 시 필드를 쉼표로 이으면 하나가 됩니다.

저는 아침과 점심 두 개를 다음 하나로 합쳐 다시 배포했습니다.

[triggers]
crons = ["30 3,21 * * *"]

UTC 21시 30분은 일본 시간 아침 6시 30분입니다. UTC 3시 30분은 일본 시간 낮 12시 30분입니다. 이걸로 1개가 비었습니다.

식이 하나가 되면 controller.cron으로는 어느 시각인지 구별할 수 없습니다. 그래서 실행 예정 시각에서 UTC의 ‘시’를 꺼내 분기합니다.

export default {
  async scheduled(controller, env, ctx) {
    const hourUtc = new Date(controller.scheduledTime).getUTCHours();
    if (hourUtc === 21) {
      await sendMorning(env); // 일본 시간 6:30
    } else if (hourUtc === 3) {
      await sendNoon(env); // 일본 시간 12:30
    }
  },
};

scheduledTime은 실행이 예정되어 있던 시각입니다. 실제로 돌아간 시각보다 이쪽으로 판정하는 게 더 안정적이라고 생각합니다.

다만 합칠 수 있는 건 ‘분’이 같은 시각뿐입니다. 6시 30분과 12시 15분처럼 분이 다르면 식 하나로 표현할 수 없습니다. 그럴 때는 분을 맞춰도 되는지 한 번 생각해 보는 게 좋겠습니다.

합쳐도 꽉 찼다면

제 경우 아침·점심을 합쳐도 5개는 여전히 꽉 찬 상태였습니다. 새 처리를 추가할 여지가 없었죠.

그래서 나머지 Cron을 다시 살펴봤습니다. 위치 정보 동기화가 1개, 집 사이니지 갱신이 2개였습니다. 이 3개는 모두 집에 있는 Mac이 켜져 있다는 전제의 처리였습니다. 그래서 실행 트리거를 밖으로 빼는 방법을 골랐습니다.

집안 자동화는 결국 인터넷 너머의 통신으로 돌아갑니다. 회선 쪽을 잘 정비해 두면 이런 구조도 안심하고 돌릴 수 있을 것 같습니다.

가입하지 않아도 100포인트를 받는 요금 시뮬레이션 집 자동화를 받쳐 주는 통신비도 라쿠텐 모바일로 점검하기

누르면 라쿠텐 로그인 페이지가 열립니다. 로그인하면 캠페인 내용이 표시됩니다.

방법 2: 실행 트리거만 밖으로 빼기

생각은 단순합니다. 처리는 Worker에 남긴 채 ‘언제 돌릴지’만 밖에 맡깁니다. 외부 트리거는 Worker의 URL을 HTTP로 호출하기만 합니다.

저는 위치 정보 동기화와 사이니지 갱신의 Cron을 뺐습니다. 대신 집 Mac의 launchd에서 Worker URL을 호출하는 형태로 옮겼습니다. 이걸로 빈 자리는 3개가 됐습니다.

반가운 부수 효과도 있었습니다. 위치 정보 동기화가 하루 1회였던 것을 아침 8시 05분부터 밤 20시 05분까지 매시간으로 늘릴 수 있었습니다. Cron 개수를 신경 쓰지 않아도 된다는 게 크네요.

Worker 쪽에 입구 만들기

Worker 쪽에는 실행용 경로를 준비합니다. 중요한 건 암호를 아는 상대만 통과시키는 것입니다.

export default {
  async fetch(request, env, ctx) {
    const url = new URL(request.url);
    if (url.pathname !== "/run/location-sync") {
      return new Response("not found", { status: 404 });
    }
    const auth = request.headers.get("Authorization");
    if (auth !== `Bearer ${env.RUN_TOKEN}`) {
      return new Response("unauthorized", { status: 401 });
    }
    await syncLocation(env);
    return new Response("ok");
  },
};

토큰은 코드에 직접 쓰지 않고 시크릿으로 등록합니다. 등록에는 npx wrangler secret put RUN_TOKEN을 씁니다. 코드에서는 env.RUN_TOKEN으로 읽을 수 있습니다.

Mac 쪽은 launchd로 호출

Mac 쪽에서는 launchd 작업에서 curl을 실행합니다. 흐름은 다음과 같습니다.

  1. 토큰을 읽어 들여 curl로 Worker URL을 호출하는 셸 스크립트를 만든다
  2. ~/Library/LaunchAgents에 plist를 두고 실행 시각을 지정한다
  3. launchctl로 작업을 불러온다
  4. 수동으로 한 번 실행해서 Worker 쪽 로그로 성공을 확인한다

스크립트 내용은 거의 curl 한 줄입니다.

curl -fsS --max-time 600 \
  -H "Authorization: Bearer ${RUN_TOKEN}" \
  https://example.workers.dev/run/location-sync

launchd는 Mac의 로컬 시각으로 동작합니다. Cron Triggers처럼 UTC로 바꿀 필요가 없다는 게 소소하게 편한 점입니다.

밖에서 호출할 때의 주의점

밖에서 실행하는 방식에는 Cron Triggers에는 없는 주의점이 있습니다. 제가 실제로 걸렸던 부분도 포함해 정리해 둡니다.

주의

URL만 알면 누구나 호출할 수 있게 됩니다. 비밀 토큰으로 인증하고, 토큰은 시크릿에 넣어 두세요. curl 타임아웃은 처리 시간보다 넉넉하게 잡는 게 안전합니다.

가장 애먹은 건 타임아웃이었습니다. Mac에서 호출하는 처리는 이틀치를 한꺼번에 하면 약 73초가 걸렸습니다. curl 타임아웃을 90초로 해 뒀더니 시간 초과가 났습니다. 지금은 600초로 늘려 두었습니다.

공식 문서에 따르면 HTTP로 실행한 Worker의 실행 시간에는 엄격한 상한이 없습니다. 다만 클라이언트가 연결되어 있는 동안만이라는 조건이 붙습니다. 연결이 끊기면 처리가 도중에 멈출 수 있습니다. 그래서 호출하는 쪽의 타임아웃은 여유 있게 잡는 게 좋다고 생각합니다.

또 하나는 CPU 시간입니다. Free에서는 1회당 10ms까지입니다. 다만 fetch()나 데이터베이스 응답을 기다리는 시간은 CPU 시간에 포함되지 않습니다. 외부 API를 기다리기만 하는 처리라면 길어 보여도 범위 안에 들어가는 경우가 많을 수 있습니다.

방법 3: 디스패처 Worker로 모으기

여러 Worker가 각자 Cron을 가지고 있다면 한곳에 모으는 방법도 있습니다. ‘디스패처’ Worker 하나에만 스케줄을 두는 형태입니다.

디스패처는 controller.cron이나 실행 시각을 보고 담당 Worker를 호출합니다. 호출 대상에는 HTTP로 호출하는 방식이 이해하기 쉬울 것 같습니다.

이 방법의 좋은 점은 Cloudflare 안에서 끝난다는 것입니다. 집 PC가 잠들어 있어도 돌아갑니다. 다만 디스패처가 고장 나면 모든 정기 처리가 멈춥니다. Free에서는 서브리퀘스트가 1회당 50까지이므로, 호출 대상이 많을 때는 신경 써 두고 싶은 부분입니다.

방법 4: 유료 플랜으로 옮기기

가장 깔끔한 건 Workers Paid로 옮기는 것입니다. 요금 페이지에서는 계정당 월 5달러부터라고 되어 있습니다.

상한은 5개에서 250개로 늘어납니다. Cron 실행 시 CPU 시간도 늘어나서 무거운 처리도 두기 쉬워집니다.

개인적으로는 집 자동화에서 250개나 쓸 일은 없을 것 같습니다. 개수 문제뿐이라면 먼저 (1)~(3)으로 상황을 본다. 처리가 무거워서 곤란해지면 유료를 생각한다. 그런 순서면 되지 않을까 싶습니다.

제가 받아들인 트레이드오프

실행 트리거를 Mac으로 옮기면서 분명히 잃은 게 있습니다. 사이니지는 Mac이 돌아가고 있지 않으면 갱신되지 않게 됐습니다. Mac을 거치지 않고 전달되는 경로는 이제 없습니다.

그래도 사이니지를 보는 건 집에 있을 때입니다. 집에 있을 때는 Mac도 켜져 있는 경우가 많습니다. 이 전제라면 받아들일 수 있다고 판단했습니다.

반대로 외출 중에도 확실히 와야 하는 알림은 Cron Triggers에 남겨 두는 게 안심이라고 생각합니다. ‘멈춰도 곤란하지 않은 것’부터 밖으로 빼 나간다는 선 긋기가 중요하다고 느낍니다.

흔한 실수와 함정

실제로 해 보면서 여기는 조심해야겠다고 생각한 점입니다.

특히 세 번째는 놓치기 쉽습니다. 배포 후에는 대시보드나 Wrangler 출력으로 스케줄이 등록됐는지 확인해 두면 안심입니다.

잘 맞는 사람, 안 맞는 사람

방법 2(실행 트리거를 밖으로 빼기)는 맞고 안 맞고가 분명합니다.

내용
잘 맞는 사람항상 켜져 있는 집 PC나 서버가 있다 / 집에 있을 때만 돌면 되는 처리가 있다 / 빈도를 촘촘하게 늘리고 싶다
안 맞는 사람외출 중이나 여행 중에도 확실히 돌아야 한다 / 집 PC를 자주 절전시킨다 / 인증 관리를 하고 싶지 않다

안 맞는 쪽이라면 (1)이나 (3)이 더 어울릴 수 있습니다. 유료 플랜도 선택지입니다.

시작하기 전에 확인할 것

자주 묻는 질문

Q. 5개 상한은 Worker마다인가요?

계정 전체에서 5개입니다. Worker 하나당 5개가 아닙니다. 여러 Worker로 나눠도 합계로 셉니다.

Q. 상한을 넘으면 배포 자체가 실패하나요?

제 경우에는 코드 배포는 통과했습니다. 실패한 건 스케줄 설정뿐이었습니다. 오류 코드는 10072였습니다. 얼핏 성공한 것처럼 보이니 출력을 잘 확인하는 게 좋다고 생각합니다.

Q. 식 하나에 시각을 몇 개까지 넣을 수 있나요?

시 필드를 쉼표로 이으면 분이 같은 시각은 몇 개든 합칠 수 있습니다. 다만 분이 다른 시각은 같은 식으로 표현할 수 없습니다. 너무 많이 합치면 핸들러 안의 분기가 읽기 어려워진다는 점도 조심하고 싶습니다.

Q. controller.cron과 event.cron은 다른가요?

지금 공식 문서에서는 controller.cron으로 판별하는 형태입니다. controller는 scheduled 핸들러의 첫 번째 인수입니다. 오래된 코드에는 event.cron으로 쓰여 있는 경우가 있습니다. 둘 다 실행된 식의 문자열을 본다는 생각은 같습니다.

Q. 밖에서 호출하는 경우 무료 플랜 요청 수는 괜찮나요?

Free에서는 하루 10만 요청까지입니다. 매시간 1회 호출하는 정도라면 하루 십수 회이니 여유가 있습니다. 다만 다른 용도와 합산된다는 점은 기억해 두면 좋을 것 같습니다.

Q. 집 PC 말고 실행 트리거를 맡길 방법이 있나요?

외부 스케줄 실행 서비스나 다른 클라우드의 정기 실행 기능에서 호출하는 방법도 있습니다. 그 경우에도 인증과 타임아웃에 대한 생각은 같습니다. 어떤 서비스를 쓸지는 멈췄을 때의 영향으로 고르는 게 좋다고 생각합니다.

Q. 유료 플랜으로 하면 CPU 시간 걱정도 사라지나요?

Cron 실행 시 CPU 시간은 Paid에서 간격에 따라 30초나 15분까지 늘어납니다. Free의 10ms보다 훨씬 여유가 있습니다. 다만 상한 자체가 없어지는 건 아니라는 점에 주의해야 합니다.

참고한 공식 정보

마무리

Cron Triggers의 상한은 계정 전체에서 5개입니다. 집 자동화를 계속하다 보면 생각보다 빨리 걸립니다.

저는 먼저 아침·점심 식을 하나로 합쳤습니다. 다음으로 Mac이 있다는 전제의 처리만 실행 트리거를 밖으로 뺐습니다. 덕분에 여유가 생겼고, 위치 정보 동기화도 매시간으로 늘릴 수 있었습니다.

대신 사이니지는 Mac에 의존하게 됐습니다. 어디까지 밖으로 뺄지는 멈췄을 때 곤란한지 아닌지로 정하는 게 좋겠습니다.

참고로 집 사이니지의 내용은 학교 알림장을 AI에게 읽혀 집 디스플레이에 띄우는 이야기에 썼습니다. 아침 정보를 한 장으로 정리하는 구조는 아침 브리핑을 자동 생성하는 이야기에 정리했습니다. 함께 읽어 보세요.

자동화의 기반을 점검하는 김에 매달 통신비도 한번 훑어보는 건 어떨까요.

가입하지 않아도 100포인트를 받는 요금 시뮬레이션 통신비도 함께 점검한다면 라쿠텐 모바일 확인하기

누르면 라쿠텐 로그인 페이지가 열립니다. 로그인하면 캠페인 내용이 표시됩니다.

이 글에는 제휴 광고가 포함되어 있습니다. 이 사이트의 링크를 통해 상품·서비스에 신청하시면 제휴사로부터 보상을 받을 수 있습니다. 또한 운영자는 라쿠텐 그룹 소속 직원으로, 사원 추천 프로그램을 통해 보상을 받는 경우가 있습니다. 기사 내용과 평가는 광고 유무와 관계없이 운영자의 실제 경험과 조사를 바탕으로 작성했지만, 위 관계를 이해하신 후 읽어 주시기 바랍니다. 자세한 내용은 면책조항·제휴 링크 안내를 참고해 주세요. 면책조항·제휴 링크 안내

이 글에는 기계 번역이 포함되어 있습니다. 정확한 조건은 라쿠텐 모바일 공식 사이트의 다국어 페이지에서 확인해 주세요.

라쿠텐 모바일의 통신 지역·전파 상황이 궁금하신 분은, 공식 전파 개선·조사 요청 양식 을 통해 문의하실 수 있습니다.

ABOUT THE AUTHOR
まさきん

라쿠텐 그룹 근무·디지털 마케터(FP 자격 보유)

40대 초반, 맞벌이·네 자녀의 아빠. 라쿠텐 그룹에서 디지털 마케터로 근무하면서, 재무설계사(FP) 자격을 활용해 가계 관리와 자산 형성에도 힘쓰고 있다.

프로필 보기

관련 글

RELATED
Gemini(Google AI Pro) 패밀리 공유는 가족 5명까지. 설정 절차와 범위 AI 활용

Gemini(Google AI Pro) 패밀리 공유는 가족 5명까지. 설정 절차와 범위

Google AI Pro는 관리자 외에 가족 5명까지 공유할 수 있습니다. Gemini 앱과 저장용량은 공유되고 YouTube Premium Lite는 관리자만. Flow 한도는 가족이 나눠 씁니다. 설정 절차와 자녀 계정 처리를 공식 도움말로 정리했습니다.

2026.10.13 · 읽는 시간 약 13분
AI 구독 청구일과 가계부가 어긋나는 3가지 이유|Claude는 업그레이드하면 청구일이 바뀐다 AI 활용

AI 구독 청구일과 가계부가 어긋나는 3가지 이유|Claude는 업그레이드하면 청구일이 바뀐다

Claude는 월 중간에 Max로 올리면 청구 주기가 리셋되어 그날이 새로운 청구일이 됩니다. 달러 결제의 엔화 환산은 카드사에 데이터가 도착한 시점에 정해지고, 명세와 가계부 반영은 며칠 늦습니다. 영수증 메일을 기준으로 월을 정하는 5단계를 정리했습니다.

2026.10.13 · 읽는 시간 약 14분
freee 회계의 미처리 내역을 월 1회 대사 작업으로. 매월 5일 7:30·3구분·상한 15건으로 사람에게 넘기는 설계 AI 활용

freee 회계의 미처리 내역을 월 1회 대사 작업으로. 매월 5일 7:30·3구분·상한 15건으로 사람에게 넘기는 설계

freee 회계의 미처리 내역이 18건 정도, 주간 확인 6번 동안 움직이지 않은 채 남아 있었습니다. 매월 5일 아침 7:30에 집 Mac에서 돌리는 대사 작업의 설계와, 확정할 수 있는 분은 월 1건, 망설여지는 내역은 1건씩 상한 15건으로 사람에게 넘기는 기준을 정리합니다.

2026.10.12 · 읽는 시간 약 15분
라쿠텐 모바일로 전환 시 최대 14,000포인트 가입하지 않아도 100포인트를 받는 요금 시뮬레이션 →
지금 신청하기 →