UREKA

AI 에이전트로 반복 작업을 자동화하기 전에 정해야 할 한 가지 기준

반복 작업을 AI 세션에 통째로 맡겼다가 비용과 조용한 실패를 겪고 세운 기준을 정리했습니다. 핵심은 '판단이 필요한 일인가' 하나입니다.


반복 작업을 자동화하려고 AI 에이전트를 붙이면 뭐든 맡길 수 있을 것 같습니다. 매일 아침 데이터를 모아 요약 보고서를 만들고, 로그를 감시하고, 파일을 정리하는 일까지 세션 하나에 시키는 구성이 먼저 떠오릅니다. 저도 그렇게 시작했다가 구성을 거의 다시 짰습니다. 비용이 예상보다 컸고, 어떤 루틴이 죽은 줄도 모르고 며칠을 보냈기 때문입니다. 본문의 금액과 비율은 모두 제 환경에서 직접 잰 값입니다.

기준은 하나, 판단이 필요한가

작업마다 묻습니다. "이 일을 if/else와 정해진 순서로 적을 수 있는가?"

적을 수 있으면 판단이 필요 없는 일입니다. 데이터 받아 오기, 파일 옮기기, 로그에서 에러 줄 세기, 결과 올리기, 어제 작업이 끝났는지 확인하기가 여기에 듭니다. 적을 수 없는 일도 있습니다. 달라진 점 중 무엇이 보고할 만한지 고르기, 표를 읽고 사람이 읽을 요약문 쓰기, 결과물 검수하기, 예외 상황 처리하기. LLM은 여기에만 씁니다. 판단이 없는 일을 LLM에 시켜도 결과는 비슷하게 나옵니다. 달라지는 건 비용과 실패하는 방식입니다.

두 층으로 나누는 법

구분 스크립트 층 LLM 층
맡는 일 실행, 수집, 계측, 감시, 업로드 고르기, 요약문 쓰기, 검수
돌리는 방법 일반 스크립트 + cron, launchd 모델 세션
실행 비용 사실상 0 세션이 뜰 때마다 발생
실패하는 모습 종료 코드와 로그로 분명하게 한도 소진처럼 조용하게

스크립트가 뼈대를 쥐고, LLM은 그 사이의 한 단계로만 끼웁니다.

./collect.sh > today.json     # 수집: 스크립트
cat today.json | claude -p "어제와 달라진 점을 5줄로 요약해 줘" \
  --output-format json --max-turns 3 --max-budget-usd 1 > summary.json   # 판단: 모델 한 번
./send.sh summary.json        # 전달: 스크립트

문서상 claude -p는 비대화형 실행이고, --max-turns와 --max-budget-usd는 이 모드 전용 상한 옵션입니다. 예산 상한은 추정치 기준이라 조금 넘길 수 있습니다.

비용 함정, 세션이 뜨는 것만으로 나가는 돈

판단 없는 일을 LLM 루틴에 맡기면 세션이 뜨는 것만으로 비용이 나갑니다. 제 환경에서는 세션 하나당 대략 0.3~2.5달러로 집계됐습니다. 세션이 시작되면 지침 문서와 도구 목록이 컨텍스트에 올라가고, 그 컨텍스트가 요청마다 나가기 때문입니다. 값은 환경마다 크게 다르니 봐야 할 건 금액이 아니라 구조입니다.

--output-format json 응답의 total_cost_usd를 기록해 두면 어떤 호출이 돈을 쓰는지 보입니다. 다만 문서상 추정치라 실제 청구와 다를 수 있습니다.

감시는 루틴 바깥에서

비용보다 나빴던 건 조용한 실패입니다. 한 루틴이 네 번 연속으로 죽었는데 나흘 동안 아무도 몰랐습니다. 원인은 사용 한도였습니다. 문서에 따르면 한도에 닿으면 Claude Code는 초기화 시각까지 이후 요청을 막습니다.

제가 놓친 건 그다음입니다. 지침에 "실패하면 보고하라"고 적어 두어도 그 지침을 실행하려면 모델 요청이 한 번은 나가야 합니다. 요청이 막히면 루틴은 첫 턴에서 끊기고 보고 단계는 오지 않습니다. 실패를 알릴 책임을 실패할 수 있는 쪽에 맡긴 구조였습니다.

