
원문: https://www.anthropic.com/engineering/harness-design-long-running-apps
하네스 설계는 에이전틱 코딩의 최전선에서 성능을 끌어올리는 핵심 열쇠입니다. 프런트엔드 디자인과 장시간 자율 소프트웨어 엔지니어링 영역에서 Claude를 한 단계 더 발전시킨 방법을 소개합니다.
2026년 3월 24일 게재
Labs 팀 소속 Prithvi Rajasekaran 작성.
지난 몇 달 동안 저는 상호 연결된 두 가지 문제를 다루어 왔습니다. Claude가 고품질의 프런트엔드 디자인을 생성하게 만드는 것, 그리고 사람의 개입 없이 완전한 애플리케이션을 빌드하게 만드는 것입니다. 이 작업은 프런트엔드 디자인 스킬과 장시간 실행 코딩 에이전트 하네스에 관한 이전 작업에서 출발했습니다. 동료들과 저는 프롬프트 엔지니어링과 하네스 설계를 통해 Claude의 성능을 베이스라인 대비 크게 끌어올릴 수 있었지만, 결국 두 영역 모두 한계에 부딪혔습니다.
이를 돌파하기 위해, 저는 매우 다른 두 도메인(하나는 주관적인 취향, 다른 하나는 검증 가능한 정확성과 사용성으로 정의)에 걸쳐 통하는 새로운 AI 엔지니어링 접근법을 탐색했습니다. 생성적 적대 신경망(GANs)에서 영감을 받아, 생성기(generator) 와 평가기(evaluator) 에이전트로 구성된 멀티 에이전트 구조를 설계했습니다. 신뢰할 수 있는, 그리고 취향 있는 평가기를 만들기 위해서는 먼저 "이 디자인이 좋은가?"와 같은 주관적인 판단을 구체적이고 채점 가능한 기준으로 전환할 수 있는 평가 기준을 개발해야 했습니다.
이후 이 기법을 장시간 자율 코딩에 적용하면서, 이전 하네스 작업에서 얻은 두 가지 교훈을 그대로 가져왔습니다. 빌드를 다루기 쉬운 단위로 분해하는 것, 그리고 세션 간 컨텍스트를 전달하기 위해 구조화된 아티팩트를 활용하는 것입니다. 최종 결과물은 플래너(planner), 생성기, 평가기로 구성된 3-에이전트 아키텍처였으며, 수 시간에 걸친 자율 코딩 세션을 통해 풍부한 풀스택 애플리케이션을 만들어냈습니다.
하네스 설계가 장시간 실행 에이전틱 코딩의 효과성에 큰 영향을 미친다는 사실은 이전에도 보여드린 바 있습니다. 이전 실험에서 저희는 초기화 에이전트로 제품 스펙을 태스크 목록으로 분해하고, 코딩 에이전트가 한 번에 하나의 기능씩 구현한 후 세션 간 컨텍스트 전달을 위해 아티팩트를 넘겨주는 방식을 사용했습니다. 더 넓은 개발자 커뮤니티에서도 "Ralph Wiggum" 방식처럼 훅이나 스크립트로 에이전트를 지속적인 반복 사이클에 머물도록 하는 유사한 통찰에 도달했습니다.
그러나 일부 문제는 여전히 해결되지 않았습니다. 복잡한 태스크에서는 에이전트가 시간이 지남에 따라 여전히 목표에서 벗어나는 경향이 있었습니다. 이 문제를 분석하면서, 저희는 이런 유형의 태스크를 수행하는 에이전트에서 두 가지 공통적인 실패 패턴을 관찰했습니다.
첫째, 모델은 컨텍스트 윈도우가 가득 찰수록 긴 태스크에서 일관성을 잃는 경향이 있습니다(컨텍스트 엔지니어링에 관한 글을 참고하세요). 일부 모델은 "컨텍스트 불안(context anxiety)"이라고 부를 수 있는 현상도 보이는데, 자신이 인식하는 컨텍스트 한계에 가까워질수록 작업을 조기에 마무리하려 드는 것입니다. 컨텍스트 리셋(컨텍스트 윈도우를 완전히 초기화하고 새 에이전트를 시작하되, 이전 에이전트의 상태와 다음 단계를 담은 구조화된 핸드오프와 결합)은 두 가지 문제를 모두 해결합니다.
이는 컨텍스트 압축과 다릅니다. 컨텍스트 압축은 대화의 이전 부분을 그 자리에서 요약하여 동일한 에이전트가 단축된 히스토리로 계속 진행할 수 있게 합니다. 압축이 연속성을 유지하기는 하지만, 에이전트에게 새 출발점을 제공하지는 않아 컨텍스트 불안이 여전히 지속될 수 있습니다. 리셋은 새 출발점을 제공하지만, 핸드오프 아티팩트가 다음 에이전트가 작업을 깔끔하게 이어받을 수 있을 만큼 충분한 상태 정보를 담아야 한다는 비용이 따릅니다. 이전 테스트에서, Claude Sonnet 4.5는 컨텍스트 불안을 충분히 심하게 보여 압축만으로는 장시간 태스크에서 강한 성능을 내기에 부족했고, 결국 컨텍스트 리셋이 하네스 설계의 필수 요소가 되었습니다. 이를 통해 핵심 문제가 해결되지만, 하네스 실행마다 오케스트레이션 복잡도, 토큰 오버헤드, 지연 시간이 추가됩니다.
두 번째 문제는 이전에 다루지 않았던 자기 평가(self-evaluation)입니다. 에이전트에게 자신이 작성한 결과물을 평가해 달라고 하면, 인간 관찰자가 보기에 품질이 명백히 평범하더라도 자신감 있게 칭찬하는 경향이 있습니다. 이 문제는 디자인처럼 주관적인 태스크에서 특히 두드러집니다. 검증 가능한 소프트웨어 테스트에 상응하는 이진 검사가 없기 때문입니다. 레이아웃이 세련된지 아니면 평범한지는 주관적인 영역이고, 에이전트는 자신의 작업을 평가할 때 어김없이 긍정적인 쪽으로 치우치는 경향이 있습니다.
그러나 검증 가능한 결과를 가진 태스크에서도, 에이전트는 태스크를 완수하는 중에 성능을 저해하는 잘못된 판단을 내리기도 합니다. 작업을 수행하는 에이전트와 판단을 내리는 에이전트를 분리하는 것이 이 문제를 해결하는 데 효과적입니다. 분리 자체만으로 이러한 관대함이 즉시 없어지지는 않습니다. 평가기도 LLM이 생성한 결과물에 관대한 경향이 있는 LLM이기 때문입니다. 하지만 독립적인 평가기를 회의적으로 동작하도록 튜닝하는 것이, 생성기가 자신의 작업에 비판적이 되도록 만드는 것보다 훨씬 다루기 쉽습니다. 그리고 외부 피드백이 마련되면, 생성기는 이를 바탕으로 구체적인 개선 작업을 진행할 수 있게 됩니다.
저는 자기 평가 문제가 가장 두드러지게 드러나는 프런트엔드 디자인에서 실험을 시작했습니다. 별도의 개입이 없으면 Claude는 대게 기술적으로 기능적이지만 시각적으로 별다른 특징이 없는, 안전하고 예측 가능한 레이아웃을 선호하는 경향이 있습니다.
프런트엔드 디자인을 위해 구축한 하네스를 만든 두 가지 통찰이 있었습니다. 첫째, 미학은 점수로 완전히 환원될 수 없고 개인 취향은 언제나 다양하지만 디자인 원칙과 선호도를 담은 채점 기준으로 개선할 수 있습니다. "이 디자인이 아름다운가?"는 일관되게 답하기 어렵지만, "좋은 디자인을 위한 우리의 원칙을 따르고 있는가?"는 Claude에게 채점의 구체적인 기준을 줍니다. 둘째, 프런트엔드 생성과 프런트엔드 채점을 분리하면 생성기를 더 강한 결과물로 유도하는 피드백 루프를 만들 수 있습니다.
이를 염두에 두고, 저는 생성기와 평가기 에이전트 모두의 프롬프트에 제공할 네 가지 채점 기준을 작성했습니다.
저는 완성도와 기능성보다 디자인 품질과 독창성을 더 강조했습니다. Claude는 필요한 기술적 역량이 모델의 특성에 자연스럽게 녹아들어 있었기 때문에, 제작 기술과 기능성 면에서는 이미 높은 점수를 받고 있었기 때문입니다. 하지만 디자인과 독창성에서 Claude는 기껏해야 평범한 수준에 그치는 경우가 많았습니다. 평가 기준은 지나치게 평범한 "AI 쓰레기(AI slop)" 패턴을 명시적인 감점 대상으로 삼았으며, 디자인과 독창성에 더 높은 가중치를 부여함으로써 모델이 미학적으로 더 과감한 시도를 하도록 유도했습니다.
저는 상세한 점수 분석이 담긴 퓨샷(few-shot) 예시를 사용하여 평가기를 교정했습니다. 이를 통해 평가기의 판단이 제 선호도와 일치하도록 맞추고, 반복 실행 간 점수 편차를 줄였습니다.
루프는 Claude Agent SDK 위에 구축했으며, 덕분에 오케스트레이션을 단순하게 유지할 수 있었습니다. 생성기 에이전트가 먼저 사용자 프롬프트를 기반으로 HTML/CSS/JS 프런트엔드를 생성합니다. 평가기는 Playwright MCP를 사용하여 각 기준을 채점하고 상세한 비평을 작성하기 전에 라이브 페이지와 직접 상호작용할 수 있게 했습니다. 실제로 평가기는 페이지를 스스로 탐색하며 스크린샷을 찍고 구현을 꼼꼼히 살펴본 후 평가를 내렸습니다. 이러한 피드백은 다음 반복을 위한 입력으로 생성기에게 다시 전달되었습니다. 생성물 하나당 5~15회 반복을 수행했으며, 각 반복마다 생성기는 평가기의 비평에 반응하여 더 뚜렷한 방향으로 나아갔습니다. 평가기가 정적 스크린샷이 아니라 실제로 페이지를 탐색했기 때문에, 각 사이클에는 실제 소요 시간이 걸렸습니다. 전체 실행은 최대 4시간까지 소요되었습니다. 또한 생성기에게 각 평가 후 전략적 결정을 내리도록 지시했습니다. 점수 추세가 양호하면 현재 방향을 다듬고, 접근 방식이 효과가 없으면 완전히 다른 미학으로 전환하도록 하였습니다.
여러 실행에 걸쳐, 평가기의 평가는 반복마다 개선되다 정체기에 접어들었으며, 여전히 개선 여지는 남아 있었습니다. 일부 생성은 점진적으로 다듬어졌고, 다른 것들은 반복 사이에 날카로운 미학적 전환을 보였습니다.
기준의 표현 방식이 예상치 못한 방식으로 생성기를 이끌었습니다. "최고의 디자인은 박물관 수준의 품질을 가져야 한다"와 같은 문구를 포함시키자 디자인들이 특정한 시각적 방향으로 수렴했고, 이는 기준에 연결된 프롬프팅 자체가 결과물의 성격을 직접적으로 형성함을 시사했습니다.
반복 과정을 거치며 점수는 전반적으로 향상되었지만, 그 추세가 항상 선형적인 것은 아니었습니다. 후반부의 구현 결과들이 전반적으로 더 나은 경향이 있었지만, 마지막 결과물보다 중간 단계의 결과를 선호하는 경우도 종종 있었습니다. 구현 복잡도도 라운드를 거칠수록 증가하는 경향이 있었는데, 평가기의 피드백에 반응하여 생성기가 더 야심찬 솔루션을 시도했기 때문입니다. 첫 번째 반복에서도 프롬프팅이 전혀 없는 베이스라인보다 결과물이 눈에 띄게 나았는데, 이는 기준과 그에 수반된 표현 자체가 평가기 피드백이 추가적인 개선으로 이어지기 전에 이미 모델을 평범한 기본값에서 벗어나도록 유도했음을 시사합니다.
주목할 만한 사례 중 하나로, 저는 모델에게 네덜란드 미술관 웹사이트를 만들어 달라고 요청했습니다. 아홉 번째 반복에서는 가상의 미술관을 위한 깔끔하고 어두운 테마의 랜딩 페이지가 만들어졌습니다. 페이지는 시각적으로 세련되었지만 대체로 제 예상 범위 안에 있었습니다. 그런데 열 번째 사이클에서, 모델은 접근 방식을 완전히 폐기하고 사이트를 공간적 경험으로 재구성했습니다. CSS perspective로 렌더링된 체크무늬 바닥이 있는 3D 방, 벽에 자유롭게 배치된 예술 작품들, 스크롤이나 클릭이 아닌 출입구 기반 갤러리 공간 탐색 방식이 적용된 것이었습니다. 이는 단 한 번의 생성 과정에서는 본 적 없는 창의적인 도약이었습니다.
이러한 발견을 바탕으로, 저는 이 GAN에서 영감받은 패턴을 풀스택 개발에 적용했습니다. 생성기-평가기 루프는 소프트웨어 개발 생명 주기에 자연스럽게 매핑됩니다. 코드 리뷰와 QA가 설계 평가기와 동일한 구조적 역할을 담당합니다.
이전 장시간 실행 하네스에서는 초기화 에이전트, 한 번에 하나의 기능씩 작업하는 코딩 에이전트, 세션 간 컨텍스트 리셋을 통해 일관성 있는 다중 세션 코딩 문제를 해결했었습니다. 컨텍스트 리셋은 핵심적인 해결책이었습니다. 해당 하네스는 앞서 언급한 "컨텍스트 불안" 경향을 보인 Sonnet 4.5를 사용했기 때문입니다. 컨텍스트 리셋 전반에 걸쳐 잘 작동하는 하네스를 만드는 것이 모델이 태스크에 집중하도록 유지하는 핵심이었습니다. Opus 4.5는 이러한 행동 양상을 자체적으로 크게 제거했기 때문에, 이 하네스에서는 컨텍스트 리셋을 완전히 제거할 수 있었습니다. 에이전트들은 전체 빌드에 걸쳐 하나의 연속 세션으로 실행되었으며, Claude Agent SDK의 자동 컨텍스트 압축 기능이 그 과정에서 발생하는 컨텍스트 증가를 처리했습니다.
이번 작업에서는 기존 하네스를 기반으로 3-에이전트 시스템을 구축했으며, 각 에이전트는 이전 실행에서 발견된 특정 문제점을 해결하도록 설계되었습니다. 시스템은 다음과 같은 에이전트 페르소나로 구성됩니다.
플래너(Planner): 이전 장시간 실행 하네스는 사용자가 상세한 스펙을 사전에 제공해야 했습니다. 저는 이 단계를 자동화하고 싶었기 때문에, 1-4문장짜리 간단한 프롬프트를 받아 완전한 제품 스펙으로 확장하는 플래너 에이전트를 만들었습니다. 범위에 대해 야심차게 생각하고, 세부 기술 구현보다는 제품 맥락과 상위 수준의 기술 설계에 집중하도록 프롬프팅했습니다. 이 강조점은 플래너가 사전에 세세한 기술적 세부 사항을 명세하려다 무언가를 잘못 지정하면, 스펙의 오류가 다운스트림 구현까지 연쇄적으로 영향을 미칠 것이라는 우려 때문이었습니다. 에이전트가 만들어야 할 결과물을 제약하고, 작업하면서 경로는 스스로 찾게 두는 것이 더 현명해 보였습니다. 또한 플래너에게 제품 스펙에 AI 기능을 엮어 넣을 기회를 찾도록 요청했습니다.
생성기(Generator): 이전 하네스에서 한 번에 하나의 기능씩 접근하는 방식은 스코프 관리에 효과적이었습니다. 여기서도 유사한 모델을 적용하여, 생성기가 스프린트 단위로 작업하며 스펙에서 한 번에 하나의 기능을 가져오도록 지시했습니다. 각 스프린트는 React, Vite, FastAPI, SQLite(이후 PostgreSQL) 스택으로 앱을 구현했으며, 생성기는 각 스프린트 마지막에 자체 평가를 수행한 후 QA에 넘기도록 지시받았습니다. 버전 관리를 위한 git도 갖추고 있었습니다.
평가기(Evaluator): 이전 하네스의 애플리케이션들은 겉으로는 인상적으로 보였지만 실제로 사용해 보면 진짜 버그가 있는 경우가 많았습니다. 이를 잡아내기 위해, 평가기는 Playwright MCP를 사용하여 사용자처럼 실행 중인 애플리케이션을 클릭하며 UI 기능, API 엔드포인트, 데이터베이스 상태를 테스트했습니다. 이후 발견한 버그와 프런트엔드 실험에서 도출된 기준(제품 완성도, 기능성, 시각 디자인, 코드 품질)을 기반으로 각 스프린트를 채점했습니다. 각 평가 기준에는 명확한 기준치가 설정되어 있었으며, 그중 하나라도 미달하면 스프린트가 실패로 처리되고 생성기는 무엇이 잘못되었는지에 대한 상세한 피드백을 받았습니다.
각 스프린트 전에, 생성기와 평가기는 스프린트 계약을 협의했습니다. 코드를 작성하기 전에 해당 작업 단위의 "완료"가 무엇을 의미하는지 합의하는 것입니다. 이는 제품 스펙이 의도적으로 추상적인 수준에 머물러 있었기 때문이며, 사용자 스토리와 테스트 가능한 구현 사이의 간극을 메울 단계가 필요했기 때문입니다. 생성기가 무엇을 만들고 성공이 어떻게 검증될지를 제안하면, 평가기가 그 제안을 검토하여 생성기가 올바른 것을 만들고 있는지 확인했습니다. 두 에이전트는 합의에 도달할 때까지 이 과정을 반복했습니다.
커뮤니케이션은 파일을 통해 이루어졌습니다. 한 에이전트가 파일을 작성하면, 다른 에이전트가 그 파일을 읽고 같은 파일 내에서 응답하거나, 이전 에이전트가 다시 읽을 새 파일을 작성하는 방식이었습니다. 생성기는 합의된 계약에 따라 빌드를 진행한 후 작업을 QA에 넘겼습니다. 이를 통해 구현 사항을 너무 이른 시점에 과도하게 구체화하지 않으면서도 스펙에 충실하게 작업을 할 수 있었습니다.
첫 번째 버전의 하네스에서는 Claude Opus 4.5를 사용했고, 비교를 위해 전체 하네스와 단일 에이전트 시스템 모두에 사용자 프롬프트를 실행했습니다. 이 실험을 시작할 당시 Opus 4.5가 우리가 보유한 최고의 코딩 모델이었기 때문에 선택했습니다.
저는 레트로 비디오 게임 제작 도구를 생성하기 위해 다음 프롬프트를 작성했습니다.
레벨 에디터, 스프라이트 에디터, 엔티티 동작, 플레이 가능한 테스트 모드를 포함한 기능을 갖춘 2D 레트로 게임 제작 도구를 만들어 주세요.
아래 표는 하네스 유형, 실행 시간, 총 비용을 보여줍니다.
| 하네스 | 소요 시간 | 비용 |
|---|---|---|
| 단독 | 20분 | $9 |
| 전체 하네스 | 6시간 | $200 |
하네스는 20배 이상 비쌌지만, 결과물 품질의 차이는 명백했습니다.
저는 레벨과 그 구성 요소(스프라이트, 엔티티, 타일 레이아웃)를 구성한 다음 플레이 버튼을 눌러 실제로 게임을 플레이할 수 있는 인터페이스를 기대했습니다. 단독 실행 결과물을 열었을 때, 초기 애플리케이션은 그 기대에 부합하는 것처럼 보였습니다.
그러나 클릭하면서 문제들이 드러나기 시작했습니다. 레이아웃이 공간을 낭비하고 있었는데, 높이가 고정된 패널들 때문에 뷰포트의 대부분이 비어 있었습니다. 워크플로우도 경직되어 있었습니다. 레벨을 채우려 하면 먼저 스프라이트와 엔티티를 만들어야 한다고 했지만, UI 어디에도 그 순서로 안내하는 것이 없었습니다. 더 중요한 것은, 실제 게임이 제대로 작동하지 않았습니다. 엔티티가 화면에 나타났지만 입력에 반응하는 것이 아무것도 없었습니다. 코드를 자세히 살펴보니 엔티티 정의와 게임 런타임 사이의 연결이 끊어져 있었고, 겉으론 어디가 문제인지 전혀 알 수 없었습니다.

