퇴근하고 다음 날 눈을 떴더니, 새 기능이 구현되고 테스트까지 끝나 리뷰만 남아 있는 상태라면 어떨까요? 바로 자율형 AI 코딩 에이전트가 약속하는 미래입니다. Claude Code 같은 도구를 연속 루프로 돌려, 잠자는 동안에도 코드를 개선하고 배포까지 이어가는 것이죠.
이 글에서는 이런 자기 개선형 에이전트 루프를 구축하는 방법을 다룹니다. 루프 오케스트레이션, 컨텍스트 파일 구조화, 메모리 영속성, QA 검증, 확장, 디버깅, 리스크 관리까지 폭넓게 살펴볼 예정입니다. 하나라도 도움이 되었으면 좋겠습니다.
이 글은 Ryan Carson의 훌륭한 아티클 How to make your agent learn and ship while you sleep을 보완하는 내용입니다. 꼭 함께 읽어보시길 추천합니다. 최근 저녁 자리에서 에이전틱 코딩의 미래에 대해 깊이 있는 대화를 나눴는데, 그가 소개한 기법들을 좀 더 확장해 보고 싶었습니다.
이 접근법의 핵심은 반복적인 에이전트 루프입니다. 흔히 "Ralph Wiggum" 기법이라 불리며, Geoffrey Huntley와 Ryan Carson 같은 개발자들이 널리 알린 방식입니다. 핵심 아이디어는 개발 작업을 아주 작은 단위로 쪼갠 뒤, AI 에이전트를 루프로 돌려 하나씩 처리하게 하는 것입니다.
루프의 각 반복은 다음과 같은 사이클을 따릅니다.
할 일 목록(예: JSON 형태의 작업 목록)에서 아직 완료되지 않은 다음 작업을 선택합니다.
작업을 구현합니다 — 에이전트가 해당 기능이나 수정 사항에 맞게 코드를 작성하거나 변경합니다.
변경 사항을 검증합니다 — 테스트, 타입 체크 등 품질 검사를 실행합니다.
검사를 통과하면 코드를 커밋하여 변경 사항을 코드베이스에 통합합니다.
작업 상태를 업데이트(완료 표시)하고 학습 내용을 기록합니다.
에이전트 컨텍스트를 초기화한 뒤, 모든 작업이 완료되거나 중지 조건에 도달할 때까지 다음 작업을 반복합니다.
매 반복마다 메모리를 초기화하기 때문에 에이전트는 이전 작업에서 쌓인 혼란이 누적되는 것을 방지하고 현재 작업에 집중할 수 있습니다. 이 "무상태이면서도 반복적인" 설계가 안정성의 핵심입니다. AI에게 기능 전체를 한 번에 만들어 달라고 했을 때 발생하는 컨텍스트 오버플로 문제를 해결해 주기 때문입니다.
하나의 거대한 프롬프트로 모델이 흐름을 잃거나 세부 사항을 잊어버리는 대신, 에이전트에게 매번 깨끗하고 범위가 한정된 프롬프트를 제공하여 명확하게 정의된 단일 작업을 수행하게 합니다.
결과적으로 더 깔끔한 코드와 더 적은 환각(hallucination)이 나옵니다. 매 실행이 백지 상태에서 명확한 지시와 함께 시작되기 때문입니다.
아래 그림은 에이전트가 지속적으로 작업을 선택하고, 코드를 작성하고, 테스트를 실행하고, 모든 작업이 통과할 때까지 작업 목록을 업데이트하는 과정을 보여줍니다.
작업을 원자적 사용자 스토리나 태스크로 쪼개는 것이 중요합니다. 각 작업은 한 번의 AI 세션에 들어갈 만큼 작아야 하고, 통과/실패 기준이 모호하지 않아야 합니다.
예를 들어, "대시보드 전체 구축" 대신 "Home, About, Contact 링크가 있는 내비게이션 바 추가"처럼 세분화하고, "현재 페이지 링크가 파란색으로 강조 표시됨"과 같이 구체적인 수락 기준을 명시합니다.
이렇게 세분화하면 에이전트가 각 단계의 "완료 상태"가 무엇인지 정확히 파악할 수 있습니다. 또한 에이전트가 궤도를 이탈할 가능성도 줄어듭니다. 작업이 테스트나 기준을 통과하지 못하면 루프가 즉시 이를 감지하고 방향을 수정할 수 있기 때문입니다.
구현 팁: SPEC을 정의하고 이를 작업 JSON으로 변환하세요. 먼저 기능에 대한 명확한 명세서를 작성합니다. AI를 활용해 엣지 케이스를 구체화하는 것도 좋은 방법입니다.
그런 다음 이를 구조화된 작업 목록(예: prd.json 파일)으로 변환합니다. 여기에는 모든 작은 사용자 스토리와 수락 기준이 포함됩니다. Carson의 /prd 및 /tasks 스킬(Amp/Claude용)을 사용하면 이 변환 과정을 자동화할 수 있습니다.
결과물은 에이전트 루프가 단계별로 실행할 수 있는, 기계가 읽을 수 있는 할 일 목록입니다.
루프 실행은 간단한 스크립트로 할 수 있습니다. Carson의 구현에서는 말 그대로 Bash 스크립트나 Python 스크립트(예: ralph.sh)로 프롬프트 템플릿을 넣어 AI 에이전트를 반복 호출합니다. Amp이나 Claude Code에서는 CLI 명령이나 플러그인으로 같은 효과를 낼 수 있습니다. 예를 들어 Amp의 CLI를 사용한다면, 다음과 같은 의사 코드 루프를 실행할 수 있습니다:
while :; do
amp run \-s prompt.md \-o progress.txt \# Run Amp with the prompt, save output
if grep \-q "\<promise\>COMPLETE\</promise\>" progress.txt; then break; fi
done
실제로 루프 스크립트는 작업 목록을 불러오고, 다음 미완료 작업을 선택하고, 관련 코드 파일과 가이드라인 등의 컨텍스트를 포함한 프롬프트를 구성한 뒤 AI 모델을 호출합니다. 모델의 응답이 성공 또는 실패를 나타내면, 스크립트가 코드 변경 적용과 테스트 실행을 처리합니다. 이 과정은 모든 작업이 완료되거나 최대 반복 횟수에 도달할 때까지 반복됩니다.
핵심은 각 반복이 독립적이라는 점입니다. 에이전트는 매번 새로 생성되며, 보통 새로운 Claude나 GPT 프로세스로 실행됩니다. 완전히 백지 상태로 시작하되, 필요한 컨텍스트만 매번 새로 주입하는 방식입니다.
복합 루프: 단일 작업 시퀀스를 넘어, 고급 워크플로에서는 여러 단계의 루프를 오케스트레이션합니다.
Compound Product는 오픈소스 시스템으로, 먼저 분석 루프(AI가 일일 보고서를 읽고 무엇을 만들지 파악)를 실행한 뒤 계획 루프(PRD와 작업 목록 생성)를 거쳐, 마지막으로 실행 루프(작업을 구현하는 코딩 에이전트)를 돌립니다. 이런 복합 파이프라인 덕분에 에이전트가 기능을 코딩할 뿐 아니라, 어떤 기능의 우선순위가 가장 높은지까지 스스로 판단합니다.
모든 프로젝트에 이 수준의 자동화가 필요하지는 않겠지만, 루프를 연쇄적으로 연결할 수 있다는 점에서 주목할 만합니다. 하나의 에이전트 출력(예: 작업 목록이나 브랜치 이름)이 더 큰 지속적 전달 시스템 내에서 다른 에이전트의 입력이 되는 구조입니다.
이 에이전트 루프에서 가장 강력한 메커니즘 중 하나는, 반복 간에 지식을 이어주는 영속적 컨텍스트 파일의 활용입니다.
하나의 AI 세션이 모든 것을 기억하도록 "억지로 늘리려" 하기보다는(컨텍스트 윈도우를 넘어서면 불가능하므로), 중요한 정보를 디스크에 명시적으로 기록해 이후 프롬프트에 다시 주입합니다. 이를 위한 대표적인 파일이 보통 AGENTS.md라 불리며, MEMORY.md 등 비슷한 이름을 쓰기도 합니다.
AGENTS.md란? 에이전트가 발견한 내용, 프로젝트 규칙, 이후 모든 에이전트가 알아야 할 가이드를 축적하는 일종의 러닝 노트북입니다.
작업이 끝날 때마다 루프가 핵심 학습 내용을 추가할 수 있습니다. 예를 들어 "참고: 이 코드베이스는 Y에 라이브러리 X를 사용하므로 해당 패턴을 따를 것"이나 "주의: 사용자 모델 업데이트 시 감사 로그도 반드시 함께 업데이트"와 같은 식입니다.
시간이 지나면서 이 파일은 에이전트가 과거 실수를 반복하지 않도록 안내하는 귀중한 힌트 모음이 됩니다. Carson의 Compound Product 철학에 따르면, "에이전트가 AGENTS.md를 업데이트하고, 발견한 패턴을 향후 반복을 위해 문서화한다"고 합니다. 즉, 각각의 개선이 말 그대로 이후의 개선을 더 쉽게 만듭니다. 에이전트가 코드베이스의 구조와 작업 방식에 대한 지식 베이스를 점점 축적해 나가기 때문입니다.
지식 베이스 구조화: AGENTS.md를 섹션별로 정리해 사람과 AI 모두 쉽게 읽을 수 있게 구성하세요. 예를 들면:
패턴 & 규칙: 상위 수준의 패턴 (예: "이 프로젝트는 SSR을 사용하며, UI 컴포넌트는 /components에, API는 /routes에 위치").
주의사항: 에이전트나 개발자가 겪었던 함정 ("새 enum 추가 시 constants.ts 파일도 업데이트하지 않으면 테스트가 실패함").
스타일/선호사항: 코딩 스타일 관련 메모 ("설정된 ESLint 규칙을 따를 것; 클래스보다 함수형 컴포넌트 선호", "기존 테스트처럼 pytest fixture 사용").
최근 학습/변경사항: 최근 이슈와 해결 방법 요약.
항목은 간결하고 사실에 기반해야 합니다. 모델을 안내하는 프롬프트 보조 자료 역할을 해야 하기 때문입니다. 많은 AI 코딩 도구(Claude Code, Cursor, Amp)는 AGENTS.md나 README.md 같은 파일이 있으면 프롬프트 컨텍스트에 자동으로 포함합니다. 예를 들어, 에이전트가 새 반복을 시작할 때 Amp은 저장소를 스캔하여 AGENTS.md 내용을 가져와 모델에 프로젝트 컨텍스트를 제공합니다.
컨텍스트 주입 전략: 컨텍스트 크기에 유의하세요. 지식 파일이 커지면 매 작업마다 전부 주입하고 싶지 않을 수 있습니다(컨텍스트 비대화는 성능을 떨어뜨리거나 모델이 지시를 무시하게 만들 수 있습니다).
AGENTS.md를 핵심 내용 중심으로 유지하고 최신 상태를 관리하는 것이 좋습니다. 오래된 정보는 필요하면 별도 파일로 아카이브하세요. 고급 설정에서는 검색 기반 방식을 쓰기도 합니다. 예를 들어 AGENTS.md를 주제별로 여러 파일로 나누고, 현재 작업과 관련된 섹션만 포함하는 것입니다. 하지만 대부분은 더 단순한 접근으로도 충분합니다. 가장 관련성 높은 팁만 남기고, 프로젝트와 함께 점진적으로 키워나가면 됩니다.
사용 예시: 에이전트가 더 이상 사용되지 않는 API를 사용하려 했고, 여러분이 이를 발견했다고 가정해 봅시다.
루프를 멈추고 AGENTS.md에 다음과 같은 메모를 추가할 수 있습니다:
"v1/users 엔드포인트는 더 이상 사용되지 않음. 대신 v2/users를 사용할 것."
다음에 에이전트가 관련 작업을 수행할 때 이 메모를 보고 더 이상 사용되지 않는 API를 피하게 됩니다. 사실 에이전트에게 직접 이 작업을 시킬 수도 있습니다:
"아니, 이전 엔드포인트를 쓰지 마. 대신 새로운 v2/users API를 사용해. AGENTS.md에 이 내용을 기록한 다음 계속 진행해."
이 실시간 피드백 기법은 개발자 Eric J. Ma가 "향후 에이전트의 동작을 개선하는 영속적 선호도 기록을 만드는" 방법으로 강조한 바 있습니다.
에이전트는 수정 내용을 충실히 AGENTS.md에 추가하고 새 지시에 따라 작업을 이어갑니다. 사실상 실수로부터 학습하는 셈입니다.
마지막으로, AGENTS.md의 지식을 여러 에이전트나 실행 간에 공유하는 것도 고려해 보세요. 서로 다른 프로젝트나 병렬 작업을 위해 여러 루프를 돌린다면, 공통 지식을 중앙화할 수 있습니다. Eric Ma의 MCP(Model Context Protocol) 서버는 이런 컨텍스트를 다양한 에이전트에 일관되게 저장하고 제공하는 시스템의 한 예입니다. 쉽게 말해, 모든 에이전트 세션이 참조하는 공유 위키나 마크다운 파일 세트만으로도, 여러 자율 에이전트가 함께 작업할 때 일관성을 확보할 수 있습니다.
AGENTS.md 외에도, 견고한 에이전트 루프는 여러 영속성 메커니즘을 활용하여 반복 간에 상태를 유지하고 망각을 방지합니다. Carson의 Ralph 루프 구현에서는 실행 간에 최소 네 가지 메모리 채널을 사용합니다:
Git 커밋 히스토리: 매 반복의 코드 변경이 커밋되므로, 다음 반복에서 git diff를 실행하거나 저장소를 확인해 무엇이 바뀌었는지 볼 수 있습니다. 에이전트가 이전 코드를 기억할 필요 없이 저장소에서 직접 읽으면 됩니다. 커밋 메시지 자체도 컨텍스트를 제공합니다("Iteration 5: 내비바 컴포넌트 추가"). Amp이나 Cursor 같은 도구에서는 에이전트가 적절한 권한만 있으면 git log나 git diff를 자율적으로 실행하여 버전 관리에서 컨텍스트를 수집할 수 있습니다.
진행 로그(progress.txt): 매 사이클마다 무슨 일이 있었는지 기록하는 일반 텍스트 로그입니다. 어떤 작업을 시도했고 통과 또는 실패했는지, 에러 메시지나 발견 사항이 무엇인지를 담습니다. 시간순 메모리 역할을 합니다. 루프가 멈추거나 디버깅이 필요하면 progress.txt를 확인해 어디서 문제가 생겼는지 파악할 수 있습니다. 에이전트 역시 반복 시작 시 progress.txt(또는 관련 부분)를 읽도록 프롬프트할 수 있어, 이전에 무엇을 시도했는지 떠올릴 수 있습니다. 에이전트의 일지라고 생각하면 됩니다.
작업 상태(prd.json 또는 작업 목록): 작업이 완료 표시되거나 passes: true/false 필드가 토글되면 JSON 파일이 업데이트됩니다. 이 파일이 각 요구사항의 상태를 영속적으로 관리합니다. 에이전트가 중단 후 재시작하더라도 prd.json을 불러오면 어떤 작업이 남았는지 정확히 알 수 있습니다. 에이전트 루프 스크립트는 이미 완료된 작업을 건너뛰고 미완료 작업에 집중합니다. 중복 작업을 방지하고 진행 상황을 한눈에 파악할 수 있습니다.
에이전트 지식(AGENTS.md): 앞서 살펴본 대로, 과거 실행에서 축적된 지혜를 담는 장기 시맨틱 메모리입니다.
이들이 합쳐져 복합 학습 루프를 형성합니다. 에이전트가 머신러닝 의미에서 "온라인 러닝"을 하는 것은 아니지만, 체계적으로 결과를 기록하여 다음 반복(또는 다음 프로젝트!)이 그 학습의 혜택을 받게 됩니다.
에이전트가 알아낸 모든 수정 사항이나 패턴은 다음 실행의 컨텍스트에 반영됩니다. Compound Product의 README가 말하듯, 각각의 개선이 향후의 개선을 더 쉽게 만들어야 한다는 철학입니다.
수십 번의 반복을 거치면서, 에이전트의 효율성은 실제로 향상될 수 있습니다. 실수를 반복하지 않고 학습한 규칙을 따르게 되기 때문입니다.
플러그인 기반 메모리 확장도 활용할 수 있습니다.
예를 들어 Claude Code는 "스킬"과 마켓플레이스 플러그인을 지원합니다. 각 코딩 세션의 요약을 자동 저장하고 다음에 불러오는 스킬을 만들 수도 있을 것입니다. Amp의 자동 핸드오프 기능은 사실상 단기 메모리로 작동합니다. 컨텍스트 윈도우가 넘치려 할 때, 그때까지의 대화를 요약하여 새 세션으로 넘겨줍니다. 이렇게 하면 작업 도중 컨텍스트가 소실되는 것을 방지할 수 있어, 매우 큰 작업이나 복잡한 리팩터링에 유용합니다.
더 실험적인 환경에서는 벡터 데이터베이스를 활용해 메모리를 저장하고 검색하기도 합니다. 예를 들어 매 반복 후 diff나 에러 메시지를 임베딩하고 설명과 함께 벡터를 저장합니다. 새 반복을 시작하기 전에 DB에서 유사한 과거 사례를 검색해 에이전트에 제공하는 방식입니다.
이렇게 하면 "이전에 이런 실패한 테스트를 본 적이 있고, 이렇게 고쳤었지"를 인식하는 데 도움이 됩니다. 하지만 이런 접근은 복잡성을 높이며, 에이전트가 직접 읽을 수 있는 단순한 산출물(파일과 로그)을 성실히 관리한다면 굳이 필요하지 않을 수도 있습니다.
팁: 어떤 영속성 방식을 사용하든, 에이전트가 실제로 이를 활용하고 있는지 주기적으로 확인하세요. 메모리 파일은 향후 실행의 프롬프트에 주입되어야만 의미가 있습니다.
프롬프트 템플릿이나 에이전트 설정에서 AGENTS.md와 최근 progress.txt 항목이 포함되어 있는지 확인하세요. Amp과 Claude에서는 기본적으로 progress.txt 같은 파일이 자동 로드되지 않을 수 있으므로, 프롬프트에 "다음은 이전 실행의 메모입니다:"와 같이 작성하고 내용을 포함하면 됩니다.
Carson의 설정에서는 프로젝트에 맞게 프롬프트 템플릿(예: prompt.md 또는 CLAUDE.md)을 커스터마이징하는 것을 권장합니다. 프로젝트별 컨텍스트를 불러오거나 특정 지시를 강조하는 섹션을 추가할 수 있습니다.
자율 에이전트가 안정적으로 동작하는 코드를 만들려면 자동화된 검증이 필수입니다. 검증 없이는 에이전트가 자신이 성공했다고 믿으면서 버그나 빌드 실패를 태연히 양산할 수 있습니다. 견고한 에이전트 루프는 테스트와 기타 검증을 사이클의 핵심 구성요소로 다룹니다:
단위 테스트 및 통합 테스트: 탄탄한 테스트 스위트가 있으면 결과물의 품질이 크게 향상됩니다. 에이전트는 작업 구현 후 npm test나 pytest를 실행할 수 있습니다. 테스트가 실패하면 루프는 작업이 실제로 완료되지 않았음을 인지하고, 에이전트에게 코드 수정을 요청합니다. 이상적으로는 prd.json의 모든 사용자 스토리에 최소 하나의 테스트가 연결되어 있어야 합니다(수락 기준이나 저장소 테스트 파일 내에). 더 나아가 에이전트에게 코딩 전에 테스트를 먼저 작성하도록 지시하거나(TDD 방식), 앱의 UI 상태를 스냅샷으로 비교하게 할 수도 있습니다. 하지만 최소한 매 반복마다 기존 테스트를 실행해야 합니다.
타입 체크 및 린트: 정적 분석 도구(MyPy나 tsc 같은 타입 체커, ESLint/Flake8 같은 린터)는 훌륭한 자동 피드백 수단입니다. 오류를 빠르게 잡아줍니다. 코드 커밋 전 루프의 품질 검사 단계에서 실행할 수 있습니다. 예를 들어 config.json에서, 에이전트가 코드를 작성한 뒤 npm run typecheck && npm run lint를 실행하고 모두 성공해야만 다음으로 넘어가도록 설정할 수 있습니다. 이렇게 하면 에이전트가 오류 위에 오류를 쌓는 상황을 방지합니다.
루프 내 지속적 통합(CI): 고급 설정에서는 CI 파이프라인과 연동하기도 합니다. 예를 들어 Cursor의 멀티 에이전트 실험에서는 프로젝트 완료 여부를 "심판" 에이전트가 판단할 수 있었는데, 여기에는 GitHub Actions CI가 그린인지 확인하는 것이 포함될 수 있습니다. 더 단순한 단일 에이전트 루프에서는 빌드 스크립트나 CI 체크를 로컬에서 검증 단계로 실행하여 이를 시뮬레이션할 수 있습니다. 루프는 위험 신호에서 멈춰야 합니다. 체크가 실패하면 에이전트가 이를 처리하거나, N번 시도 후에도 막혀 있으면 해당 작업을 미해결로 표시하고 다음으로 넘어가야 합니다.
AI 자체 평가(선택사항): 자동화된 테스트를 쉽게 작성하기 어려운 경우(예: 테스트 프레임워크 없는 UI 변경), 에이전트 자체를 검증에 활용할 수 있습니다. 예를 들어 프론트엔드 작업에서 Carson의 에이전트는 dev-browser 스킬을 사용합니다. 에이전트가 헤드리스 브라우저를 띄워 페이지로 이동한 뒤, UI 요소가 존재하는지 또는 인터랙션이 정상 작동하는지 확인합니다. 이는 본질적으로 에이전트 주도의 통합 테스트입니다. 검증에 실패하면 에이전트가 다시 시도해야 한다는 것을 인식합니다. 강력한 기능이지만, 에이전트가 코드를 실행하거나 브라우저를 제어하는 것이므로 샌드박싱 환경을 갖추어야 합니다(안전성에 대해서는 뒤에서 더 다룹니다).
전문가 인사이트: AI 에이전트가 애초에 좋은 테스트를 작성하게 하려면 어떻게 해야 할까요? Simon Willison에 따르면, 가장 좋은 방법은 직접 모범을 보여주는 것입니다. 코드베이스에 고품질 테스트를 유지하면, 에이전트가 자연스럽게 그 패턴을 따라 합니다. LLM 기반 코더는 자신이 참조하는 코드의 스타일을 따르는 경향이 있습니다. 저장소에 기존 컴포넌트에 대한 명확하고 간결한 테스트가 있으면, 에이전트에게 새 기능을 추가하라고 했을 때 유사한 수준의 테스트를 작성하는 경우가 많습니다.
Willison은 프로젝트에 깔끔한 테스트가 갖춰져 있으면 "에이전트가 추가하는 새 테스트도 기존과 동일한 품질을 유지하는 경향이 있다"고 말합니다. 또한 에이전트에게 좋은 예시를 직접 참조하도록 지시하는 것도 추천합니다. 예를 들어 "[해당 파일]의 테스트 스타일을 따라라"와 같이 말하거나, 특정 패턴을 확인하기 위해 다른 저장소를 클론하라고 지시할 수도 있습니다. 이런 컨텍스트 시딩은 에이전트의 결과물 품질을 크게 높이고, 나중에 부실한 테스트를 수정하는 데 드는 시간을 줄여줍니다.
실무에서는 에이전트가 처음부터 테스트를 작성하는 것을 항상 신뢰하지 않을 수 있습니다. 많은 개발자가 테스트를 직접 작성하거나 최소한 리뷰하는 것을 선호합니다. 그럼에도 루프 안에서 해당 테스트를 실행하는 것은 필수입니다. 이를 통해 에이전트가 코드가 진정으로 명세를 충족할 때만(테스트 통과가 그 대리 지표) "완료"로 인식하는 피드백 루프가 만들어집니다. 이 에이전틱 QA 루프가 단순한 "코드 생성" 과정을 신뢰할 수 있는 엔지니어링 워크플로로 바꿔줍니다.
지금까지는 하나의 에이전트가 작업 목록을 순차적으로 처리하는 경우를 살펴봤습니다. 더 빠르게 여러 작업이나 여러 프로젝트를 동시에 처리하고 싶다면 어떨까요? 최근 업계 실험들에서는 하나의 코드베이스에 수십에서 수백 개의 에이전트를 동시에 실행하는 시도가 이루어지고 있습니다.
아직 일상적인 개발에서 흔하지는 않은 최첨단 영역이지만, 이런 루프의 확장 가능성과 한계를 이해하는 데 좋은 참고가 됩니다.
병렬 에이전트의 과제: 같은 저장소에 여러 에이전트를 단순히 돌리면 조율과 충돌 문제에 부딪힙니다. 예를 들어 두 에이전트가 같은 작업을 선택하거나, 한 에이전트의 코드 변경이 다른 에이전트의 작업을 깨뜨릴 수 있습니다. 초기에 공유 파일 잠금 메커니즘을 사용한 시도에서는, 에이전트들이 멈추거나 서로를 기다리느라 시간을 낭비하는 문제가 드러났습니다. 또한 에이전트가 위험 회피적으로 변하기도 했는데, 자유경쟁 시스템에서 어떤 에이전트도 어려운 작업에 대한 "책임감"을 느끼지 않아 모두가 아주 작고 안전한 변경만 하고 크고 복잡한 작업은 피하는 현상이었습니다.
플래너-워커 모델: 더 성공적인 패턴은 에이전트 간에 계층 또는 역할 분담을 도입하는 것입니다. 예를 들어 Cursor의 Wilson Lin은 에이전트 군집 내에서 플래너 에이전트와 워커 에이전트를 활용하는 방식을 설명합니다. 플래너는 프로젝트 매니저 역할로, 전체 코드베이스를 읽고 무엇을 해야 하는지 결정하며 작업을 생성합니다(재귀적으로 하위 작업까지 만들기도 합니다). 워커는 이 작업을 받아 전체 그림은 신경 쓰지 않고 구현에만 집중합니다.
반복이 끝나면 심판(Judge) 에이전트가 목표(예: 프로젝트 완료)의 달성 여부를 평가합니다. 이 접근법은 에이전트의 방향 없는 배회를 방지하고 처리량을 크게 끌어올렸습니다. Cursor 팀은 수백 개의 에이전트를 협업시켜 웹 브라우저를 구축하면서, 일주일 만에 1,000개 이상의 파일에 걸쳐 100만 줄이 넘는 코드를 생산했습니다.
이 정도 규모가 필요하지는 않겠지만, 다른 용도로 여러 루프를 병렬 실행하는 것은 충분히 가능합니다. 예를 들어 하나의 에이전트 루프는 프론트엔드 작업에, 다른 하나는 백엔드 작업에 동시 투입할 수 있습니다(코드베이스의 다른 부분이나 다른 브랜치에서 작업).
이 경우 충돌을 최소화하기 위해 작업 범위를 명확히 분리해야 합니다.
또 다른 시나리오는 별도의 피처 브랜치마다 야간 루프를 돌리는 것입니다. 예를 들어 10개 기능이 대기 중이면, 10개 브랜치에 10개 에이전트 프로세스를 실행합니다. Ryan Carson은 궁극적으로 창업자들이 매일 밤 10개 이상의 루프를 돌리게 될 것이라고 예측합니다. 각 루프는 동일한 원칙을 따르지만, 그 결과물을 통합하려면 좋은 CI 관행이 필요합니다(여러 명의 인간 엔지니어가 동시에 작업할 때와 마찬가지입니다).
조율 도구: 여러 에이전트가 같은 프로젝트를 다뤄야 한다면, 조율용 파일이나 간단한 API를 통한 통신을 고려하세요. 잠금 체계를 갖춘 공유 tasks.json이 하나의 방법이지만, 앞서 언급했듯이 파일 잠금은 까다로울 수 있습니다. 더 가벼운 접근은 "교통 정리" 스크립트가 큐를 사용해 에이전트에 작업을 배정하는 방식입니다.
멀티 에이전트 워크플로를 처리하는 에이전트 오케스트레이션 플랫폼도 등장하고 있지만, 현재로서는 대부분 커스텀 구축이나 연구 프로젝트 수준이지 기성 솔루션은 아닙니다.
오늘날 대부분의 고급 사용자에게 확장이란 단순히 넓히기보다는 더 깊이 반복하는 것을 의미합니다. 관리가 어려운 에이전트 군집을 띄우기보다, 유능한 에이전트 루프 하나를 밤새 또는 며칠에 걸쳐 복잡한 프로젝트에 돌리는 것이 더 생산적인 경우가 많습니다. 모델 성능이 향상되면서 단일 에이전트의 장기 실행 능력도 점점 좋아지고 있습니다.
코딩을 자율 에이전트에 맡기려면, 에이전트의 행동에 대한 가시성이 필요합니다. 에이전트를 여러분의 코드를 리뷰하는 실제 엔지니어처럼 대하세요. 에이전트 루프 모니터링과 디버깅을 위한 베스트 프랙티스를 소개합니다:
실시간 로그: 터미널을 열어 에이전트의 출력이나 progress.txt 로그를 실시간으로 확인하세요. 루프는 현재 어떤 작업을 수행 중인지 출력해야 하고, 테스트 결과나 에러를 볼 수 있어야 합니다. 에이전트가 같은 에러에 여러 번 루프하고 있다면 막힌 것이니 개입(중단 또는 힌트 제공)할 수 있습니다. 많은 프레임워크에서 AI의 메시지를 확인할 수 있습니다. 예를 들어 Claude Code 데스크톱 앱에서는 에이전트가 작업하는 동안 대화 스레드가 표시되고, Amp의 CLI는 모델 출력을 단계별로 출력합니다.
체크포인트 커밋: 매 반복마다 git에 커밋하므로, 훌륭한 감사 추적이 됩니다. git log와 git diff를 자주 활용하세요. git log --oneline -5로 에이전트가 만든 최근 커밋 몇 개를 빠르게 확인할 수 있습니다. diff에서 이상한 점이 보이면 너무 진행되기 전에 잡을 수 있습니다. diff 리뷰를 자동화할 수도 있습니다. 예를 들어 diff가 예상보다 훨씬 크거나 작업 범위 밖의 핵심 파일을 건드리면(에이전트가 "탈선"했을 가능성) 루프를 중단하는 식입니다.
| 점검 명령어: 루프에 디버그 명령어를 포함하거나 쉽게 실행할 수 있도록 만들어 두세요. 예를 들어 모든 작업 상태를 보여주는 스크립트(jq '.tasks[] | {id, story, passes}' prd.json)로 진행 상황을 빠르게 요약할 수 있습니다. progress.txt에서 "ERROR"라는 단어를 검색하거나 마지막 N줄을 읽으면 작업 실패 원인을 파악할 수 있습니다. |
에이전트 자기 성찰: 필요하면 에이전트에게 스스로 설명하도록 요청할 수 있습니다. 예를 들어 작업에 막혀 있다면, 프롬프트에 "3번 시도 후에도 테스트가 실패하면 왜 실패하는지 추론과 해결 계획을 출력하라"고 추가할 수 있습니다. 이렇게 하면 에이전트의 내부 사고 과정(chain-of-thought), 이른바 "자기 성찰"이 드러나 단서를 제공할 수 있습니다. 적절히 사용하세요. 과도한 자기 성찰은 루프를 혼란에 빠뜨릴 수 있지만, 디버깅 도구 상자에서 유용한 수단입니다.
성능 지표: 각 반복에 걸리는 시간과 비용(API 토큰)을 로깅하면 유용합니다. 루프에 각 작업과 전체의 소요 시간을 기록하는 계측을 추가할 수 있습니다. 특정 작업이 다른 작업보다 10배 오래 걸린다면, 해당 작업이 복잡하거나 막혀 있다는 신호입니다. 며칠에 걸쳐 "시간당 기능 수" 같은 통계를 수집하면, 모델 변경이나 프롬프트 튜닝이 효과가 있었는지 판단하는 데 도움이 됩니다.
자동 중지 조건: 때로는 문제가 발생합니다. 에이전트가 해결할 수 없는 까다로운 버그 때문에 무한 루프에 빠지거나, 외부 의존성이 다운되어 테스트가 계속 실패할 수 있습니다. 정상 완료 조건 외에도 중지 조건을 설정하세요. 가장 간단한 것은 최대 반복 횟수 제한입니다. 예를 들어 미완료 상태라도 50번 루프 후 중지합니다. 이렇게 하면 비용 폭주와 무한 루프를 방지합니다. 시간 제한("3시간 이상 실행되면 종료")이나 유휴 조건("최근 5번 반복 동안 새 커밋이 없으면 중단")도 설정할 수 있습니다. 이를 통해 에이전트가 밤새 아무 성과 없이 돌아가는 대신, 중단된 상태에서 여러분이 확인할 수 있습니다.
에이전트가 특정 유형의 작업에서 반복적으로 실패한다면, 이를 피드백으로 받아들이세요. 수락 기준이 모호하거나 너무 엄격한 것일 수 있습니다. 또는 AGENTS.md에 특정 프레임워크에 대한 더 나은 힌트가 필요한 것일 수도 있습니다. 실패를 여러분 자신과 에이전트 모두를 위한 학습 신호로 활용하세요.
예를 들어 에이전트가 서드파티 API 사용법을 모르는 컨텍스트 부족으로 어려움을 겪는다면, AGENTS.md에 간단한 사용 예시를 추가하거나 코드에 코멘트로 남기세요. 며칠, 몇 주에 걸친 이런 회고적 개선(페어 프로그래밍 회고와 다를 바 없는)이 시스템을 점점 더 견고하게 만들어 줍니다.
커밋 권한과 셸 실행 권한을 가진 코드 생성 에이전트를 돌리는 것은 강력하지만 위험합니다. 이 리스크를 의도적으로 관리해야 합니다. 핵심 영역과 대응 방법을 살펴보겠습니다:
자율 에이전트가 잘못 설정되면 파일을 삭제하거나, 저장소를 손상시키거나, 보안에 취약한 코드를 푸시할 수 있습니다. 이를 완화하려면:
범위 제한: 에이전트를 피처 브랜치나 포크에서만 실행하고, main 브랜치에서 직접 실행하지 마세요. 이렇게 하면 에이전트가 문제를 일으키더라도 프로덕션 코드는 리뷰 전까지 영향받지 않습니다.
읽기 전용 vs 쓰기 권한: 대부분의 에이전트 플랫폼에는 위험한 작업에 대한 확인 게이트가 있습니다. Amp과 Claude Code에는 자동화를 위해 확인을 건너뛰는 --dangerously-allow-all 같은 플래그가 있습니다.
이런 플래그는 신중하게 사용하세요. 더 안전한 접근은 읽기 전용 명령만 자동 승인하고 쓰기 작업에는 수동 승인을 요구하는 것입니다. 예를 들어 grep, git log, npm test는 확인 없이 허용하되, git push나 rm -rf는 여러분의 명시적 승인 없이 허용하지 마세요. 안전한 작업을 허용 목록에 등록하면, 에이전트가 자유롭게 정보를 수집하면서도 부작용은 억제할 수 있습니다.
이렇게 하면 의도치 않은 명령으로 인한 피해를 제한할 수 있습니다. API 키도 최소 범위로 설정하세요. 에이전트가 GitHub 코멘트를 작성하기 위해 API 키가 필요하다면, 해당 기능만 수행할 수 있는 토큰을 발급하세요.
에이전트가 해로운 행동을 하고 있다면 먼저 종료하고, 원인은 나중에 파악하세요. 리소스 사용량도 모니터링하세요. 에이전트 프로세스가 비정상적으로 높은 CPU나 메모리를 소비한다면(코드에서 무한 루프가 발생했을 가능성), 자동 모니터가 이를 종료하도록 설정할 수 있습니다.
AI 모델은 문법적으로 그럴듯하지만 의미적으로 틀린 결과물(환각)을 생성하기도 합니다. 코딩에서 이는 존재하지 않는 함수를 호출하거나, 잘못된 알고리즘을 사용하거나, 의미 없는 주석을 작성하는 것으로 나타날 수 있습니다. 작업 방향 이탈 위험도 있습니다. 에이전트가 요구사항을 잘못 해석하여 엉뚱한 것을 구현할 수 있습니다.
완화 방법:
강력한 명세와 프롬프트: 명확한 수락 기준과 잘 정의된 작업이 첫 번째 방어선입니다. "POST /api/login을 호출하여 200 OK를 받는다"라고 명시하면, 에이전트가 다른 엔드포인트를 환각할 여지가 거의 없습니다. 모호함이 적입니다. 사전에 작업을 명확하게 정의하고, 프롬프트 템플릿에서 무엇을 해야 하고 무엇을 하지 말아야 하는지 명시하는 데 시간을 투자하세요(시스템 프롬프트/프리앰블에 "명시되지 않는 한 새 의존성을 추가하지 말 것"이나 "이 저장소의 코딩 스타일을 따를 것"을 나열할 수 있습니다).
환각을 잡는 검증: 앞서 언급한 테스트와 타입 체크가 많은 환각을 잡아줍니다(정의되지 않은 함수 호출 등). 타입 에러, 참조 에러, 실패하는 테스트 — 이 모든 것이 에이전트가 비현실적인 것을 만들었다는 신호입니다. 루프 로직은 에이전트에게 이를 수정하도록 프롬프트해야 합니다. 대부분의 경우 코드를 실행하고 에러 출력을 다시 피드백하는 것만으로도 모델이 실수를 인식하고 수정합니다.
주기적 재정비: 장시간 실행되는 루프는 시간이 지나면서 방향이 틀어질 수 있습니다. 작은 오해가 누적되기 때문입니다. 이런 이탈을 방지하는 기법은 주기적으로 새로운 계획 단계부터 다시 시작하는 것입니다. 예를 들어 일정 수의 작업 후에 일시 중단하고, /prd 스킬을 다시 실행하거나 코드베이스를 재스캔하여 남은 작업이 여전히 유효한지 확인합니다. Carson의 팀은 "방향 이탈과 터널 비전을 방지하기 위해 주기적으로 새로 시작할 필요가 있다"고 매우 긴 에이전트 실행에서 언급합니다. 실무적으로는 에이전트가 큰 덩어리를 완료한 뒤 멈추고, 중간 산출물을 리뷰하고, 필요하면 작업 목록을 갱신한 뒤 재개하는 것을 의미합니다.
멀티 모델 교차 검증: 가능하다면 역할별로 다른 모델을 사용하세요. Cursor 실험에서는 계획에 고성능 모델, 코딩에 코드 특화 모델을 섞어 쓰는 것이 하나의 모델로 모든 것을 처리하는 것보다 효과적이었습니다. 사용하는 도구에 따라 여러 모델을 선택할 수 없을 수도 있지만, 핵심 단계에서 보조 모델로 확인하는 것(예: Claude가 생성한 diff를 GPT-4로 검토)만으로도 오류를 줄일 수 있습니다. 일부 개발자는 수동으로 이를 수행합니다. 예를 들어 루프가 끝난 뒤 PR을 머지하기 전에 ChatGPT에 리뷰를 요청하는 식입니다.
프로젝트가 커지면 에이전트에 주입해야 할 컨텍스트 양도 방대해질 수 있습니다. AGENTS.md와 progress.txt에 수백 줄이 쌓이면, 10만 토큰 윈도우에 전부 넣을 수 없을 때도 있습니다. 몇 가지 제안을 드립니다:
오래된 내용 요약: 에이전트 자체를 활용할 수 있습니다. "위 진행 로그의 핵심 사항을 요약하라"고 프롬프트한 뒤 그 결과를 저장하고 원본 로그를 축약합니다. 필요하면 요약의 요약을 만들 수도 있습니다. 중요한 정보를 훨씬 짧은 형태로 보존할 수 있습니다.
컨텍스트 분할: 작업 ID를 활용해 관련된 로그나 코드 부분만 보여주세요. 작업 7이 로그인 페이지에 관한 것이라면, 결제 기능 관련 노트를 프롬프트에 포함할 필요가 없습니다. 일부 자동화 방식에서는 작업과 관련된 키워드로 저장소를 검색해 해당 파일만 컨텍스트에 포함합니다.
모델의 학습 지식 현명하게 활용: 모델이 이미 많은 일반 지식(흔한 라이브러리, 알고리즘 등)을 갖고 있다는 점을 기억하세요. 프로젝트가 매우 새롭거나 생소한 기술을 사용하지 않는 한, 모델이 이미 "알고 있는" 문서를 통째로 넣을 필요는 없습니다. 예를 들어 React 문서 전체를 붙여넣기보다, "이 프로젝트는 Hooks와 Vite를 사용하는 React 프로젝트"라고만 명시하면 모델이 학습 데이터에서 나머지를 채웁니다. 모델의 강점을 활용하여 프로젝트 고유의 세부 사항에 컨텍스트를 집중하세요.
마지막으로, 이 전체 시스템을 살아 있는 프로세스로 다루세요. 모니터링하고, 조정하고, 수시로 사람의 판단을 적용하세요. Ryan Carson은 이런 루프를 구축한 경험에서 프롬프트와 워크플로 통합을 다듬는 데 들어가는 "수작업과 노력"을 강조합니다.
한 번에 완벽한 자율 마법 같은 것은 없습니다. 핵심은 지속적인 개선입니다.
개발자로서 여러분의 역할은 코드를 직접 작성하는 것에서, 프로세스를 큐레이팅하는 것으로 바뀝니다. 명세를 작성하고, 결과를 리뷰하고, AI 에이전트를 상위 수준에서 가이드하는 것이죠(마치 AI 개발 팀의 엔지니어링 매니저처럼).
비용(API 사용량)도 주의 깊게 관찰하세요. 루프에 빠진 에이전트는 토큰을 빠르게 소진할 수 있습니다. 합리적인 한도와 예산 알림을 설정하세요. 하지만 실제로는 제대로 운영하면 ROI가 매우 높을 수 있습니다. Ralph 커뮤니티에서는 엄청난 생산성 향상이 보고되었고, 5만 달러 규모 프로젝트를 수백 달러의 API 비용만으로 완수한 사례도 전해지고 있습니다.
자율 코딩 에이전트는 이미 현실입니다. 신중하게 설정하면 반복적인 코딩 작업을 지속적으로 맡길 수 있습니다.
반복을 거듭할수록, 여러분과 에이전트 모두 더 나아집니다.
AI 증강 소프트웨어 엔지니어링의 다음 단계에 오신 것을 환영합니다. 잠자는 동안 배포하고, 에이전트가 진척을 복리로 쌓아가게 하세요.
이 글은 Gemini를 활용하여 가독성을 개선했습니다