실전 루프 엔지니어링

TMT

https://addyo.substack.com/p/practical-loop-engineering

저는 보통 5개에서 10개 사이의 에이전트를 동시에 병렬로 돌리면서 일합니다. 종료 조건과 제약을 아주 명확하게 잡아둘 수 있다면 기꺼이 에이전트에게 완전히 맡기는 작업이 있고, 반대로 에이전트가 하는 일을 좀 더 가까이서 지켜보며 코드 리뷰를 해야 하는 작업도 있습니다.

그 맥락에서 루프 엔지니어링(loop engineering) 이라는 말을 들어보셨을 겁니다. 몇 달 전에 긴 블로그 글로 다룬 적이 있습니다.

루프란 AI 에이전트가 특정 목표가 달성될 때까지 행동하고, 결과를 검증하고, 접근 방식을 조정하기를 반복하는 자율적이고 자기 교정적인 피드백 사이클입니다

이제는 크게 두 가지 핵심 프리미티브를 놓고 생각하면 됩니다. Claude Code에는 goal 프리미티브가 있어서, 측정 가능한 결승선 같은 특정 목표가 달성될 때까지 경계가 정해진 단일 작업을 밀고 나갈 수 있습니다. 그리고 loop 는 타이머나 고정 간격으로 다시 실행되므로, 변경 작업을 일정에 태우는 용도로 쓸 수 있습니다.

Image

프리미티브가 프리미티브가 되기 전

Claude Code와 Codex에 프리미티브가 내장되기 전에는 루프 엔지니어링이라는 게 대부분 직접 bash 루프를 손수 짜서 돌리는 일이었습니다. 저도 그렇게 접근했고요. 올해 초에 여럿이서 Geoff Huntley의 Ralph 루프를 가지고 이것저것 해보던 걸 기억하실지 모르겠습니다. 실험하고, 워크플로를 공유하고, 뭐가 되고 뭐가 안 되는지 나눴지만, 대부분 개인 프로젝트에서였습니다. 개인 프로젝트라 벽에 부딪혀도 별로 잃을 게 없었으니까요.

루프 엔지니어링에서 어떤 패턴, 어떤 측면이 이제 좀 더 무르익었는지 살펴보면서, 이걸 어떻게 돌봐야 하는지에 대한 감도 더 또렷해졌다고 생각합니다. 지금은 Claude Code와 Codex 프리미티브의 결과물을 대체로 믿고 쓸 수 있습니다. 그만큼은 발전한 거죠. 하지만 동시에 아주 부지런해야 합니다. 최종 목표나 제약이 잘 정의됐는지 제대로 따져보지 않은 채 루프를 방치해 두면 곤란한 상태에 빠질 수 있기 때문입니다. 사용자도 없고 쌓인 복잡성도 없는 신생 코드베이스에 쓸지, 아니면 이를테면 레거시가 얽힌 은행 코드베이스에 쓸지 결정할 때 미묘한 차이를 따져야 하는 이유가 여기에 있습니다.

Claude Code 팀이 루프를 바라보는 틀

Claude Code 팀이 네 가지 종류의 루프에 대한 자신들의 관점을 공개했는데(팀의 글), 제가 프리미티브를 쓰는 방식과도 잘 맞아떨어집니다. 본론에 들어가기 전에 제 나름의 요약부터 보여드리면:

Image

Claude Code 팀에서는 루프를, 에이전트가 중지 조건이 충족될 때까지 작업 사이클을 반복하는 것으로 정의합니다. 무엇이 루프를 촉발하는지, 어떻게 멈추는지, 어떤 Claude Code 프리미티브를 쓰는지, 어떤 유형의 작업에 가장 적합한지를 기준으로 몇 가지 루프 유형을 나눕니다. 모든 작업에 복잡한 루프가 필요한 건 아닙니다. 가장 단순한 해법에서 시작하고, 이 패턴들은 선별적으로 쓰세요.