단독 하네스로 만든 앱의 초기 화면

단독 하네스로 만든 스프라이트 에디터에서 스프라이트 생성하기

내가 만든 레벨을 플레이하려다 실패한 모습
단독 실행을 평가한 후, 하네스 실행으로 시선을 돌렸습니다. 이 실행은 동일한 한 문장 프롬프트에서 시작했지만, 플래너 단계에서 해당 프롬프트를 10개의 스프린트에 걸쳐 16개 기능으로 구성된 스펙으로 확장했습니다. 단독 실행이 시도한 것을 훨씬 뛰어넘었습니다. 핵심 에디터와 플레이 모드 외에, 스펙에는 스프라이트 애니메이션 시스템, 동작 템플릿, 효과음과 음악, AI 보조 스프라이트 생성기와 레벨 디자이너, 공유 링크를 통한 게임 내보내기 기능이 포함되었습니다. 플래너에게 프런트엔드 디자인 스킬에 대한 접근 권한을 주었고, 플래너는 이를 읽어 스펙의 일부로 앱의 시각 디자인 언어를 구축했습니다. 각 스프린트마다 생성기와 평가기는 스프린트의 구체적인 구현 세부 사항과 완료 검증에 사용할 테스트 가능한 동작을 정의하는 계약을 협의했습니다.
단독 실행에서 만든 앱 보다 훨씬 세련되고 매끄러워졌습니다. 캔버스는 전체 뷰포트를 활용했고, 패널의 크기도 적절했으며, 인터페이스는 스펙의 디자인 방향을 반영하는 일관된 시각적 정체성을 갖추고 있었습니다. 다만, 단독 실행에서 보였던 일부 불편함은 남아 있었습니다. 레벨을 채우기 전에 스프라이트와 엔티티를 먼저 만들어야 한다는 것을 여전히 탐색하면서 스스로 파악해야 했습니다. 이는 하네스가 해결하도록 설계된 것이 아니라 제품에 대한 베이스 모델의 직관 부족으로 발생한 것으로 보였지만, 하네스 내부에서 집중적인 반복 작업을 통해 결과물 품질을 더욱 향상시킬 수 있는 지점을 시사하기도 했습니다.
에디터를 직접 사용해 보면서, 새로 만든 버전이 단독 실행에서 만든 버전보다 갖는 장점이 더욱 명확해졌습니다. 스프라이트 에디터는 더 풍부하고 완성도 높았으며, 더 깔끔한 도구 팔레트, 더 나은 색상 선택기, 더 사용하기 편한 줌 컨트롤을 제공했습니다.
플래너에게 스펙에 AI 기능을 엮어 넣도록 요청했기 때문에, 앱에는 프롬프팅으로 게임의 다양한 부분을 생성할 수 있는 내장 Claude 통합도 포함되었습니다. 덕분에 작업 흐름이 상당히 빨라졌습니다.

