클로드 코드 완전 자동화 #3 — 리밋 걸리면? 중단과 재개 전략
Claude Code 자동 실행 중 rate limit, 토큰 한도, 크레딧 소진 시 대응법. 재시도 로직과 비용 최적화 전략.
한 줄 요약: 리밋에 걸리면 해당 세션은 멈추지만, 작업을 쪼개고 재시도 로직을 넣으면 자동으로 이어갈 수 있다.
클로드 코드(Claude Code)를 headless 모드로 자동 실행하다 보면 반드시 한 번은 마주치는 문제가 있다. Rate limit으로 429 에러가 뜨거나, 대화가 길어져 컨텍스트 창이 꽉 차거나, 월 구독 한도에 도달하는 상황이다. 이 글에서는 각 리밋의 실체와 행동 방식을 정확히 파악하고, 자동화 스크립트에서 안전하게 재개하는 전략을 정리한다.
※ 이 글은 클로드 코드 완전 자동화 시리즈 #3입니다. 2026년 3월 기준, Claude Code CLI 공식 문서 기반으로 작성됐습니다.
Claude Code에서 만나는 리밋 4가지
클로드 코드(Claude Code)를 자동화 환경에서 돌릴 때 마주치는 리밋은 성격이 제각각이다. 원인과 해결 경로가 다르기 때문에 먼저 구분하는 것이 중요하다.
| 리밋 종류 | 발생 조건 | 에러 신호 | 해결 방향 |
|---|---|---|---|
| Rate Limit | 단위 시간당 API 호출 수 초과 | 429 Too Many Requests | 대기 후 재시도 |
| 컨텍스트 초과 | 대화 누적 토큰이 200K 초과 | context window full 메시지 | /compact 또는 새 세션 |
| 구독 사용량 한도 | Pro/Max 플랜 월간 한도 소진 | usage limit reached 메시지 | 갱신일 대기 또는 플랜 업그레이드 |
| API 크레딧 소진 | Console API 선불 크레딧 소진 | 402 / billing error | 크레딧 충전 |
※ 구독(Pro/Max)과 API 콘솔 크레딧은 별개다. Claude Code CLI는 기본적으로 Anthropic 계정 구독을 사용하고, --api-key로 Console API 키를 지정하면 크레딧을 소모한다.
리밋에 걸리면 실제로 어떻게 되나
각 리밋이 걸렸을 때 클로드 코드(Claude Code)가 취하는 행동은 실행 모드(대화형 / headless)에 따라 다르다.
Rate Limit (429)
대화형 세션에서는 클로드 코드가 내부적으로 일정 시간(수십 초~수 분) 대기한 뒤 자동으로 재시도한다. 사용자는 대기 메시지를 보게 된다. headless 모드(claude -p)에서는 재시도 없이 에러 메시지와 함께 즉시 종료된다. exit code는 0이 아닌 값으로 반환된다.
컨텍스트 윈도우 초과
Claude 3.x 모델의 컨텍스트 창은 200K 토큰이다. 대화가 길어지면 이 한도에 도달한다. 대화형에서는 /compact 명령으로 대화 내용을 요약·압축해 새 컨텍스트 공간을 확보할 수 있다. headless 자동화에서는 이 명령을 직접 호출할 수 없으므로, 처음부터 세션을 짧게 유지하는 설계가 필요하다.
구독 사용량 한도
Pro/Max 플랜은 월간 사용량 한도가 있다. 한도에 도달하면 다음 갱신일(보통 구독 시작일 기준 매월)까지 추가 요청이 불가능하다. 에러 메시지에 갱신 예정일이 표시된다. 이 경우 자동화 스크립트에서 할 수 있는 것은 없다 — 스크립트가 이 상황을 감지해 알림을 보내고 멈추는 것이 최선이다.
API 크레딧 소진
Console API 크레딧이 소진되면 402 응답 또는 billing 관련 에러가 반환된다. 크레딧을 충전하면 즉시 재개 가능하다. 자동화에서는 크레딧 잔액 알림을 Anthropic Console에서 설정해두는 것이 권장된다.
429, rate limit, too many requests 문자열을 별도로 체크해야 한다..claudeignore에 불필요한 디렉토리(node_modules, .git, dist, build 등)를 추가하고, 작업 단위를 파일 범위별로 분리해 새 세션에서 시작할 것.자동화에서 리밋 대응 전략
리밋을 완전히 피할 수는 없다. 중요한 것은 리밋이 걸렸을 때 스크립트가 어떻게 반응하느냐다. 핵심 원칙은 세 가지다.
- 작업을 독립 단위로 쪼갠다 — 한 세션에 너무 많은 작업을 넣지 않는다
- 결과를 파일로 저장한다 — 중간 결과가 파일에 있으면 다음 실행에서 이어받을 수 있다
- 에러를 감지하고 재시도 또는 중단한다 — 스크립트가 리밋 에러를 인식하지 못하면 무한 실패 루프가 발생한다
아래는 이 원칙을 적용한 bash 재시도 래퍼 스크립트다.
rate_limit 감지 + 지수 백오프 재시도 래퍼 (bash)#!/usr/bin/env bash # claude_run.sh — rate limit 대응 재시도 래퍼 # 사용법: ./claude_run.sh "작업 프롬프트" output_file.txt PROMPT="$1" OUTPUT_FILE="$2" MAX_RETRIES=5 RETRY_DELAY=60 # 초 단위 초기 대기 시간 run_claude() { claude -p "$PROMPT" --output-format text 2>&1 } for attempt in $(seq 1 $MAX_RETRIES); do echo "[$(date '+%H:%M:%S')] 시도 $attempt / $MAX_RETRIES" OUTPUT=$(run_claude) EXIT_CODE=$? # 429 rate limit 감지 (exit code 및 stdout 모두 확인) if echo "$OUTPUT" | grep -qi "rate.limit\|429\|too many requests"; then WAIT=$((RETRY_DELAY * attempt)) # 지수 백오프 echo "[RATE LIMIT] ${WAIT}초 대기 후 재시도..." sleep $WAIT continue fi # 구독 한도 / 크레딧 소진 — 재시도 불가, 즉시 중단 if echo "$OUTPUT" | grep -qi "usage limit\|billing\|402"; then echo "[LIMIT REACHED] 구독 한도 또는 크레딧 소진. 수동 확인 필요." exit 2 fi # 정상 종료 if [ $EXIT_CODE -eq 0 ]; then echo "$OUTPUT" > "$OUTPUT_FILE" echo "[OK] 결과 저장: $OUTPUT_FILE" exit 0 fi echo "[ERROR] exit code $EXIT_CODE. 재시도..." sleep $RETRY_DELAY done echo "[FAIL] 최대 재시도 횟수 초과." exit 1
이 래퍼를 쓰면 rate limit 시 지수 백오프(60초, 120초, 180초...)로 대기하고, 구독 한도나 크레딧 소진은 재시도 없이 즉시 exit code 2로 종료한다. 호출하는 상위 스크립트에서 exit code로 분기 처리할 수 있다.
중단 후 이어가기 — 세션 재개 전략
클로드 코드(Claude Code)에는 이전 대화를 이어가는 두 가지 방법이 있다.
대화형에서 /resume 사용
대화형 세션에서 /resume 명령을 실행하면 이전 대화 목록이 표시되고, 선택한 대화를 이어갈 수 있다. 단, 이 기능은 대화형 모드에서만 동작한다. headless(claude -p) 자동화에서는 이전 대화 ID를 --resume 플래그로 전달해야 한다.
headless에서 이전 세션 이어가기# 첫 번째 실행 — 대화 ID를 파일에 저장 SESSION_ID=$(claude -p "작업 1 시작" --output-format json | jq -r '.session_id') echo "$SESSION_ID" > .claude_session_id # 이후 실행 — 저장된 세션 ID로 재개 SESSION_ID=$(cat .claude_session_id) claude -p "작업 2 이어서" --resume "$SESSION_ID" --output-format text
단, 세션 재개는 컨텍스트 한도 문제를 해결하지 않는다. 이전 대화가 이미 길었다면 재개해도 곧 컨텍스트가 꽉 찰 수 있다. 이 경우에는 새 세션을 시작하되, 이전 작업의 결과 파일을 컨텍스트로 넘기는 방식이 더 안정적이다.
파일 기반 상태 관리 (권장)
headless 자동화의 가장 안정적인 재개 전략은 중간 결과를 파일로 저장하고, 다음 세션에서 해당 파일을 프롬프트에 포함하는 것이다. 대화 상태에 의존하지 않으므로 컨텍스트 초과와 무관하게 작동한다.
파일 기반 상태 관리 패턴 (multi-step 작업)#!/usr/bin/env bash # 작업을 단계별 파일로 분리해 재개 가능하게 만드는 패턴 WORK_DIR=".claude_work" mkdir -p "$WORK_DIR" # 단계 1 — 코드 분석 (아직 결과 파일이 없을 때만 실행) if [ ! -f "$WORK_DIR/step1_analysis.txt" ]; then echo "[STEP 1] 코드 분석 중..." claude -p "src/ 디렉토리의 함수 목록을 정리해줘" \ --output-format text > "$WORK_DIR/step1_analysis.txt" fi # 단계 2 — 이전 단계 결과를 프롬프트에 포함 if [ ! -f "$WORK_DIR/step2_tests.txt" ]; then echo "[STEP 2] 테스트 생성 중..." ANALYSIS=$(cat "$WORK_DIR/step1_analysis.txt") claude -p "다음 함수 목록에 대한 단위 테스트를 작성해줘:\n\n$ANALYSIS" \ --output-format text > "$WORK_DIR/step2_tests.txt" fi echo "[DONE] 모든 단계 완료."
session not found 에러가 남 → 세션은 로컬에 일정 기간만 보관된다. 며칠 이상 지난 세션 ID는 만료돼 재개할 수 없다 → 파일 기반 상태 관리로 전환하거나, 세션 ID 보관 주기를 최대 24시간 이내로 설계할 것.비용 최적화 — 리밋을 덜 만나는 방법
리밋에 덜 걸리는 가장 직접적인 방법은 토큰 소모를 줄이는 것이다. 클로드 코드(Claude Code) 자동화에서 적용할 수 있는 방법들이다.
모델 선택
Claude Code는 기본적으로 claude-sonnet을 사용한다. 단순 반복 작업(포맷 변환, 간단한 리팩토링 등)에는 더 저렴한 모델을 지정할 수 있다.
모델 지정 — headless 모드에서 사용# 기본 (Sonnet — 균형) claude -p "작업 내용" --model claude-sonnet-4-5 # 저렴한 모델 (Haiku — 단순 작업용) claude -p "작업 내용" --model claude-haiku-4-5 # 고성능 모델 (Opus — 복잡한 아키텍처 설계 등) claude -p "작업 내용" --model claude-opus-4-5
.claudeignore로 불필요한 파일 제외
클로드 코드는 프로젝트 디렉토리를 탐색할 때 .claudeignore에 명시된 경로를 제외한다. 대규모 프로젝트에서는 컨텍스트에 들어오는 파일 수를 줄이는 것만으로도 토큰 소모가 크게 줄어든다.
.claudeignore 예시 — 불필요한 디렉토리 제외# .claudeignore node_modules/ dist/ build/ .next/ .git/ coverage/ *.log *.lock *.min.js *.map public/ assets/images/
CLAUDE.md로 컨텍스트 집중
프로젝트 루트에 CLAUDE.md를 두면 클로드 코드가 세션 시작 시 이 파일을 먼저 읽는다. 여기에 작업 범위, 금지 사항, 자주 쓰는 명령어를 명시하면 매번 긴 프롬프트를 전달할 필요가 없어 토큰이 절약된다. 이미 CLAUDE.md가 있다면 반복적인 지시 문구를 프롬프트에서 제거할 수 있다.
| 최적화 방법 | 효과 | 적용 난이도 |
|---|---|---|
| .claudeignore 설정 | 컨텍스트 토큰 대폭 감소 | 낮음 |
| 작업 단위 분리 | 세션 길이 단축, 재시도 용이 | 낮음 |
| Haiku 모델 지정 | 비용 최대 95% 절감 (단순 작업) | 낮음 |
| CLAUDE.md 활용 | 프롬프트 길이 단축 | 낮음 |
| 파일 기반 상태 관리 | 컨텍스트 누적 방지 | 중간 |
실전 패턴 — 리밋 안전 자동화 스크립트
아래는 시리즈에서 다룬 내용을 모두 통합한 실전 자동화 스크립트다. 시간당 실행 횟수 제한, 에러 감지, 슬랙 알림, 일일 비용 상한 설정을 포함한다.
리밋 안전 자동화 스크립트 — 통합 버전#!/usr/bin/env bash # safe_claude_runner.sh — rate limit + 비용 상한 + 슬랙 알림 통합 # 설정값 SLACK_WEBHOOK="https://hooks.slack.com/services/YOUR/WEBHOOK/URL" MAX_RUNS_PER_HOUR=10 # 시간당 최대 실행 횟수 DAILY_COST_LIMIT=5.0 # 일일 비용 상한 (달러, 개인 추적용) RUN_LOG=".claude_run_log.txt" COST_LOG=".claude_cost_log.txt" WORK_DIR=".claude_work" mkdir -p "$WORK_DIR" send_slack_alert() { local MESSAGE="$1" if [ -n "$SLACK_WEBHOOK" ]; then curl -s -X POST -H 'Content-type: application/json' \ --data "{\"text\": \"[Claude Auto] $MESSAGE\"}" \ "$SLACK_WEBHOOK" > /dev/null fi echo "[ALERT] $MESSAGE" } check_hourly_rate() { local NOW=$(date +%s) local ONE_HOUR_AGO=$((NOW - 3600)) local RECENT_RUNS=0 if [ -f "$RUN_LOG" ]; then RECENT_RUNS=$(awk -v cutoff="$ONE_HOUR_AGO" '$1 > cutoff' "$RUN_LOG" | wc -l) fi if [ "$RECENT_RUNS" -ge "$MAX_RUNS_PER_HOUR" ]; then send_slack_alert "시간당 실행 한도($MAX_RUNS_PER_HOUR)에 도달. 다음 시간까지 대기." sleep 3600 fi echo "$(date +%s)" >> "$RUN_LOG" } run_task() { local TASK_NAME="$1" local PROMPT="$2" local OUTPUT_FILE="$WORK_DIR/${TASK_NAME}.txt" # 이미 완료된 작업은 건너뜀 if [ -f "$OUTPUT_FILE" ]; then echo "[SKIP] $TASK_NAME — 이미 완료됨" return 0 fi check_hourly_rate echo "[RUN] $TASK_NAME" OUTPUT=$(claude -p "$PROMPT" --model claude-sonnet-4-5 \ --output-format text 2>&1) EXIT_CODE=$? if echo "$OUTPUT" | grep -qi "rate.limit\|429\|too many requests"; then send_slack_alert "Rate limit 감지: $TASK_NAME. 60초 후 재시도." sleep 60 run_task "$TASK_NAME" "$PROMPT" # 재귀 재시도 return fi if echo "$OUTPUT" | grep -qi "usage limit\|billing\|402"; then send_slack_alert "구독 한도 또는 크레딧 소진. 자동화 중단." exit 2 fi if [ $EXIT_CODE -ne 0 ]; then send_slack_alert "오류 발생 (exit $EXIT_CODE): $TASK_NAME" return 1 fi echo "$OUTPUT" > "$OUTPUT_FILE" echo "[OK] $TASK_NAME 완료 → $OUTPUT_FILE" } # 작업 목록 실행 run_task "analyze" "src/의 함수 목록을 정리해줘" run_task "test_gen" "$(cat "$WORK_DIR/analyze.txt" 2>/dev/null) 위 함수들에 대한 단위 테스트를 작성해줘" run_task "docs" "$(cat "$WORK_DIR/analyze.txt" 2>/dev/null) 위 함수들에 대한 JSDoc 주석을 작성해줘" send_slack_alert "모든 작업 완료." echo "[DONE]"
$WORK_DIR/${TASK_NAME}.txt 파일이 있으면 해당 작업을 건너뛰는 로직이 핵심이다. 스크립트가 중간에 중단되더라도 다음 실행에서 완료된 작업은 다시 실행하지 않는다. cron으로 주기적으로 돌리면 실패한 작업만 자동으로 재시도된다.SLACK_WEBHOOK을 빈 문자열로 두면 알림 전송을 건너뛴다. 이메일 알림이 필요하다면 send_slack_alert 함수 안에 mail -s "Claude Alert" you@example.com <<< "$MESSAGE"를 추가하면 된다.시리즈 마무리 — 핵심 체크리스트
클로드 코드(Claude Code) 완전 자동화 3편 시리즈에서 다룬 내용을 체크리스트로 정리한다.
| 항목 | 편 | 확인 |
|---|---|---|
--dangerously-skip-permissions 이해 및 적용 | #1 | □ |
headless 모드(claude -p) 사용 | #1 | □ |
| cron / launchd 스케줄링 설정 | #2 | □ |
| GitHub Actions 연동 | #2 | □ |
| .claudeignore로 불필요한 파일 제외 | #3 | □ |
| 429 / usage limit 에러 감지 로직 | #3 | □ |
| 파일 기반 상태 관리로 재개 가능 설계 | #3 | □ |
| 모델 선택으로 비용 최적화 | #3 | □ |
| 알림(슬랙/이메일) 연동 | #3 | □ |
참고: Claude Code 공식 문서 / CLI 레퍼런스