여러분이 보내는 모든 프롬프트는 매 턴을 여러분이 직접 지휘하는 수동 루프를 시작합니다. Claude는 컨텍스트를 모으고, 행동하고, 결과를 점검하고, 필요하면 반복한 뒤 응답합니다. 우리는 이걸 에이전틱 루프(agentic loop)라고 부릅니다. 예를 들어 Claude에게 좋아요 버튼을 만들어 달라고 해보세요. 코드를 읽고, 수정하고, 테스트를 돌린 다음, 자기 생각에 동작하는 결과물을 돌려줍니다. 그러면 여러분이 직접 그 작업을 확인하고 다음 프롬프트를 씁니다.

팀의 글은 이 사다리를 한 단씩 짚어 갑니다.

goal 기반 루프에 대해:

한 턴으로는 부족할 때가 있습니다. 특히 더 복잡한 작업이 그렇습니다. 에이전트는 반복할 수 있을 때 더 잘합니다. /goal로 완료가 어떤 모습인지 정의해 주면 Claude가 반복을 이어가는 시간을 늘릴 수 있습니다. 성공 기준을 정의해 두면 Claude가 뭐가 "충분히 괜찮은지"를 스스로 판단해 루프를 일찍 끝내 버릴 일이 없습니다. Claude가 멈추려 할 때마다 평가자 모델이 지정된 조건을 확인하고, 목표가 달성되거나 정해 둔 턴 수에 도달할 때까지 다시 작업으로 돌려보냅니다. 통과한 테스트 개수나 특정 점수 기준선 돌파처럼 결정론적인 기준이 그토록 효과적인 이유가 이것입니다. 예: /goal 홈페이지 Lighthouse 점수를 90 이상으로 올려라, 5번 시도 후 중단하라.

시간 기반 루프에 대해:

에이전트 작업 중에는 반복되는 일이 있습니다. 작업 자체는 그대로이고 입력만 바뀌는 경우죠. 매일 아침 Slack 메시지를 요약하는 일이 그 예입니다. 외부 시스템에 의존하는 일도 있는데, 이런 시스템과 맞물리는 간단한 방법은 일정 간격으로 확인하고 바뀐 것에 반응하는 겁니다. 코드 리뷰가 달리거나 CI가 실패할 수 있는 PR이 그 예입니다. 이런 일에는 /loop로 Claude의 실행 시점을 정할 수 있습니다. /loop는 프롬프트를 일정 간격으로 다시 실행합니다. 예: /loop 5m 내 PR을 확인하고, 리뷰 코멘트에 대응하고, 실패하는 CI를 고쳐라. /loop는 사용자 컴퓨터에서 돌기 때문에 컴퓨터를 끄면 멈춥니다. /schedule로 루틴을 만들면 루프를 클라우드로 옮길 수 있습니다.

그리고 사다리 맨 윗단인 능동형 루프(proactive loop)에 대해:

촉발 조건: 이벤트 또는 일정. 사람이 실시간으로 개입하지 않습니다. 중지 기준: 각 작업은 목표가 달성되면 종료됩니다. 루틴 자체는 사용자가 끌 때까지 돌아갑니다. 최적 용도: 버그 리포트, 이슈 분류, 마이그레이션, 의존성 업그레이드처럼 잘 정의된 작업이 반복해서 흘러들어오는 경우. 사용량 관리: 루틴은 더 작고 빠른 모델로 보내고, 판단이 필요한 결정에는 가장 유능한 모델을 씁니다.

팀의 검증 조언은 통째로 옮겨올 만합니다. 수동으로 하던 확인 작업을 Claude가 스스로 적용하는 것으로 바꿔 놓기 때문입니다:

---
name: verify-frontend-change
description: Verify any UI change end-to-end before declaring it done.
---
# Verifying frontend changes
Never report a UI change as complete based on a successful edit alone.
Verify it the way a human reviewer would:
1. Start the dev server and open the edited page in the browser.
2. Interact with the change directly. For a new control (button, input,
   toggle): click it, confirm the expected state change, and screenshot
   before/after.
3. Check the browser console: zero new errors or warnings.
4. Use the Chrome Devtools MCP, run a performance trace and audit
   Core Web Vitals.
