본문으로 건너뛰기

© 2026 Molayo

Zenn헤드라인2026. 05. 19. 12:41

Claude Code의 동적 /loop 구성하기 — ScheduleWakeup과 캐시 TTL

요약

Claude Code의 `/loop` 기능을 활용하여 작업 간격을 Claude가 스스로 결정하게 하는 동적 모드 운영 방법을 설명합니다. 특히 Anthropic의 프롬프트 캐시 TTL(5분)을 고려하여 비용과 효율을 최적화하는 `ScheduleWakeup` 도구 사용 전략을 다룹니다.

핵심 포인트

  • 동적 `/loop` 모드는 `ScheduleWakeup`을 통해 Claude가 상황에 맞춰 다음 작업 시간을 스스로 결정하게 함
  • Anthropic 프롬프트 캐시의 TTL은 5분(300초)이므로, 300초 근처의 설정은 캐시 미스로 인해 비용과 속도 면에서 비효율적임
  • 효율적인 운영을 위해 270초 이하로 설정하여 캐시를 유지하거나, 20~30분 이상으로 길게 설정하여 캐시 미스 비용을 상쇄할 것을 권장함
  • 동적 모드 사용 시 `ScheduleWakeup` 호출 시 반드시 동일한 `prompt`를 전달해야 루프가 지속됨

안녕하세요, 에리스입니다.

Claude Code에 /loop라는 스킬이 있다는 것을 알고 계시나요? "5분마다 이 작업을 수행해"와 같이 반복적인 태스크를 Claude 스스로 수행하게 만드는 기능입니다. 이것만으로도 편리하지만, 최근에는 **"간격을 지정하지 않고, Claude가 스스로 결정하게 하는" 모드 (동적 모드)**를 자주 사용하고 있으며, 이것이 운영 측면에서 꽤 효과적입니다.

오늘은 동적 /loop의 동작과 그 이면에서 작동하는 ScheduleWakeup 도구, 그리고 캐시 TTL(Time To Live)과의 관계에 대해 제가 운영하면서 깨달은 기준을 정리해 두겠습니다.

/loop란 무엇인가

일반적인 /loop/loop 5m /check-deploy와 같이 간격을 전달하는 방식입니다. 이것도 편리하지만 다음과 같은 단점이 있습니다.

  • 너무 빠르면 불필요한 tick이 늘어나 토큰을 소모함
  • 너무 느리면 상황을 파악하는 것이 늦어짐
  • 애초에 "몇 분이 정답인가"가 상황에 따라 변함

이를 Claude 스스로 결정하게 하는 것이 동적 모드입니다. /loop에 간격을 전달하지 않고 실행하면, Claude는 매 tick마다 "다음에는 언제 깨어날지"를 ScheduleWakeup을 통해 자기 신고하는 메커니즘으로 되어 있습니다.

즉, 지금 빌드가 돌아가고 있다면 짧게, 더 이상 할 일이 없다면 길게, 라는 것을 문맥을 보고 결정할 수 있습니다.

ScheduleWakeup 사용법

도구 자체는 심플하며, 인수는 3개뿐입니다.