전체 하네스로 만든 앱의 초기 화면: 새 게임 만들기

더 깔끔하고 사용하기 편한 스프라이트 에디터

내장 AI 기능으로 레벨 생성하기

내장 AI 기능으로 레벨 생성하기

내가 생성한 게임 플레이하기
가장 큰 차이는 플레이 모드에서 나타났습니다. 실제로 엔티티를 움직여 게임을 플레이할 수 있었습니다. 물리 엔진에는 다소 미흡한 점이 있었습니다. 캐릭터가 플랫폼 위로 점프했을 때 플랫폼과 겹쳐 보여 직관적으로 어색함이 느껴졌습니다. 하지만 단독 실행에서는 달성하지 못했던 핵심 기능은 제대로 작동했습니다. 조금 더 살펴보다 보니 AI의 게임 레벨 구성에 몇 가지 한계가 있었습니다. 점프로 넘을 수 없는 커다란 벽이 있어 갇히고 말았습니다. 이는 하네스가 앱을 더 정교하게 다듬기 위해 처리할 수 있는 상식적인 개선 사항과 엣지 케이스가 남아있음을 시사했습니다.
로그를 살펴보면서, 평가기가 구현을 스펙에 맞게 유지했다는 것이 분명했습니다. 각 스프린트마다 스프린트 계약의 테스트 기준을 검토하고 Playwright로 실행 중인 애플리케이션을 테스트하여 예상 동작에서 벗어난 사항에 대해 버그를 등록했습니다. 계약은 세분화되어 있었습니다. 스프린트 3만 해도 레벨 에디터에 관한 27개의 기준이 있었고, 평가기의 발견 사항은 추가 조사 없이 바로 조치를 취할 수 있을 만큼 구체적이었습니다. 아래 표는 평가기가 식별한 문제들의 몇 가지 예시입니다.
| 계약 기준 | 평가기 발견 사항 |
|---|---|
| 직사각형 채우기 도구가 클릭-드래그로 선택한 타일로 직사각형 영역을 채울 수 있어야 함 | FAIL — 도구가 드래그 시작/끝 지점에만 타일을 배치하고 영역을 채우지 못함. fillRectangle 함수는 존재하지만 mouseUp 이벤트에서 제대로 트리거되지 않음. |
| 배치된 엔티티 스폰 포인트를 선택하고 삭제할 수 있어야 함 | FAIL — LevelEditor.tsx:892의 Delete 키 핸들러가 selection과 selectedEntityId 모두 설정되어야 작동하지만, 엔티티 클릭 시 selectedEntityId만 설정됨. 조건이 selection \|\| (selectedEntityId && activeLayer === 'entity')여야 함. |
| API를 통해 애니메이션 프레임을 재정렬할 수 있어야 함 | FAIL — PUT /frames/reorder 라우트가 /{frame_id} 라우트 이후에 정의되어 있음. FastAPI가 'reorder'를 frame_id 정수로 매칭하여 422 오류("unable to parse string as an integer") 반환. |
평가기가 이 수준으로 성능을 발휘하도록 만드는 데는 상당한 노력이 필요했습니다. 기본 상태에서 Claude는 형편없는 QA 에이전트였습니다. 초기 테스트에서 Claude가 정당한 문제를 식별했다가, 스스로 설득해 '별일 아니다'라고 판단하고 어쨌든 작업을 승인하는 모습을 지켜보았습니다. 또한 엣지 케이스를 파고들기보다 피상적으로 테스트하는 경향이 있어, 더 미묘한 버그들을 놓치곤 했습니다. 튜닝 루프는 평가기의 로그를 읽고, 판단이 제 기준과 달랐던 예시를 찾아 QA 프롬프트를 업데이트하는 방식이었습니다. 평가기가 합리적으로 채점하는 방식이 되기까지 이 개발 과정을 여러 차례 반복해야 했습니다. 그럼에도 불구하고 하네스 결과물은 모델의 QA 능력의 한계를 보여주었습니다. 사소한 레이아웃 문제, 일부 비직관적인 인터랙션, 평가기가 충분히 테스트하지 못한 더 깊이 중첩된 기능의 미발견 버그들이 있었습니다. 추가적인 튜닝으로 검증 범위를 더 넓힐 여지가 분명히 있었습니다. 하지만 애플리케이션의 핵심 기능이 아예 작동하지 않았던 단독 실행과 비교하면, 성능 향상은 명백했습니다.
첫 번째 하네스 결과는 고무적이었지만, 부피가 크고 느리고 비쌌습니다. 따라서 성능을 저하시키지 않으면서 하네스를 단순화할 방법을 찾아야 했습니다. 이는 부분적으로 상식적인 접근이었고, 부분적으로는 더 일반적인 원칙을 따른 것이었습니다. 하네스의 모든 컴포넌트는 모델이 혼자서는 할 수 없는 것에 대한 가정을 담고 있으며, 이러한 가정은 잘못되었을 수도 있고 모델이 개선됨에 따라 금세 구식이 될 수 있기 때문에 스트레스 테스트를 통해 검증할 가치가 있습니다. 우리의 블로그 게시물 '효과적인 에이전트 구축'은 이 근본적인 아이디어를 "가능한 가장 단순한 해결책을 찾고, 필요할 때만 복잡도를 높여라"로 표현하며, 이는 에이전트 하네스를 유지 관리하는 누구에게나 일관되게 나타나는 패턴입니다.
처음 단순화를 시도할 때 하네스를 과감하게 축소하고 몇 가지 창의적인 아이디어를 시도했지만, 원래 성능을 재현할 수 없었습니다. 또한 하네스 설계의 어떤 부분이 실제로 필수적인지, 어떤 방식으로 그런지 파악하기가 어려워졌습니다. 그 경험을 바탕으로, 한 번에 하나의 컴포넌트를 제거하고 최종 결과에 어떤 영향을 미치는지 검토하는 더 체계적인 접근 방식으로 전환했습니다.
이 반복 사이클을 진행하면서, Opus 4.6도 출시되었는데 이는 하네스 복잡도를 줄여야 할 동기를 더욱 강화해 주었습니다. 4.6이 4.5보다 더 적은 스캐폴딩을 필요로 할 것이라고 기대할 타당한 이유가 있었습니다. 출시 블로그에서 "[Opus 4.6은] 더 신중하게 계획하고, 에이전틱 태스크를 더 오래 지속하며, 더 큰 코드베이스에서 더 안정적으로 동작하고, 자신의 실수를 잡아내는 코드 리뷰 및 디버깅 능력이 향상되었습니다." 또한 긴 컨텍스트 검색 기능도 상당히 개선되었습니다. 이 모든 기능은 하네스가 보완하기 위해 구축된 것이었습니다.
먼저 스프린트 구조를 완전히 제거하는 것부터 시작했습니다. 스프린트 구조는 모델이 일관성 있게 작업할 수 있도록 작업을 작은 단위로 분할하는 데 도움이 되었습니다. Opus 4.6의 개선 사항을 감안할 때, 모델이 이러한 분할 없이도 작업을 기본적으로 처리할 수 있을 것이라는 확신이 들었습니다.
플래너와 평가기는 각각 뚜렷한 가치를 계속 제공했기 때문에 둘 다 유지했습니다. 플래너가 없으면 생성기가 범위를 제대로 잡지 못했습니다. 즉, 원시 프롬프트만 주어지면 작업 스펙을 작성하지 않고 빌드를 시작하여, 결국 플래너가 만든 것보다 기능이 적은 애플리케이션을 만들게 되었습니다.
스프린트 구조를 제거하면서, 스프린트별로 점수를 매기는 방식 대신 평가기를 실행 마지막에 단일 패스로 이동시켰습니다. 모델의 역량이 훨씬 높아졌기 때문에, 일부 실행에서 평가기의 필요성이 달라졌고, 그 유용성은 모델이 자체적으로 안정적으로 수행할 수 있는 범위에 비해, 해당 작업이 어디에 위치하는지에 따라 달라지게 되었습니다. 4.5에서는 그 경계가 매우 가까웠습니다. 빌드가 생성기가 단독으로 잘 처리할 수 있는 범위의 한계에 가까웠고, 평가기는 빌드 전반에 걸쳐 의미 있는 문제를 잡아냈습니다. 4.6에서는 모델의 순수 성능이 향상되어 경계가 바깥으로 이동했습니다. 예전에는 평가기의 검토가 필요했던 태스크들이 이제 생성기가 단독으로 잘 처리하는 범위 안에 들어오는 경우가 많았고, 그 경계 안에 있는 태스크들에서 평가기는 불필요한 오버헤드가 되었습니다. 하지만 생성기의 역량 경계에 여전히 걸쳐 있는 빌드 부분에서는 평가기가 계속해서 실질적인 도움을 주었습니다.
실질적인 시사점은 평가기가 단순히 '예' 또는 '아니오'로 결정되는 고정된 개념이 아니라는 것입니다. 태스크가 현재 모델이 단독으로 안정적으로 처리하는 것을 넘어설 때 비용을 들일 가치가 있습니다.
구조적 단순화와 함께, 하네스가 각 앱에 AI 기능을 구축하는 방식을 개선하는 프롬프팅도 추가했습니다. 구체적으로는 생성기가 앱 자체의 기능을 도구를 통해 구동할 수 있는 제대로 된 에이전트를 구축하도록 하는 데 중점을 두었습니다. 관련 지식이 최근의 것이라 Claude의 학습 데이터에 충분히 반영되지 않았기 때문에, 이 작업에는 상당한 반복이 필요했습니다. 하지만 충분한 튜닝을 거친 후, 생성기는 에이전트를 올바르게 구축하였습니다.
업데이트된 하네스를 검증하기 위해, 곡을 작성, 녹음, 믹싱하는 음악 제작 프로그램인 디지털 오디오 워크스테이션(DAW)을 생성하도록 다음의 프롬프트를 사용했습니다.
Web Audio API를 사용하여 브라우저에서 완전한 기능을 갖춘 DAW를 만들어 주세요.
실행은 여전히 길고 비쌌습니다. 약 4시간, 토큰 비용 $124이었습니다.
대부분의 시간은 빌더에서 소요되었으며, Opus 4.5가 필요로 했던 스프린트 분해 없이도 2시간 이상 일관성 있게 실행되었습니다.
| 에이전트 & 단계 | 소요 시간 | 비용 |
|---|---|---|
| 플래너 | 4.7분 | $0.46 |
| 빌드 (라운드 1) | 2시간 7분 | $71.08 |
| QA (라운드 1) | 8.8분 | $3.24 |
| 빌드 (라운드 2) | 1시간 2분 | $36.89 |
| QA (라운드 2) | 6.8분 | $3.09 |
| 빌드 (라운드 3) | 10.9분 | $5.88 |
| QA (라운드 3) | 9.6분 | $4.06 |
| V2 하네스 합계 | 3시간 50분 | $124.70 |
이전 하네스와 마찬가지로, 플래너가 한 줄 프롬프트를 완전한 스펙으로 확장했습니다. 로그를 살펴보니, 생성기 모델이 앱과 에이전트 설계를 잘 계획하고, 에이전트를 연결하며, QA에 넘기기 전에 테스트까지 잘 수행했음을 확인할 수 있었습니다.
그럼에도 불구하고 QA 에이전트는 여전히 실질적인 누락을 잡아냈습니다. 첫 번째 라운드 피드백에서 다음과 같이 지적했습니다.
이 앱은 뛰어난 디자인 완성도, 탄탄한 AI 에이전트, 좋은 백엔드를 갖춘 강력한 앱입니다. 하지만, 가장 큰 문제점은 기능의 완성도입니다. 앱의 외관이 인상적이고 AI 통합도 잘 작동하지만, 여러 핵심 DAW 기능들이 상호작용이 불가능한 '표시 전용'으로만 제공됩니다. 타임라인에서 클립을 드래그하거나 이동할 수 없고, 악기 UI 패널(신스 노브, 드럼 패드)이 없으며, 시각적 이펙트 에디터(EQ 커브, 컴프레서 미터)가 없습니다. 이것들은 엣지 케이스가 아니라 DAW를 사용 가능하게 만드는 핵심 상호작용이며, 스펙에서도 명시적으로 요구하고 있습니다.
두 번째 라운드 피드백에서도 여러 기능 누락을 다시 잡아냈습니다.
남은 누락 사항
- 오디오 녹음이 여전히 스텁(stub)만 구현됨 (버튼 토글은 되지만 마이크 캡처 없음)
- 가장자리 드래그를 통한 클립 리사이즈 및 클립 분할 미구현
- 이펙트 시각화가 그래픽이 아닌 숫자 슬라이더 형태임 (EQ 커브 없음)
생성기는 혼자서 작업할 때 여전히 세부 사항을 놓치거나 기능을 스텁으로 처리하는 경향이 있었고, QA는 생성기가 수정해야 할 이런 마지막 구간의 문제들을 잡아내는 데 여전히 중요한 역할을 했습니다.
프롬프트에 기반하여 저는 멜로디, 하모니, 드럼 패턴을 만들어 곡으로 편곡하고, 도중에 통합 에이전트의 도움을 받을 수 있는 프로그램을 기대했습니다. 아래 영상은 그 결과물을 보여줍니다.
앱은 전문 음악 제작 프로그램과는 거리가 멀었고, 에이전트의 작곡 능력은 개선할 여지가 명백히 많았습니다. 또한 Claude가 실제로 들을 수 없어서, 음악 취향과 관련하여 QA 피드백 루프의 효과가 제한적이었습니다.
하지만 최종 앱은 기능적인 음악 제작 프로그램의 모든 핵심 요소를 갖추고 있었습니다. 브라우저에서 작동하는 어레인지먼트 뷰, 믹서, 트랜스포트가 있었습니다. 뿐만 아니라, 저는 프롬프트만으로 짧은 곡 스니펫을 만들 수 있었습니다. 에이전트가 템포와 조성을 설정하고, 멜로디를 깔고, 드럼 트랙을 구성하고, 믹서 레벨을 조정하고, 리버브를 추가했습니다. 작곡을 위한 핵심 기본 요소들이 존재했고, 에이전트는 도구를 사용하여 처음부터 끝까지 간단한 프로덕션을 자율적으로 구동할 수 있었습니다. 아직 완벽하다고 할 순 없겠지만, 분명히 발전하고 있습니다.
모델이 지속적으로 개선됨에 따라, 대략적으로 더 오랜 시간 동안 더 복잡한 태스크를 수행할 수 있게 될 것이라 예상할 수 있습니다. 어떤 경우에는 모델을 둘러싼 스캐폴드의 중요성이 시간이 지남에 따라 줄어들 것이며, 개발자들은 다음 모델을 기다리면서 특정 문제들이 자연스럽게 해결되는 것을 볼 수 있을 것입니다. 반면에, 모델이 좋아질수록 베이스라인에서 모델이 할 수 있는 것을 넘어서는 복잡한 태스크를 달성할 수 있는 하네스를 개발할 공간도 더 넓어집니다.
이를 염두에 두고, 이번 연구에서는 얻을 수 있는 몇 가지 교훈이 있습니다. 빌드하는 모델을 대상으로 실험하고, 실제 문제에 대한 모델의 실행 추적을 분석하며, 원하는 결과를 달성하기 위해 성능을 튜닝하는 것은 언제나 좋은 실천입니다. 더 복잡한 태스크를 다룰 때는 태스크를 분해하고 문제의 각 측면에 특화된 에이전트를 적용하는 것에서 얻을 수 있는 여지가 있습니다. 그리고 새 모델이 출시될 때마다, 성능에 더 이상 필수적이지 않은 부분을 제거하고 이전에는 불가능했을 수 있는 더 큰 역량을 달성하기 위한 새로운 부분을 추가하면서 하네스를 재검토하는 것이 일반적으로 좋은 실천입니다.
이번 연구를 통해 제가 확신하는 바는, 모델이 발전한다고 해서 흥미로운 하네스 조합의 범위가 줄어들지 않는다는 것입니다. 오히려 그 범위는 변화하며, AI 엔지니어들에게 주어진 흥미로운 과제는 계속해서 새로운 조합을 찾아내는 것입니다.
이 작업에 기여해 주신 Mike Krieger, Michael Agaby, Justin Young, Jeremy Hadfield, David Hershey, Julius Tarng, Xiaoyi Zhang, Barry Zhang, Orowa Sidker, Michael Tingley, Ibrahim Madha, Martina Long, Canyon Robbins에게 특별히 감사드립니다.
포스트를 다듬는 데 도움을 주신 Jake Eaton, Alyssa Leonard, Stef Sequeira에게도 감사드립니다.