If any step fails, fix the issue and rerun from step 1 - do not hand
back partially verified work.

Goal

저는 goal을, 특정 작업 하나를 증명 가능하게 끝날 때까지 밀어붙이는 데 씁니다. 예를 들어 goal로 이렇게 지시할 수 있습니다: 이 화면이 5초 안에 로드되게 만들어라, 될 때까지 계속하라. 그러면 완료 기준이 충족됐는지를 독립적인 평가 검사로 계속 확인합니다. 어떤 도구를 쓸지까지 더 구체적으로 지정해 주면 더 좋습니다.

숫자를 걸고 실제로 돌려본 goal을 꼽자면 몇 가지가 있습니다. GitHub 이슈를 훑는 데 goal을 써 왔습니다. 최근 이슈 10개를 검토해서 닫아라, 또는 최근 이슈 10개를 검토해서 진전시켜라, 이런 식으로요. 이건 절반쯤 열린 과제죠. 아니면: 이 페이지를 50% 더 빠르게 로드되게 만들자. 잘 될 때도 있고 안 될 때도 있지만, 결국은 실험해 보는 게 핵심입니다.

Image

Loop

loop는 스케줄러에 좀 더 가깝습니다. 무언가를 계속 지켜보거나, 일정한 주기로 어떤 패턴을 반복 실행합니다. cron과 비슷하다고 생각하면 됩니다. 로그를 폴링하거나 외부 상태를 모니터링하는 일에 가장 잘 맞습니다. 주기적으로 상황을 점검하는 용도로도 쓸 수 있고요. 일정한 주기로 반복하고 있는 작업이 있다면 loop가 꽤 잘 맞습니다.

Image

무엇을 맡기고, 무엇을 지켜보는가

저는 하루에 에이전트를 5개에서 10개쯤 씁니다. 동시에 돌리는 건 보통 5개 정도가 최대입니다. 그중에는 비교적 안전한 작업들이 있습니다. 이를테면, 내가 이 기능을 구현했으니 문서를 써 달라. 아니면 테스트 커버리지가 충분한지 다시 확인해 달라. 그런 부류의 일이죠. 더 복잡한 문제를 다루고 있거나, 제 딴에는 좋은 스펙을 주고 종료 조건까지 지정했는데도 전부 제대로 해내지 못할 가능성이 꽤 있다는 걸 아는 작업이라면, 더 가까이서 지켜보려고 합니다. 시스템 접근 권한을 준 경우든, 기능이 인증을 건드리는 경우든, 보안이나 금융과 관련된 경우든, 조금이라도 민감한 구석이 있는 작업은 반드시 가까이서 지켜봅니다.

전반적으로, 목표나 종료 조건이 충족됐는지 명확하게 검증할 방법만 갖춰진다면 사람들이 위임을 점점 편하게 여기게 될 거라고 생각합니다. 하지만 그래도 코드를, 지금 생성되고 있는 결과물을 직접 들여다보고 자기 기준에 맞는지 확인해야 합니다.

여기서 중요한 또 하나의 습관은, 작업을 한 에이전트가 그 작업이 괜찮은지까지 판정하게 두지 않는 것입니다. 한 서브에이전트가 변경안을 만들면, 별도의 서브에이전트가 검증합니다.

에이전트가 무언가를 확신하고 있을 때, 검증 에이전트가 미처 예상하지 못한 지점을 잡아낼 수 있습니다. 예컨대 자기가 만든 화면의 기본 성능이 괜찮다고 생각하는데 실은 데스크톱 기준으로만 성능을 평가하고 있고, 정작 여러분이 신경 쓰는 건 모바일 경험인 경우처럼요. 문제의 한 차원에 대해서는 매우 확신하면서 다른 차원은 놓치고 있다는 뜻일 수 있습니다.

Image