그래서 감시를 바깥으로 뺐습니다. 별도 스크립트(워치독)가 하루 두 번 정해진 시각에 돌면서, 각 루틴이 기대한 주기 안에 성공 기록을 남겼는지 확인하고 없으면 경고합니다. 오류 신호가 아니라 소식 없음을 잡으니 첫 턴에서 죽어도 걸립니다.

  • 워치독에는 LLM을 쓰지 않습니다. 같은 한도에 걸리면 감시가 아닙니다.
  • 종료 코드만 믿지 않고 결과물이 실제로 생겼는지도 봅니다.
  • 스케줄은 OS 스케줄러에 둡니다. /loop 같은 Claude Code 안의 예약은 세션 범위라서, 문서에 따르면 반복 작업이 7일 뒤 만료되고 실행 시각이 최대 30분 늦춰지며 놓친 실행은 따라잡지 않습니다.
  • 노트북이라면 Apple 문서 기준으로 cron은 잠든 동안 건너뛰고 launchd(StartCalendarInterval)는 깨어날 때 실행하며, cron은 비권장입니다.

서브에이전트 위임, 그리고 오히려 비싸지는 경우

메인 세션은 지휘만 하고 실제 작업은 서브에이전트가 하도록 바꿨습니다. 문서 설명대로 서브에이전트는 자기 컨텍스트 창에서 일하고 요약만 돌려주기 때문에 큰 출력이 메인 대화에 쌓이지 않습니다. 함정은 둘이었습니다.

첫째, 출력이 긴 명령을 메인에서 돌리면 오히려 비싸집니다. 긴 작업 하나를 뜯어 보니 메인은 결과물을 한 줄도 쓰지 않았는데 전체 비용의 42%를 차지했습니다. 명령 50번 안팎의 출력이 컨텍스트에 눌러앉아 첫 턴 약 6만 5천 토큰이 마지막 턴에는 약 16만 5천 토큰이 됐고, 그 전체가 요청마다 다시 실렸기 때문입니다. 문서도 요청마다 대화 전체를 보내고 캐시된 부분만 싼 요율로 읽는다고 설명합니다. 지금은 로그가 긴 단계를 통째로 서브에이전트에 맡기고 판정 결과만 받습니다. 훅으로 로그를 미리 걸러 에러 줄만 넘기는 방법도 문서에 있습니다.

둘째, 서브에이전트가 쓰는 토큰도 같은 사용 한도에 잡힙니다. 모델을 지정하지 않으면 호출 시 지정, 정의 파일의 model, 환경변수 CLAUDE_CODE_SUBAGENT_MODEL 순으로 찾고 마지막에는 메인 모델을 물려받습니다. 저는 이걸 빠뜨려 서브에이전트 다섯 개가 메인과 같은 비싼 모델로 돈 적이 있습니다. 가벼운 일에는 model: haiku처럼 명시하세요.

비용 규칙은 한 문서에만

루틴이 늘면 비용 규칙을 루틴마다 지침에 복사하고 싶어집니다. 복사본은 반드시 갈라집니다. 규칙은 한 문서에만 두고 각 루틴에는 "작업 전에 그 문서를 읽는다"만 적습니다.

시작 체크리스트

  1. 작업마다 "if/else로 쓸 수 있는가"를 묻고, 쓸 수 있으면 스크립트로 만듭니다.
  2. LLM은 판단 구간에서만 부르고, 상한을 걸고, 회당 비용을 기록합니다.
  3. 루틴마다 성공 기록을 남기게 하고, LLM 없는 워치독이 주기를 확인하게 합니다.
  4. 서브에이전트에는 모델을 명시하고, 긴 출력은 걸러서 받습니다.

마무리

처음에는 전부 에이전트에게 시키는 쪽이 편해 보입니다. 그 대가는 매번 나가는 세션 비용, 그리고 실패를 스스로 알리지 못하는 구조였습니다. 지금은 새 작업을 붙일 때마다 같은 질문부터 합니다. 판단이 필요한가. 아니면 스크립트로 내리고, 맞으면 그 구간에만 모델을 부릅니다. 도구 동작은 2026년 10월 공식 문서 기준이니, 적용 전에 현재 문서를 다시 확인하세요.

댓글

아직 댓글이 없습니다. 첫 댓글을 남겨보세요.

이메일은 선택이며 공개되지 않습니다. 자세한 내용은 개인정보처리방침을 참고하세요. 스팸·광고·링크, 인신공격성 댓글은 삭제될 수 있습니다.

새 글 소식은 뉴스레터로

무료 뉴스레터로 매일 핵심만 받아보세요.

언제든 수신을 해지할 수 있습니다. 스팸은 보내지 않습니다.