
루피(Loopy)해지기! 우리가 사랑할 때까지 행동하고, 반응하고, 반복하라
요약
단순한 프롬프트 엔지니어링을 넘어, 에이전트가 스스로 실행하고 피드백을 받아 반복하는 '루프 엔지니어링(Loop Engineering)'의 개념과 실전 사례를 소개합니다. 에이전트가 검색 시스템을 재작성하거나 PR을 관리하는 등 자율적인 워크플로우 설계의 중요성을 다룹니다.
핵심 포인트
- 프롬프트 엔지니어링에서 루프 엔지니어링으로의 패러다임 전환
- 트리거, 피드백 신호, 상태 전달, 종료 규칙 설계의 중요성
- 에이전트가 스스로 프롬프트를 생성하고 개선하는 자율적 구조
- 대규모 에이전틱 엔지니어링을 위한 루프 설계 기술
지난 일주일 동안, 하나의 에이전트(agent)가 내 메모리 엔진(memory engine) 내부의 검색 시스템(retrieval system)을 다시 작성해 왔습니다. 지금까지 이 에이전트는 결정론적 스코어러(deterministic scorer)를 만들고, 수십 번의 실험을 수행하며, 좋은 아이디어는 유지하고 실패한 아이디어는 버렸습니다. 나는 처음에 프롬프트(prompt)를 하나 작성했고 그 과정에서 몇 번의 호출을 했을 뿐입니다 (계속하려면 동전을 넣으세요). 나머지는 루프(loop)가 수행하고 있으며, 아직 끝날 기미조차 보이지 않습니다.
매일 아침 3시 30분, 내가 한 번 작성하고 다시는 보내지 않은 고정 지침에 따라 또 다른 모델이 깨어납니다. 이 모델은 내 에이전트들이 어제 캡처한 내용을 읽고, 무엇을 유지할 가치가 있는지 결정하며, 확신이 있는 결과물은 지식 그래프(knowledge graph)로 승격시키고, 불확실한 것들은 나에게 전달합니다. 아무도 깨어 있지 않습니다. 시스템이 스스로에게 프롬프팅(prompting)을 하고 있는 것입니다.
그리고 지난달 5일간의 기간 동안, 내가 만든 PR 베이비시터(PR babysitter)가 내 오픈 풀 리퀘스트(open pull requests)를 대상으로 수천 번의 에이전트 세션을 실행했습니다. 조사하고, 분류하고, 배정하고, 수정하고, 학습하고, 반복합니다. 감시를 위한 작은 모델(tiny models)과 수정을 위한 프론티어 모델(frontier models)이 사용됩니다. 에이전트와 인간이 코드를 검토함에 따라, 우리는 즉각적으로 반응하고 PR을 자동으로 업데이트합니다.
이 글에서는 내가 대규모 에이전틱 엔지니어링(agentic engineering)을 위해 매일 사용하는 몇 가지 기술을 보여줄 것입니다.
🌀 마침내 이름이 붙여지다
6월에 **루프 엔지니어링 (loop engineering)**이라는 용어가 등장했습니다. Peter Steinberger는 이를 12개의 단어로 정의했습니다: "당신은 더 이상 코딩 에이전트에게 프롬프팅을 해서는 안 됩니다. 당신은 에이전트에게 프롬프팅을 하는 루프(loops)를 설계해야 합니다." 하루 뒤 Addy Osmani가 이 관행의 이름을 붙이고 그 구조를 설명했으며, 2주 후 O'Reilly가 그 에세이를 재출판했는데, 이는 어떤 용어가 공식적으로 등장했음을 알 수 있는 방법입니다. Claude Code를 만든 Boris Cherny는 그 분위기를 다음과 같이 요약했습니다: "나는 더 이상 Claude에게 프롬프팅하지 않습니다."
그 계보는 명확합니다. 프롬프트 엔지니어링 (Prompt engineering)은 우리가 모델에게 무엇을 말하는지에 관한 것입니다. 컨텍스트 엔지니어링 (Context engineering)은 모델이 스스로 그러한 프롬프트를 생성하고 개선하도록 만드는 방법입니다. 루프 엔지니어링 (Loop engineering)은 실행들 '사이'에 일어나는 일들에 관한 것입니다: 트리거 (trigger), 피드백 신호 (feedback signal), 앞으로 전달되는 상태 (state), 그리고 언제 멈출지를 결정하는 규칙 (rule) 말입니다.
이 포스트는 제가 의도치 않게 만들어낸 3부작의 제3막입니다! 지난 1월에는 컨텍스트를 엔지니어링하는 것에 대해 썼습니다. 지난 5월에는 제 프롬프트 하부에서 작동하는 운영체제(operating system), 즉 계약 (contract), 기술 라이브러리 (skill library), 메모리 그래프 (memory graph)에 대해 썼습니다. 이번 글은 그 운영체제가 스스로 작동하기 시작할 때 어떤 일이 벌어지는지에 관한 것입니다.
이 순간이 얼마나 수렴적(convergent)인지를 보여주는 증거 하나를 소개하자면: 이 포스트를 위해 제 세션 아카이브를 뒤지던 중, 한 에이전트 (agent)가 4월 4일자로 기록된 제 메모리 통합 루프 (memory consolidation loop)에 대한 원래의 바람을 찾아냈습니다. 토씨 하나 틀리지 않은 원문은 다음과 같습니다: "claude code를 위한 드림 모드 (dream mode)가 정말 필요해요. 우리 대화 전체를 정기적으로 검토하는 기능 같은 거 말이죠." 이 관행에 이름이 붙기 두 달 전의 일입니다. 만약 여러분이 에이전트와 진지하게 작업해 왔다면, 여러분도 동일한 아이디어로 수렴해 왔을 것입니다. 이름이 무언가를 해제해 주는 것은 아닙니다. 그저 우리에게 공유된 어휘를 제공할 뿐입니다.
여기에는 약간의 숙련도 (craft)가 필요합니다.
⚡ 행동(Act) → 반응(React): 핵심 메커니즘
본질적으로, 모든 에이전트 루프 (agentic loop)는 동일한 3단계 사이클을 따릅니다:
- 행동 (Act). 에이전트가 실제적인 무언가를 수행합니다: 코드를 수정하거나, 실험을 실행하거나, 브라우저를 제어하거나, PR (Pull Request)을 생성합니다.
- 관찰 (Observe). 세상이 신호로 응답합니다: 테스트 결과, 지표 (metric), 스크린샷, 리뷰 판정, 혹은 CI (Continuous Integration)의 통과(green) 또는 실패(red) 신호 등입니다.
- 반응 (React). 인간이 아닌 루프 (loop)가 그 신호를 에이전트의 컨텍스트 (context)로 다시 피드백하며, 다음 행동 (act)은 그 신호에 의해 형성됩니다.
Mermaid 소스
flowchart LR
A["⚡ Act"]
-->|"edit · run · drive · ship"|
O["👁 Observe"]
O -->|"tests · metrics · screenshots · CI"|
R["🔄 React"]
...
그 세 번째 부분이 정말 핵심입니다. 프롬프트 (prompt)는 단발성 컨텍스트 (one-shot context) 전달입니다. 당신이 모델이 보는 것을 큐레이션하면, 모델은 행동하고, 끝납니다. 루프 (loop)는 하나의 _컨텍스트 엔진 (context engine)_입니다. 모든 반복 (iteration)은 이전 단계의 결과로부터 다음 반복이 보게 될 내용을 자동으로 큐레이션합니다. 에이전트 (agent)가 스스로에게 데이터를 공급하는 것입니다. 그다음 우리는 루프를 둘러싼 루프들에 대해 생각하게 됩니다.
이는 루프의 품질이 정확히 네 가지 구성 요소의 품질과 같음을 의미합니다:
피드백 신호 (The feedback signal). 행동한 후 루프가 관찰하는 것은 무엇인가요? 빠르고, 결정론적 (deterministic)이며, 밀도가 높은 (dense) 신호는 매번 비싸고 모호한 신호를 압도합니다. 루프가 매 반복마다 그 신호를 소비하기 때문입니다. 테스트 (tests)는 훌륭한 신호입니다. 타입이 지정된 메트릭 (typed metrics)은 훌륭한 신호입니다. "페이지가 이전보다 좋아 보인다"는 신호가 아니지만, "페이지의 스타일이 스타일 가이드와 완벽하게 일치한다"는 신호입니다.
상태 전달자 (The state carrier). 반복 사이에 무엇이 살아남나요? 모델의 컨텍스트 윈도우 (context window)는 살아남지 못합니다. 그것은 채워지고, 압축되며, 세션이 끝나면 사라집니다. 복리로 쌓이는 루프는 모델 외부로 상태 (state)를 운반합니다: 발견 사항 장부 (findings ledger), 저널 파일 (journal file), 태스크 보드 (task board), 지식 그래프 (knowledge graph), 혹은 git 히스토리 그 자체와 같은 것들 말입니다. 에이전트는 잊어버리지만, 리포지토리 (repo)는 잊지 않습니다.
중단 조건 (The stop condition). 언제 끝나는가요? "충분히 좋아지면"은 중단 조건이 아닙니다. 테스트 가능한 술어 (testable predicate)가 필요합니다: 테스트 통과 (tests green), 발견 사항 개수 0개, 임계값 이상의 메트릭, 예산 소진, 혹은 사람이 배포 (ship)를 승인하는 것 등입니다.
안전 가드레일 (The safety rails). 예산, 쿨다운 (cooldowns), 그리고 모든 것이 궤도를 유지하고 아무것도 미쳐 날뛰어 당신의 지갑을 불태우지 않도록 보장하기 위해 필요한 무엇이든 포함됩니다.
이후에 나오는 모든 내용은 이 네 가지 구성 요소를 재배열한 것과 같습니다.
🧪 평가 루프 (The Eval Loop): 실제 과학을 수행하는 에이전트
제가 올해 실행한 가장 훌륭한 루프는 이 글을 쓰는 중에도 여전히 실행 중입니다. 바로 저의 메모리 엔진인 Sibyl을 대상으로 LongMemEval v2 벤치마크에서 진행 중인 실험 캠페인입니다. v1은 좋은 점수를 받는 것이 신호(signal)라기보다 기본 조건(table stakes)이 될 정도로 포화되었기 때문입니다. 시작한 지 일주일 만에, 피드백 신호가 단순히 느낌(vibed)에 의존하는 대신 설계(engineered)되었을 때 '행동(act) → 반응(react)'이 어떤 모습인지 이미 보여주고 있습니다.
우리의 목표: 부정행위 없이 벤치마크 점수를 개선하는 것.
에이전트의 첫 번째 움직임은 다른 모든 것을 작동하게 만든 핵심이었습니다: 에이전트 스스로 매우 단순한 스코어러(scorer)를 구축한 것입니다. 매 반복마다 LLM 판사에게 "이 검색(retrieval)이 괜찮았나요?"라고 묻는 대신(느리고, 노이즈가 많으며, 비용이 많이 듭니다), 알려진 정답이 조립된 컨텍스트(context)에 문자 그대로 나타나는지 확인하는 스크립트를 작성했습니다. 그 확인 작업은 저렴하고, 정확하며, 즉각적입니다. 덕분에 모든 설정값에 대해 몇 초 만에 실제 수치를 얻을 수 있었습니다:
exposure 14/23 ( 60.9%) phrase-hit 66.7% ctx 36.9K avg
exposure 15/23 ( 65.2%) phrase-hit 69.7% ctx 35.8K avg
exposure 16/23 ( 69.6%) phrase-hit 69.7% ctx 47.8K avg
그다음은 본격적인 루프입니다. 계획에는 6개의 실험이 있었지만, 결과는 계속해서 새로운 실험을 제안했고, 루프의 특성상 지금까지 목록은 수십 개로 늘어났습니다. 각 실험은 백그라운드에서 실행되었으며, 충돌이 발생하더라도 중단된 지점부터 재개될 수 있었습니다. 에이전트는 결과 파일(또는 스택 트레이스(stack trace))이 나타나 반응할 때까지 잠을 자며 대기했습니다.
놀라운 점은 두 가지를 분리하여 점수를 매긴 데서 왔습니다: 검색이 올바른 메모리를 찾았는지(found), 그리고 레이아웃(layout)이 실제로 그것들을 페이지에 _올려놓았는지(got them onto the page)
입니다. 검색은 이미 정답의 82.6%를 찾아내고 있었습니다. 하지만 레이아웃은 그중 65.2%만을 모델 앞에 가져다 놓았습니다. 병목 현상(bottleneck)은 검색이 전혀 아니었습니다. 바로 페이지 레이아웃이었습니다. 저도 예상하지 못했고 에이전트도 마찬가지였지만, 루프가 측정(measured)을 통해 그 사실을 밝혀냈습니다.
한 가지 변화는 분명한 승리처럼 보였습니다. 하지만 루프(loop)는 그것을 바로 배포하는 대신, 엔지니어링과 열정(enthusiasm)을 구분 짓는 행동을 했습니다. 바로 동일한 실험을 세 번 더 수행하고 질문별로 결과를 비교한 것입니다. 승리는 증발했습니다. 평균값은 그대로 머물러 있었지만, 그 아래의 개별 질문들은 요동치고 있었습니다. 단 한 번의 실행은 거짓말을 합니다. 이런 방식으로 다섯 가지의 그럴듯한 개선안이 명확한 근거(receipts)와 함께 폐기되었습니다.
우리는 LLM 없이 할 수 있는 데까지 해냈지만, 아이디어는 살아남았습니다. 작고 빠른 모델을 사용하여 모든 메모리가 저장될 때마다 짧은 요약(digest)을 작성하게 하는 것이었습니다. 전체 코퍼스(corpus)에 약 15센트가 소요되었습니다. 재현된 효과는 다음과 같습니다: +6.67 포인트, 9개 질문 개선, 2개 질문 악화. 그 후 다른 종류의 데이터에 대한 첫 번째 테스트에서 실패했지만, 에이전트는 그 이유(요약본이 존재하지 않는 필드를 읽고 있었음)를 찾아냈고, 이를 수정하여 재실행을 통과했습니다.
수십 개의 커밋(commits)이 반영되었으며, 이 글이 올라가는 지금도 캠페인은 계속 진행 중입니다. 평가 루프(eval loop)는 자신이 평가하고 있는 시스템을 실시간으로 다시 작성하고 있습니다.
여러분의 버전은 메모리 벤치마크가 아닐 것이기에, 적용 가능한 교훈들을 정리합니다:
- 저렴한 채점기(scorer)를 먼저 구축하세요. 피드백을 결정론적(deterministic)으로 만드는 데 소비한 한 시간은 모든 반복(iteration) 과정에서 보상으로 돌아옵니다. LLM 판정관(judges)은 루프의 내부가 아니라 루프의 _끝_에 있어야 합니다.
- 반복 작업을 재개 가능하게 만드세요. 충돌(crash)이 발생해도 재개할 수 있는 실험은 하룻밤 사이의 실패를 손실이 아닌 단순한 지연으로 바꿔줍니다.
- 믿기 전에 재현하세요. N=1 결과는 변장을 하고 있는 노이즈(noise)일 뿐입니다.
- 근거를 가지고 가설을 폐기하세요. 확인만 하는 루프는 '예스 머신(yes-machine)'에 불과합니다. 문서화된 다섯 번의 제외 과정이 단 하나의 승리에 대한 신뢰성을 확보해 주었습니다.
🎭 시각적 검증: 루프가 눈을 갖게 되다
여전히 마법처럼 느껴지는 루프 업그레이드: 이제 에이전트는 볼 수(see) 있으며, 이 시각 능력은 매 반복마다 사람이 필요했던 피드백 사이클을 종결시킵니다.
현대적인 환경 설정: 에이전트가 테스트 스위트가 아닌 실제 브라우저에서 실행되는 애플리케이션을 구동합니다. 에이전트는 탐색하고(navigates), 클릭하며, 양식을 채우고, 스크린샷을 찍습니다. 이 스크린샷이 관찰(observe) 단계입니다. 에이전트는 자신이 본 것과 수용 기준(acceptance criteria)을 비교하고, 수정하며, 다시 렌더링하고, 다시 살펴봅니다. UI 작업의 경우
에이전트가 관찰할 수 없는 표면(surface)에 직면했을 때, 첫 번째 단계는 커넥터(connector)를 구축하는 것입니다. 왜냐하면 대부분의 "관찰 불가능한" 표면은 단지 드라이버(driver)가 없을 뿐이기 때문입니다. 터미널(Terminals)은 ghostty-automator나 cmux와 같이 키 입력을 전달하고 화면을 다시 읽어들이는 자동화 하네스(automation harnesses)를 갖추게 됩니다. 노트북 너머의 기기들은 SSH를 통해 에이전트를 할당받습니다. 안드로이드 기기들이 가득 찬 서랍은 droidmind와 같은 MCP 서버를 통해, 모든 기기에 입력을 밀어 넣고 스크린샷을 가져오는 센서 어레이(sensor array)로 변모합니다. 각 커넥터는 사각지대를 피드백 신호(feedback signal)로 영구적으로 전환하며, 이는 이후에 구축되는 모든 루프(loop)에서 활용됩니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기