그리고 이건 저도 호되게 배웠습니다. 이슈 트래커든 어디 댓글에서든 사용자에게 직접 피드백을 받은 적은 없지만 우리가 놓치고 있는 게 있지 않을까 궁금했습니다. 그래서 에이전트에게 경쟁 제품 몇 개를 살펴보고, 그 격차를 메우면 어떤 모습이 될지 목록으로 정리하고, 푸시는 하지 않은 로컬 PR도 몇 개 만들어 보라고 시켰습니다. 그리고 그 변경 일부를 거의 푸시할 뻔했습니다. 그런데 사실 충분히 꼼꼼하게 보지 않았던 겁니다. 리서치 내용은 통독했지만 구현은 충분히 들여다보지 않았습니다. 작업을 위임했는데, 판단까지 위임하기 직전이었던 거죠. 나중에 변경 내용을 실제로 훑어보고 나서야, 사용자에게 상당한 복잡성을 추가로 안기는 데 비해 얻는 것은, 적어도 제 생각에는, 그리 크지 않다는 걸 깨달았습니다. 그래서 때때로 스스로 점검해야 한다고 느낍니다. 취향과 판단을 에이전트에게 넘기고 있지는 않은지 말이죠. 위임하는 건 작업이고, 그 결과가 자기 기준에 맞는지는 직접 다시 확인해야 합니다.

참고로, goal 뒤에 앉아 있는 평가자는 그런 검사자가 아닙니다. 내용이 좋은지 나쁜지는 어떤 형태로도 보지 않습니다. 대화 기록을 살펴서 지정해 둔 명시적 규칙이 충족됐는지만 확인할 뿐입니다.

/goal Refactor the data-fetching layer in Dashboard.tsx until Lighthouse performance score is >= 92 and LCP is under 1.8s as shown by the Lighthouse CLI output. Do not change the public API of any hooks. Each turn must improve at least one reported metric; abort if two consecutive turns show no improvement. Stop after 10 turns.

매일 돌리는 워크플로

매일 돌리는 워크플로 중 하나는 이렇습니다. 저는 Agent Skills라는 인기 오픈소스 저장소를 운영하고 있습니다. 스타가 8만 개를 넘고, 최근까지만 해도 하루에 리뷰해야 할 풀 리퀘스트가 많게는 80~90개씩 들어왔습니다. 그래서 매일 시간을 들여 이걸 확인하곤 했죠. 이제 loop가 있으니 이렇게 말할 수 있습니다: 24시간마다 또는 12시간마다 GitHub 저장소에서 새로 열린 이슈를 확인해 긴급도 요약을 제공하라, 또는 1차 리뷰를 제공하라, 그런 식으로요.

/loop every 1h "Check the GitHub repository for any new open issues. Provide a bulleted summary of their urgency."
Image

loop와 goal 결합하기

loop와 goal을 결합할 수도 있습니다. loop로 점검을 일정에 태우고, goal로 문제를 해결하는 식입니다. 예를 들면 이렇게요: 24시간마다 loop를 돌려 GitHub에서 bug 라벨이 붙은 이슈를 확인하라. 있으면 goal을 써서 로컬 테스트가 전부 통과할 때까지 수정을 구현하고 브랜치를 푸시하라.

/loop every 24h "Check GitHub for issues labeled 'bug'. If one exists, use /goal to implement a fix until all local tests pass and push the branch."

다만 goal에 얼마나 많은 걸 욱여넣을 수 있는지에는 한계가 있다는 점도 염두에 두세요.

Image

팀의 글에는 이 모든 게 어디로 향하고 있는지 보여주는 조합 예시도 있습니다:

위 프리미티브들은 자동 모드나 동적 워크플로(연구 프리뷰) 같은 다른 Claude Code 기능과 함께 장시간 작업용 루프로 조합할 수 있습니다. 예를 들어 들어오는 피드백을 처리하려면 이렇게 쓸 수 있습니다: 새 리포트를 확인하는 루틴을 돌리는 /schedule(연구 프리뷰), 완료가 어떤 모습인지 정의하는 /goal, 검증 방법을 문서화하는 스킬. 각 리포트를 분류하고, 고치고, 수정을 리뷰하는 에이전트들을 지휘하는 동적 워크플로. 루틴이 권한을 물으러 멈추지 않고 돌아가게 하는 자동 모드. 이걸 합치면 프롬프트는 이런 모습이 될 수 있습니다: "/schedule 매시간: project-feedback 채널에서 버그 리포트를 확인하라. /goal: 이번 실행에서 발견된 모든 리포트가 분류되고, 조치되고, 응답될 때까지 멈추지 마라. 버그를 고칠 때는 워크플로를 써서 병렬 워크트리 세 개에서 해법 세 가지를 탐색하고 심판이 적대적으로 리뷰하게 하라."

