Claude Code의 주간 사용량 제한으로 자동화를 멈추지 않는 방법: 프로바이더 자동 페일오버 설계
요약
Claude Code의 주간 사용량 제한으로 인해 자동화 파이프라인이 멈추는 문제를 해결하는 방법을 제시합니다. 이 글은 공통 러너(common runner)를 설계하여, 특정 프로바이더가 제한에 걸리면 자동으로 다른 에이전트 CLI로 전환하고, 제한 해제 시점에 다시 돌아오는 시스템 아키텍처를 소개합니다.
핵심 포인트
- 공통 러너를 도입해 작업과 프로바이더 호출을 분리해야 합니다.
- 종료 코드 0이라도 '주간 제한' 문구가 있으면 실패로 간주하는 로직이 필요합니다.
- 제한 해제 시점까지는 해당 프로바이더를 아예 실행하지 않아 불필요한 오류를 방지합니다.
- 작업 성격에 따라 workspace, direct, reconcile 세 가지 모드로 자동 전환 전략을 설계해야 합니다.
Claude Code를 정기 작업(scheduled job) 실행 엔진으로 사용할 때 피할 수 없는 벽이 있습니다. 바로 **사용량 주간 제한(weekly limit)**입니다. 어느 날 밤, 캘린더 동기화 작업이 다음과 같은 메시지를 출력하며 멈췄습니다.
You've hit your weekly limit · resets Jul 26, 9pm (Asia/Tokyo)
사람이라면 '그럼 일요일까지 기다리자'로 끝날 문제지만, 자동화는 매일 실행되어야 합니다. 이 글에서는 제한을 감지하여 다른 에이전트 CLI(Codex 등)로 자동으로 전환하고, 제한 해제 시점에 Claude로 다시 돌아오는 '공통 러너(common runner)'의 설계 방법을 소개합니다.
원칙: CLI를 직접 호출하지 않기
우선, 각 작업(메일 분류, 캘린더 동기화, 회의록 작성 등)이 프로바이더의 CLI를 직접 호출하는 것을 중단하고, 그 사이에 공통 러너를 하나 삽입합니다.
러너는 프로바이더의 우선순위(claude, codex, ...)를 가지며, 실패하면 다음으로 넘어갑니다. 작업 측은 어떤 프로바이더를 사용하는지 알 필요 없이, '이 프롬프트를 이 권한으로, 이 부작용 모드로 실행해 줘'라고만 요청합니다.
감지의 함정: 종료 코드 0에서 제한이 반환되는 경우
초기 구현에서는 exit code와 표준 에러만 확인했기 때문에 실제 제한 상황을 간과했습니다. 실제로 관찰된 동작은 다음과 같습니다.
- 제한 문구가 **표준 출력(stdout)**에 나타나고, 종료 코드는 0인 경우가 있다. - 문구는
weekly limit를 포함한다 (실측:You've hit your weekly limit · resets ...).
이에 따라 '종료 코드 0이라도 신뢰도가 높은 제한 문구가 있으면 실패로 간주한다'는 판별 로직을 세웠습니다. 반대 방향의 오탐지(false positive)도 고려했습니다. 실행 도중에 발생한 툴 에러가 최종적으로 복구되어 성공한 run을, 로그에 오류 문자열이 있다는 이유만으로 실패 처리하여 성공 작업을 망치는 일이 있었습니다. 최종 규칙은 다음과 같습니다.
종료 코드 0인 run을 실패로 간주할 수 있는 경우는,
명시적인 주간 제한 문구가 있을 때뿐입니다.
복구 일시를 저장하고, 기한까지 Claude를 실행하지 않기
제한 문구에는 복구 일시가 포함되어 있으므로, 타임존을 포함하여 UTC로 정규화한 후 로컬 파일(gitignore 처리됨)에 저장합니다.
{ "claude": { "limitedUntil": "2026-07-26T12:00:00Z" } }
이후의 run은, 기한 내라면 Claude를 아예 실행하지 않고 다음 프로바이더부터 시작합니다. 불필요한 실행 실패가 사라지고 로그도 조용해집니다. 기한을 넘긴 다음 run에서 Claude를 재우선순위로 두고 성공하면 상태를 해제합니다.
가장 어려운 것은 '도중에 멈춘 작업'의 인계
프로바이더 A가 도중에 멈추고, 프로바이더 B가 그続き(이어지는 부분)를 처리하는 것이 핵심입니다. 작업의 성격에 따라 세 가지 모드로 나누었습니다.
workspace (코드/문서 편집)
파일 변경은 작업 트리(work directory)에 남아있기 때문에, 다음 프로바이더에게 '먼저 git status와 diff를 확인하고, 미완료된 부분만 계속 진행하라'고 지시합니다. 처음부터 다시 하는 것이 아니라 이어서 합니다.
direct (외부 전송 등 취소 불가능한 작업)
메일 전송 같은 작업은 결과가 불분명한 상태에서 자동 재실행해서는 안 됩니다. 중복 전송이 최악이기 때문입니다. 이전 프로바이더의 결과를 확인할 수 없을 때는 자동 전환을 금지하고, 사람에게 보고하여 멈춥니다.
reconcile (재조정하여 남은 부분만 실행)
그렇다고 '모두 멈추는 것'도 곤란하기 때문에, 외부 상태를 다시 읽어올 수 있는 작업에는 재조정 모드를 준비했습니다. 다음 프로바이더는 먼저 Gmail/캘린더/DB를 재획득하여, 수신자・제목・시간・원본 데이터 참조 ID・실행 ID를 대조하여 '이미 완료된 작업'을 제외한 나머지만 실행합니다.
세부적인 보강도 효과적이었다
- Windows의 제한된 환경에서는 자식 프로세스의
spawn이 이벤트가 아닌 동기 예외(Synchronous Exception) (EPERM)를 발생시키는 경우가 있습니다. 러너 외부에 새어나가지 않도록 일반 실패로 처리하여 다음 프로바이더로 진행할 수 있게 했습니다. - 프로바이더별 통신 및 권한을 확인하는doctor명령어를 준비하여, 전환이 일어나지 않는 평상시에도 건전성을 점검합니다. - 이 계층은 테스트하기 쉬운 부분이므로, 판정 로직에는 회귀 테스트(regression test)를 25개 배치했습니다. 제한 문구 패턴이 변경되었을 때 가장 효과적입니다.
요약
⚠️ 레이트 리미트는 예외가 아니라 전제입니다. 에이전트 기반은 처음부터 '실행자를 교체 가능'하게 만드세요. 탐지는 문언 기반으로 하고, 종료 코드를 믿지 마세요.
- 복구 일시를 저장하여 제한 시간에는 작동하지 않게 합니다.
- 중간 중단의 인계는 '작업 트리 확인', '재조합(再照合)', '취소 불가능한 작업은 멈추기'의 3가지 모드로 생각합니다.
이 구조는 부가적으로 모델 교체에도 강점을 가집니다. 새로운 CLI가 나오면, runner의 provider 목록에 한 줄만 추가하면 됩니다.
논의 (Discussion)

AI 자동 생성 콘텐츠
본 콘텐츠는 Zenn AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기