ScheduleWakeup({
  delaySeconds: 270,
  reason: "checking long bun build",
  ...
  • delaySeconds: 다음에 깨어날 초 단위 시간 ([60, 3600] 사이로 clamp됨)
  • reason: 왜 그 간격으로 설정했는지에 대한 한 문장. 텔레메트리(Telemetry) 및 사용자에게도 보임
  • prompt: 깨어났을 때 자신에게 재입력할 문자열. 동일한 /loop 프롬프트를 그대로 전달함

prompt를 전달하지 않으면 루프가 종료됩니다. 이것이 "그만둘 타이밍"을 판단하는 포인트가 되기도 합니다.

5분의 벽: 캐시 TTL과의 관계

이 부분이 가장 빠지기 쉬운 함정인데, Anthropic의 프롬프트 캐시(Prompt Cache)는 TTL이 5분입니다. 즉,

  • 300초 미만으로 깨어남 → 캐시가 유지된 상태(Warm) → 저렴하고 빠름
  • 300초를 초과함 → 캐시 미스(Cache Miss) → 전체 문맥을 다시 읽음 → 느리고 비쌈

따라서 "딱 5분"이 가장 손해입니다. 캐시는 만료되는데, 긴 시간을 확보한 이점도 없는 최악의 상황(worst-of-both)이 됩니다.

제가 지키고 있는 기준은 다음과 같습니다:

상황delaySeconds
상태가 곧 변할 것 같을 때 (빌드 상황 관찰, 작업 진행 확인)60~270
...300~600 사이의 애매한 값은 사용하지 않음

"5분 정도"라고 생각될 때는, 270초로 낮추어 캐시를 남기거나, 아니면 20~30분으로 늘려 한 번의 캐시 미스 비용을 길게 상쇄하거나 둘 중 하나를 선택합니다.

매번 prompt를 전달하는 것을 잊어버림

실수 포인트 1: 처음에 제가 저지른 실수입니다. 동적 모드에서는 스스로 prompt를 매번 명시적으로 전달하지 않으면, 다음 tick에서 "무엇을 해야 하는지"를 잊어버립니다.

제대로 의식하지 않으면, 5분 뒤에 깨어난 Claude가 "어라, 나 뭐 하러 깨어난 거지?" 상태가 됩니다.

대책: /loop의 프롬프트를 변수에 담아, 매 tick마다 동일한 것을 전달한다는 것을 처음에 결정해 둡니다.
ScheduleWakeup을 호출하는 흐름을 템플릿화해 두면 사고를 줄일 수 있습니다.

reason이 부실하면 스스로 곤란해짐

실수 포인트 2: reason은 짧은 한 문장이기에 대충 적기 쉽지만, 이것이 나중에 효과를 발휘합니다.

"waiting"이라고만 적은 tick과 "checking long bun build, expected ~8min"이라고 적은 tick은, 다음에 깨어났을 때 자신에게 전달되는 인계 사항이 완전히 다릅니다. reason미래의 자신에게 남기는 메시지라고 생각하고 상황을 제대로 적도록 하고 있습니다.

사용자에게도 보이기 때문에, 적당한 reason으로 인해 "의문의 30분 대기"가 실행되면 사용자로부터 "이거 뭐 기다리는 거예요?"라는 질문을 받는 사고도 발생합니다 (실제로 발생했습니다).

빠졌던 포인트 3: 종료를 잊는 것

동적 모드는 prompt를 전달하지 않으면 종료되지만, 이를 잊으면 영원히 루프(loop)하게 됩니다.

특히 실수하기 쉬운 경우가, "지금 tick에서 작업이 완료되었다"고 판단했음에도 반사적으로 ScheduleWakeup을 호출해 버리는 케이스입니다. 완료되었다면 루프도 종료되어야 합니다.

나만의 규칙: tick의 마지막에 "다음 tick에서 할 일이 있는가"를 반드시 한 번 자문한다. 없다면 ScheduleWakeup을 호출하지 않고 조용히 종료한다. 이 규칙 덕분에 루프가 멈추지 않는 사고는 상당히 줄어들었습니다.

실제 운영에서의 활용 사례

실제로 제가 어떻게 사용하고 있냐면,

  • 긴 빌드·테스트 모니터링: 60~270초 간격으로 진행 상황 체크, 완료되면 종료
  • PR babysitting: 1800초(30분) 간격으로 순회, 무언가 발생하면 간격을 짧게 조정
  • 배포 후 모니터링: 초기 270초, 안정화되면 1800초로 연장
  • 유휴 대기 (특정 이벤트 대기): 1800~3600초

"모니터링기는 짧게, 대기기는 길게"라고 동적으로 전환할 수 있는 것이 동적 모드의 가장 큰 장점입니다. 간격을 고정하는 /loop 5m과 비교했을 때 토큰 소비량이 체감상 절반 정도로 줄어들었습니다.

요약

  • /loop에 간격을 전달하지 않음 = 동적 모드. 다음 기상 시점을 Claude가 ScheduleWakeup으로 결정
  • delaySeconds300~600을 피할 것. 캐시 TTL(5분)의 전후 중 한쪽으로 맞출 것
  • 짧은 tick: 60~270초, 긴 tick: 1200초 이상
  • 매 tick마다 prompt를 전달할 것. 전달하지 않으면 종료
  • reason은 미래의 자신에게 남기는 메시지. 구체적으로 작성할 것
  • tick의 마지막에 "다음에 할 일이 있는가?"를 자문한 뒤에 ScheduleWakeup을 호출할 것

동적 /loop는 "Claude에게 자신의 페이스를 결정하게 하는" 첫걸음이며, 이를 운영하다 보면 Claude 내부에 상황 판단 감각이 길러지는 것을 느낄 수 있습니다. 고정 인터벌(fixed interval)에서 졸업하면, 미미해 보이지만 확실한 효과를 볼 수 있습니다.

그럼, 다음에 또 뵙겠습니다.

AI 자동 생성 콘텐츠

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

원문 바로가기
1

댓글

0