분류 시스템이 실제로 하는 일

PR 분류에서 loop와 goal이 함께 돌아가면, 결과적으로 PR과 이슈를 계속 받아들이면서 매일 내 몫으로 쏟아지는 일을 놓치지 않고, 특히 서로 교차 대조까지 할 수 있는 시스템이 생깁니다. 이게 저한테는 정말 큰 도움이 됐습니다. 시스템의 특정 부분을 뜯어고칠 예정인데 이 재작업으로 그 부분을 건드리는 이슈들이 확실히 닫히게 하고 싶다거나, 다른 사람의 작업을 밟지 않게 하고 싶다거나 하는 특정 목표를 진행할 때, 그 조건이 잘 정의되도록 만들 수 있습니다.

예약 작업은 새 PR을 정기적으로 검토하고 명백히 맞지 않는 것들을 닫는 데 아주 유용합니다. 좋은 종료 조건의 예를 하나 들면: 우리에게는 기여 가이드라인이 있고, 거기에는 현재 번역 기여는 받지 않는다는 항목 같은 게 들어 있습니다.

Image

관심이 없어서가 아니라, 들어오는 언어를 우리가 다 하지 못해서 유지보수하기 어렵기 때문입니다. 그래서 기여 가이드라인의 그 항목에 걸리는 이슈나 PR은 닫으라고 지시해 두면, 일정에 태워진 상태에서 정말 잘 해내는 일이 됩니다. 그만큼 우리가 리뷰해야 할 전체 물량이 줄어들죠.

Image

루프로 얻을 수 없는 것

루프 엔지니어링이 어디에는 안 맞느냐는 질문을 자주 받습니다. 일반적으로, 작업이 끝났다는 게 어떤 상태인지, 무엇이 '완료'이고 무엇이 '좋음'인지 분명하게 그려지지 않는다면 이 패턴이 맞지 않을 수 있습니다. 예를 들어 "이 UI 디자인이 좋아질 때까지 계속하라"는 모호한 목표입니다. 그게 무슨 뜻일까요? 누구에게 좋다는 걸까요? 어떻게 평가하죠? 사람의 취향, 주관적인 디자인, 열린 결말의 창의적 탐색이 필요한 작업은 잘 맞지 않습니다. 목표가 꽤 분명하게 그려진다면 루프는 고려해 볼 만한 좋은 선택지라고 생각합니다.

알아둬야 할 세부 사항

루프가 제자리에서 헛돌고 있다는 고전적인 신호 하나는, 같은 명령이 결과 변화 없이 계속 반복 시도되는 것입니다. 같은 명령을 세 번째 실행했는데 두 번째와 달라진 게 없다면 아마 멈출 때가 된 겁니다.

알아둘 만한 세부 사항이 하나 있습니다. 반복 루프는 생성 후 7일이 지나면 만료됩니다. 저는 사람들에게 3일이라고 말해 왔는데, 7일입니다. 그리고 루프는 세션 단위라서 새 대화를 시작하면 멈춥니다. 다만 --resume이나 --continue로 그 세션을 재개하면 7일 기한 안에 있는 반복 작업이 되살아납니다. 세션보다 오래 살아남아야 하는 작업이라면 /schedule이 클라우드에서 돌려 줍니다.

매일 아침 손으로 직접 하고 있는 점검이 있다면, 그게 여러분의 첫 루프입니다. 제 경우엔 쌓여 있는 풀 리퀘스트 더미였습니다.

Image
Edit this page