
Claude Code의 /loop로 '요건 정의→테스트→배포'를 반나절 동안 자율 주행시켜 얻은 운용 노하우 정리
요약
Claude Code의 /loop 명령어를 활용해 요건 정의부터 배포까지의 개발 사이클을 자율 주행하며 얻은 실전 운용 노하우를 공유합니다. AI에게 개발을 맡기고 인간은 리뷰와 우선순위 결정에 집중하는 효율적인 워크플로우를 제안합니다.
핵심 포인트
- 프롬프트를 품질 게이트와 종료 조건이 포함된 '운용 계약서'로 작성할 것
- BACKLOG.md 파일을 통해 AI와 인간이 태스크 목록을 공유하며 관리할 것
- CI(테스트/lint/빌드)를 루프의 안전망으로 사전에 구축할 것
- 작업 단위를 세밀하게 나누어 토큰 소비를 줄이고 애자일하게 운영할 것
- 인간의 역할은 우선순위 재배치, 피드백, 권한 필요 작업으로 수렴함
Claude Code(터미널에서 동작하는 Anthropic의 AI 코딩 에이전트)의 /loop 명령어를 사용하여, 개인 개발 Web 앱을 대상으로 「요건 정의→설계→개발→검증(lint/테스트/빌드)→배포→수정」 사이클을 반나절 이상 자율적으로 계속 돌려보았습니다.
이 기사는 /loop, /goal 등의 기능 소개가 아니라, 실제로 돌려보며 알게 된 운용 노하우의 정리입니다. 「AI에게 개발을 맡기고, 인간은 방침 결정과 리뷰에 집중하는」 스타일을 시도하고 싶은 분들을 위해 작성했습니다.
- 루프용 프롬프트는 운용 계약서로서 작성한다 (품질 게이트, 보고 형식, 종료 조건까지 전부 포함)
- 태스크 목록을 Markdown 파일(BACKLOG.md)로 공유하고, AI가 위에서부터 소화하며 인간이 언제든 순서를 바꾸는 운용 방식이 최강이다
- 요건 정의와 기입도 AI에게 맡길 수 있다. 대략적인 요구사항을 던지면, Claude Code가 요건으로 구체화하여 백로그(Backlog)에 추가해 준다
- 이터레이션(Iteration)을 세밀하게 나누면 애자일(Agile)의 스프린트(Sprint)처럼 돌릴 수 있다. 되돌아오는 작업(rework)이 작아지고, 토큰(Token) 소비도 절감할 수 있다
- CI(테스트+lint+빌드)는 루프의 안전망이다. 먼저 만들어 둔다
/goal을 설정하면 「모든 태스크 완수」를 강제할 수 있다 (16개 항목을 1턴 만에 완수했다)- 인간의 업무는 「우선순위 재배치·실기 피드백·권한이 필요한 1회성 작업」의 3가지로 수렴한다
실험 대상으로 삼은 것은 제가 혼자 개발하고 있는 소규모 Web 앱입니다. 고유 명칭은 숨기겠지만, 구성은 개인 개발에서 흔히 볼 수 있는 형태이므로, 비슷한 구성이라면 본 기사의 방식은 거의 그대로 사용할 수 있을 것입니다.
- 앱: 가족이 사용하는 기록계 Web 앱 (화면 수는 10개 내외 규모)
- 기술 스택: Next.js (프론트엔드+API) / Supabase (DB·인증) / Vercel (호스팅)
- 배포: GitHub 연동 완료,
git push를 하면 Vercel이 자동으로 빌드 및 운영 환경 배포를 수행하는 구성 - 태스크 관리: 하고 싶은 일을 리포지토리 직하단의
BACKLOG.md에 불렛 포인트로 쌓아둠 (실험 시작 시점에 남은 항목 16개)
즉, 「push하면 운영 환경에 반영되는 개인 개발 앱」과 「할 일 목록」이 있는 상태에서 시작하여, 소화 작업을 AI의 루프에 맡겼다는 이야기입니다.
/loop는 Claude Code에게 동일한 지시를 반복해서 실행하게 하는 명령어입니다. 두 가지 모드가 있습니다.
/loop <프롬프트>: 간격을 지정하지 않으면 동적 모드(Dynamic Mode). 모델이 스스로 다음 실행 타이밍을 결정하여 자율 주행합니다 (배포 대기 시간은 짧게, 사용자 응답 대기 시간은 길게 하는 식의 자기 조절(Self-pacing))/loop 5m <프롬프트>: 고정 간격 모드(Fixed Interval Mode). 세션 내의 cron(정기 실행 작업)으로서 일정 간격으로 실행됩니다 (최장 7일 후 자동 만료되며, 세션을 닫으면 사라짐)- 매일 실행과 같은 장주기라면
/schedule(클라우드 실행)을 안내받게 됩니다.
실제로 사용하며 알게 된 구분법은 다음과 같습니다.
개발 사이클과 같은 「1 이터레이션당 몇 분십수 분」 정도의 작업은 **고정 간격 cron(510분)이 안정적**입니다. 동적 모드는 배포 완료 확인과 같은 「대기」가 포함되는 상황에서 효과적이지만, 후술할 표시 문제가 있었습니다.
루프에 전달할 프롬프트에 할 일 이외의 운용 규칙까지 전부 적는 것이 최대의 요령이었습니다. 실제로 사용한 구성은 다음 5가지입니다.
- 무엇을 할 것인가: 「BACKLOG.md의 남은 백로그를 위에서부터 1 이터레이션 실행」
- 품질 게이트(Quality Gate): 「lint·테스트·빌드를 통과한 후 push」
- 보고 형식: 「결과를 반드시 일본어 텍스트로 보고. 턴의 마지막은 도구 호출(Tool call)이 아닌 텍스트로 종료」
- 지속성: 「이전 작업의 연속이 미완료 상태라면 먼저 그것을 완료할 것」
- 종료 조건: 「백로그가 비게 되면 완료를 기록하고 cron을 스스로 정지」
특히 4)와 5)가 중요합니다. 대화가 길어지면 Claude Code는 오래된 대화 내용을 요약으로 교체하여 컨텍스트(Context)를 절약합니다(Compaction). 이로 인해 과거 경위의 상세 내용이 손실되더라도, 프롬프트 자체가 자기 완결적(Self-contained)이라면 루프는 깨지지 않습니다. 종료 조건을 적어두면 할 일이 없어진 후에 헛도는 현상을 방지할 수 있습니다.
태스크 목록을 BACKLOG.md
라는 Markdown 파일로서 리포지토리에 두면, AI는 위에서부터 순서대로 소화하고, 인간은 언제든 순서를 바꾸거나 추가·삭제할 수 있는 운영 방식이 매우 궁합이 좋았습니다. 내용은 다음과 같은 이미지입니다.
## 남은 백로그 (위쪽이 우선순위 높음)
1. 목록 화면에 날짜 필터 추가하기
2. 그래프 화면의 모바일 표시 깨짐 수정하기
...
- 완료된 항목은 커밋 ID와 함께 「완료됨」 표로 옮긴다. 이것이 진척 로그와 감사 추적 (Audit Trail)을 겸한다.
- 루프 도중 사용자가 버그 보고나 요구사항을 던지면, AI는 백로그보다 우선하여 **끼어들기 대응 (Interrupt handling)**을 하고, 작업이 끝나면 루프로 복귀한다.
- Claude Code는 이미지도 읽을 수 있으므로, 화면 스크린샷 + "이 부분이 이렇게 된다"라는 증상만 붙여넣으면 버그 수정까지 진행된다. 이 경험은 루프 중에도 유효하다.
전용 태스크 관리 도구가 아니라 "그저 Markdown 파일"이라는 점이 포인트입니다. 인간은 에디터로 행을 재배열하기만 하면 되고, AI는 일반적인 파일 편집으로서 읽고 쓰기만 하면 협업이 성립됩니다.
백로그 항목을 인간이 전부 작성할 필요는 없습니다. 대략적인 요구사항을 던지기만 해도, 요건 정의 (Requirements Definition)부터 기입까지 Claude Code 측에서 수행해 줍니다.
예를 들어 "데이터를 나중에 다시 보기 편하게 만들고 싶다"와 같은 모호한 한마디를 던지면, Claude Code가 기존 코드와 화면 구성을 바탕으로,
- 목적 (무엇을 해결하고 싶은가)
- 구체적인 실현 방법 (어떤 화면에 어떤 UI를 추가할지, 기존의 어떤 기능을 사용할지)
- 스코프 (Scope) (이번에 할 것·하지 않을 것)
을 정리하여, 구현 가능한 단위의 태스크로 분해해 BACKLOG.md에 추가해 줍니다. 즉, "요구사항 → 요건 → 기입"의 번역 작업 자체를 AI에게 맡길 수 있다는 뜻입니다.
나아가, 루프 도중 AI 스스로가 깨달은 개선점(리팩터링 (Refactoring) 후보, 테스트 부족, 표시 불일치 등)을 그 자리에서 바로 처리하지 않고 백로그 하단에 기입해 두는 움직임도 보입니다. 인간의 역할은 **기입된 항목을 리뷰하고 순서를 결정하는 것(또는 삭제하는 것)**으로 좁혀집니다.
두서없이 적은 요구사항 메모를 건네며 "이것을 백로그로 정리해 줘"라고 부탁하는 것도 효과적이었습니다. 우선순위의 최종 결정권만 인간이 쥐고 있다면, 기입은 AI에게 맡겨도 문제없습니다.
/goal은 Claude Code에 달성 조건을 설정하는 커맨드입니다. 조건을 만족할 때까지 AI는 턴(한 묶음의 작업)을 종료할 수 없게 됩니다.
/goal 백로그의 태스크가 모두 완료될 것
이를 설정하자마자, 5~10분 간격으로 꾸준히 진행되던 루프가, 1턴 만에 남은 태스크를 연속으로 소화하는 마라톤 모드에 진입했습니다 (남아있던 16개 항목을 1턴 만에 완주).
"조금씩 진행하며 상황을 보고 싶다"면 설정하지 않는 것이 좋습니다. 반대로 "오늘 안에 전부 끝내고 싶다"는 상황에서는 강력한 힘을 발휘합니다.
루프의 내용은 매번 거의 이 형식으로 수렴했습니다.
| 페이즈 | 내용 |
|---|---|
| 요건 정의 | 착수 전에 "무엇을 어떻게 만들지"에 대한 설계 판단을 짧게 선언하게 함 |
| ... |
포인트는 **"검증을 프롬프트로 강제하는 것"**입니다. 적어두지 않으면 생략될 가능성이 있지만, 적어두면 매번 반드시 검증을 통과한 후 push 합니다.
이 형식을 세밀한 단위로 계속 돌리다 보니, 흐름 전체가 그대로 **미니 스프린트 (Mini-sprint)**로서 기능한다는 것을 깨달았습니다. 애자일 (Agile) 용어에 대응시키면 다음과 같습니다.
| 애자일 개념 | 루프 운용에서의 대응물 |
|---|---|
| 프로덕트 백로그 (Product Backlog) | BACKLOG.md |
| ... |
매 이터레이션 (Iteration)의 끝에 "동작하는 것"이 운영 환경에 배포되고, 인간이 그것을 만져보며 피드백을 돌려주는——폭포수 (Waterfall) 모델처럼 전부 만든 뒤에 확인하는 것이 아니라, 동작하는 것을 기반으로 방향을 수정하며 나아가는 개발이 AI와의 사이에서 자연스럽게 성립됩니다.
이터레이션을 세밀하게 나누는 것에는 개발 스타일 외에도 두 가지 실질적인 이점이 있었습니다.
- 재작업(手戻り)이 줄어듭니다: 변경 사항이 작을수록 방향성이 어긋났을 때 더 빨리 알아차릴 수 있습니다. 크게 만들어 놓은 뒤에 "생각했던 것과 다르다"라고 판단되면 코드 재작성 및 디버깅을 처음부터 다시 해야 하지만, 작게 나누어 매번 검증과 실기 확인(実機確認)을 거치면 오차는 해당 1회 이터레이션(Iteration) 분량으로 그칩니다.
- 토큰 소비를 절감할 수 있습니다: 재작업은 곧 토큰의 재소비입니다. 다시 작성하게 된 코드의 생성, 읽기, 디버깅에 사용된 토큰은 모두 낭비됩니다. 또한, 큰 태스크를 한 번의 턴(Turn)에 진행하면 컨텍스트(Context)가 팽창하여 요약(Compaction)이나 과거 대화 내용을 다시 읽는 데에도 토큰을 소모합니다. 작은 이터레이션은 한 턴의 컨텍스트를 짧게 유지할 수 있으므로, 동일한 성과를 내는 데 필요한 총 토큰량을 저렴하게 유지할 수 있었습니다.
"빠르게 만들게 하는 것"보다 "작게 만들게 하여 빠르게 확인하는 것"이 결과적으로 더 빠르고 저렴합니다. 이는 루프(Loop) 운용을 통해 가장 체감한 교훈입니다.
루프로 인해 개발 속도가 올라갈수록 "깨진 상태로 push"하는 사고율도 높아집니다. 유닛 테스트(Unit Test) + CI는 루프 운용과 세트로 초기 단계부터 도입해야 했습니다.
주의할 점 1: GitHub Actions의 워크플로(Workflow) 파일(.github/workflows/ 이하)은 git 인증 토큰에 workflow 스코프(Scope, 권한)가 없으면 push도, API를 통한 생성도 거부됩니다.
gh auth refresh -s workflow
위 명령어로 재인증이 필요합니다(대화형 브라우저 인증이므로 인간의 작업이 필요함).
회피책: Vercel은 배포 시 package.json에 vercel-build라는 스크립트가 있으면 일반적인 build 대신 이를 실행합니다. 이를 이용하면 다음 한 줄을 추가하는 것만으로 "push할 때마다 lint + 테스트 + 빌드가 실행되고, 하나라도 실패하면 배포를 중단"하는 실질적인 CI를 구현할 수 있습니다. GitHub Actions를 생성할 권한이 부족할 때 훌륭한 대안이 되었습니다.
{
"scripts": {
"vercel-build": "npm run lint && npm test && npm run build"
...
}
주의할 점 2: 다음과 같이 파이프(Pipe)를 사용하면 exit code(명령어의 성패를 나타내는 종료 코드)가 파이프 대상의 것이 되어, 빌드 실패를 놓치고 push 하는 사고가 실제로 발생했습니다.
# NG: tail의 exit code가 되어 빌드 실패를 놓침
npm run build 2>&1 | tail
# OK: 파일로 리다이렉트하여 $?를 확인
...
루프 중에도 인간의 손길이 필요한 장면은 남아 있습니다. 제 경우에는 다음 세 가지였습니다.
- DB 권한 설정: Supabase의 RLS(Row Level Security: 행 단위 액세스 제어) 정책과 같은 DDL은 관리 화면의 SQL 에디터에서 실행해야 했습니다.
- 대화형 브라우저 인증: 앞서 언급한
gh auth refresh와 같이 브라우저를 열어 인간이 승인하는 작업. - 비용과 관련된 기능의 채택 여부 판단: 유료 서비스를 사용할지 여부와 같이 돈이 얽힌 의사결정.
원활하게 돌아갔던 방식은 다음 세 가지입니다.
-
AI에게 실행해야 할 SQL이나 명령어를 "복사해서 붙여넣기만 하면 끝나는 형태"로 준비시키고, 인간은 붙여넣어 실행만 하도록 한다.
-
판단이 필요한 것은 선택지 형식의 질문으로 모아서 묻게 하고(Claude Code에는 선택식으로 질문하는
AskUserQuestion이라는 메커니즘이 있습니다), 답변에 따라 루프를 계속한다. -
인간의 작업 대기 시간 동안 루프를 멈추지 않는다. 기다리는 동안 다른 태스크를 진행시킨다.
-
동적 모드(Dynamic Mode)에서 보고가 표시되지 않는 경우가 있었다: 동적 모드에서 AI가 다음 실행을 예약하고 턴을 종료하면, 직전의 보고 텍스트가 터미널에 표시되지 않는 경우가 있었습니다. 고정 cron 방식으로 전환하고 "턴의 마지막은 반드시 텍스트로 끝낼 것"이라고 프롬프트에 명시하여 해결했습니다.
-
이중 실행 주의: 동적 모드의 예약과 고정 cron이 이중으로 작동하면 동일한 태스크가 중복 실행될 수 있습니다. 전환 시에는 한쪽을 확실히 중단해야 합니다.
-
세션 cron은 휘발성이다: 7일 후에 만료되며, 세션을 닫으면 사라집니다. 영구적으로 유지하고 싶다면
/schedule을 사용하세요.
(클라우드 실행)으로 -
코드 블록이 표시되지 않는 환경이 있었다: 중요한 명령은 일반 텍스트(plain text)로도 작성하거나, 파일로 내보낸 뒤 에디터로 여는 방식이 유용한 대안이 되었습니다.
요건 정의서·설계서·운용 가이드를 docs/ 디렉토리에 정비한 후, CLAUDE.md (Claude Code가 매 세션 자동으로 읽어들이는 프로젝트 지침 파일)에 "기능 추가·사양 변경을 하면 동일한 작업 내에서 해당 문서를 업데이트한다"라는 규칙과 기능 및 문서 대응표를 작성했습니다.
이후의 이터레이션(Iteration)에서는 기능 구현과 동일한 커밋(Commit)으로 문서가 업데이트되게 되었습니다. 매번 "문서를 작성해 줘"라고 요청하는 것이 아니라, 규칙으로서 메커니즘에 심어두는 것이 루프(Loop) 운용과의 올바른 조합이라고 생각합니다.
/loop는 "정기 실행 메커니즘"에 불과하지만, 다음의 조합을 통해 "방침을 전달하고 정기적인 보고를 받는" 개발 스타일이 성립되었습니다.
| 요소 | 역할 |
|---|---|
| 루프 프롬프트 (Loop Prompt) | 운용 계약서 |
| ... |
요건 정의·기안부터 구현·배포까지를 AI가 수행하고, 이터레이션을 세밀하게 나누어 진행함으로써, AI를 상대로도 **애자일(Agile) 스프린트에 가까운 "동작하는 결과물 중심의 개발"**이 성립됩니다. 인간의 업무는 우선순위 재조정·실기(Real machine) 피드백·권한이 필요한 단발성 작업의 세 가지로 수렴되었습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Qiita AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기