하네스 엔지니어링의 핵심: 에이전트 오케스트레이션과 TDD
지난 글에서 하네스 엔지니어링의 개념을 정리했다. 프롬프트에서 컨텍스트로, 컨텍스트에서 하네스로 이어지는 포함 관계와 세 가지 축(컨텍스트, 제약, GC), 그리고 그것들을 잇는 피드백 루프까지 훑었다.
이번 글의 질문은 하나다. “그래서 하네스 엔지니어링은 어떻게 하는 건데?”
답은 결국 멀티 에이전트 오케스트레이션 구조로 수렴하고, 그 구조의 핵심에 TDD와 QA가 있다. (스킬이나 훅처럼 중요한 것들이 더 있지만 여기선 넘어간다)
▍에이전트 네트워크: 조직 단위의 조감도
먼저 한 발 물러서 전체 그림을 보자. 에이전트 시스템은 프로젝트 하나에 갇히지 않는다.
조직 안에는 여러 팀이 있고 각 팀은 여러 프로젝트를 운영하는데, 에이전트 시대에는 각 프로젝트가 독립된 에이전트 시스템을 갖는다. 대표 에이전트 하나와 그 아래 서브 에이전트들이 프로젝트 단위의 기본 구성이 된다.
이 단위들이 모이면 에이전트 네트워크가 된다. Team A의 에이전트가 만든 API를 Team B의 에이전트가 소비하고, Team C의 에이전트가 그 위에 UI를 올린다. 사람 간 협업이 에이전트 간 협업으로 확장되는 셈이다.
여기서 중요한 게 하나 있다. 네트워크가 커질수록 각 노드의 에이전트가 얼마나 믿을 만한 출력을 내느냐가 전체 품질을 결정한다. Team A의 에이전트가 버그 있는 API를 배포하면 그걸 소비하는 Team B와 C의 에이전트도 줄줄이 실패한다.
그래서 개별 프로젝트의 에이전트 아키텍처, 특히 검증 체계가 네트워크 전체의 건강을 좌우한다. 이제 프로젝트 하나의 안을 들여다보자.
▍대표 에이전트: 전체 컨텍스트를 쥔 오케스트레이터
멀티 에이전트 시스템을 설계할 때 가장 먼저 부딪히는 문제는 누가 전체를 보는가다.
서브 에이전트 10개가 각자 자기 일만 하면 전체 그림을 아는 쪽이 없다. A 에이전트가 바꾼 스키마를 B 에이전트가 모르면 충돌이 난다. 이걸 푸는 패턴이 대표 에이전트(Representative Agent) 구조다.
대표 에이전트가 쥐고 있는 것은 이렇다.
- 시스템 프롬프트: 에이전트의 정체성, 역할 범위, 금지 사항
- 세션 상태: 현재 작업 맥락, 사용자 요청, 진행 상황
- 슬라이딩 윈도우: 최근 대화와 도구 호출 이력
- 상태 저장소: 장기 기억과 세션 간 상태 유지
- 스킬/도구 정의: 호출 가능한 함수의 스키마
- 가드레일: 위반 불가능한 규칙
여기서 대표 에이전트는 전체 컨텍스트를 독점하고, 서브 에이전트는 대표가 넘겨준 컨텍스트만 본다. 이 비대칭은 의도적이다. 컨텍스트를 나눠주는 주체가 하나로 명확해야 에이전트 간 충돌을 막을 수 있다.
외부 도구(이슈 트래커, VCS, 메신저, 디자인 툴, 위키)는 MCP 같은 프로토콜로 대표 에이전트에 붙고, 레거시 자료는 벡터DB + RAG로 보강한다. 대표 에이전트가 이 모든 채널의 허브 역할을 한다.
▍서브 에이전트 풀: 전문화된 일꾼들
대표 에이전트 아래에는 서브 에이전트 풀이 있고, 각 에이전트는 하나의 전문 영역을 맡는다.
| 에이전트 | 역할 |
|---|---|
| Doc sync | 코드와 문서 간 불일치 감지 |
| Schema guard | 스키마 변경 감지 + 마이그레이션 검증 |
| Code health | 네이밍, 타입, 복잡도, 중복, 미사용 코드 종합 감시 |
| Security audit | 보안 취약점 스캔 |
| API contract | API 스키마 호환성 검증 |
| Test gen | 테스트 커버리지 감시 + 테스트 자동 생성 |
| E2E test | 엔드투엔드 시나리오 테스트 |
| Bundle watch | 번들 사이즈/성능 감시 |
| Context GC | 불필요한 컨텍스트 정리 |
| … | 프로젝트 요구에 따라 동적 확장 |
작동 방식은 단순하다. 대표 에이전트가 컨텍스트를 분배하면 서브 에이전트가 작업을 실행하고, 그 결과를 대표 에이전트가 종합한다. 이 과정에서 나온 피드백이 다시 대표 에이전트로 돌아온다.
서브 에이전트 풀은 동적으로 늘어난다. 새로운 검증 요구가 생기면 에이전트를 하나 더 붙이면 되는데, 이 유연성이 고정된 CI 파이프라인과 갈리는 지점이다.
트리거는 네 가지다. CI 이벤트(PR 머지 시), 스케줄러(주기적 스캔), VCS 액션(코드 변경 감지), 웹훅(외부 시스템 이벤트). Hook이 서브 에이전트를 자동으로 깨운다.
▍TDD와 QA가 핵심인 이유
위 서브 에이전트 목록을 다시 보면 눈에 띄는 게 있다. 대부분이 “검증” 에이전트다.
순수하게 정리만 하는 에이전트는 Context GC 정도고 나머지는 전부 검증인데, 이렇게 된 데는 이유가 있다.
하네스 엔지니어링의 피드백 루프를 떠올려 보자. 에이전트가 작업하고, 검증하고, 실패하면 고치고, 또 검증한다. 이 루프가 반복될수록 사람이 직접 확인하지 않은 코드 수정이 쌓인다. 에이전트가 버그를 고치면서 옆에 있던 핵심 로직을 건드릴 수도 있고, 리팩토링하면서 기존 동작을 미묘하게 바꿔놓을 수도 있다. 문제는 사람이 그 변경을 일일이 따라가기 어렵다는 데 있다.
사실 이건 에이전트만의 문제가 아니다. 팀 단위 개발에서도 “이전에 돌아가던 게 어느 순간 안 돌아간다”는 일은 늘 있었다. 누군가 공통 모듈을 고치면서 다른 팀 기능이 깨지고, 머지하고 나서야 발견되는 식이다. 다만 AI로 개발하는 게 주류가 되면서 이런 상황이 훨씬 잦아졌다. 코드 변경의 속도와 양이 사람이 따라갈 수 있는 범위를 넘어서기 때문이다.
코드베이스가 커지고 루프가 빨라질수록 사람 몰래 깨지는 것들이 늘어난다. 에이전트가 코드를 못 짜는 게 아니라, 잘 짜면서 다른 걸 부순다.
이 문제의 해법이 TDD다. 다만 여기서 말하는 TDD는 테스트를 먼저 작성하라는 전통적 의미에 머무르지 않는다.
핵심은 에이전트에게 TDD 원칙대로 코드를 짜게 시키는 것이다. 작은 함수, 명확한 인터페이스, 느슨한 결합, 단일 책임. 이렇게 짜인 코드라야 QA 에이전트가 의미 있는 테스트를 자동으로 만들어낼 기반이 생긴다.
흐름은 이렇다.
- 에이전트가 테스트 가능한 구조로 TDD 기반 코드를 작성한다
- QA 에이전트가 그 코드를 분석해 테스트를 자동 생성한다
- 에이전트가 생성된 테스트로 자기 코드를 검증한다
코드가 스파게티면 QA 에이전트도 좋은 테스트를 만들 수 없다. 함수 하나가 500줄이고 전역 상태에 의존하면 어떤 테스트를 짜야 할지 에이전트도 알 수 없다. 반대로 코드가 잘 구조화돼 있으면 각 함수의 입출력을 보고 경계값과 예외 케이스, 통합 시나리오를 스스로 뽑아낸다.
이유가 하나 더 있다. AI가 모든 시나리오를 알아서 떠올리기는 어려워서, 사람이 “이 경우도 테스트해야 한다”고 짚어주는 일이 남는다. 그때 QA 에이전트가 코드만 보고 해당 테스트를 정확히 만들어낼 수 있어야 하는데, 코드가 테스트 가능한 구조가 아니면 사람이 시나리오를 아무리 잘 정의해도 에이전트가 그걸 테스트로 옮기지 못한다.
결국 개발 품질이 테스트 품질을 정하고, 테스트 품질이 검증의 신뢰도를 정한다. 사람이 모든 변경을 리뷰하지 않아도 테스트가 통과하는 한 핵심 동작은 보존된다.
이건 개인적인 의견이 아니다. Anthropic의 공식 베스트 프랙티스 문서도 같은 얘기를 한다.
Include tests, screenshots, or expected outputs so Claude can check itself. This is the single highest-leverage thing you can do.
Claude performs dramatically better when it can verify its own work. Without clear success criteria, it might produce something that looks right but actually doesn’t work. You become the only feedback loop, and every mistake requires your attention.
— Best Practices for Claude Code, Anthropic
에이전트에게 자기 검증 수단을 쥐여주라는 얘기고, 그 검증 수단의 품질은 코드 자체의 품질에 달려 있다.
사람의 TDD는 테스트를 먼저 쓰면 설계가 좋아진다는, 좋지만 선택할 수 있는 습관이었다. 에이전트의 TDD는 테스트 가능하게 짜야 에이전트가 스스로 검증할 수 있다는, 빠질 수 없는 조건이 됐다.
▍피드백 루프의 실체
전편에서 하네스의 핵심이 피드백 루프라고 했는데, TDD 기반 개발을 얹으면 이 루프가 구체적으로 이렇게 돈다.
- 에이전트가 테스트 가능한 구조로 코드를 작성한다
- QA 에이전트가 코드를 분석해 테스트를 자동 생성한다
- 생성된 테스트를 실행한다
- 실패하면 어디가 깨졌는지 즉시 드러나고, 에이전트가 스스로 고친다
- 전부 통과하면 비로소 다음 작업으로 넘어간다
이 루프에서 테스트가 빠지면 에이전트가 “됐습니다”라고 할 때 그걸 믿는 수밖에 없다. 그런데 에이전트의 자기 평가는 믿을 게 못 된다. “코드를 짰고 잘 작동할 것 같습니다”는 사람도 에이전트도 똑같이 틀릴 수 있는 판단이다. 테스트는 다르다. 통과하거나 실패하거나 둘 중 하나다.
다만 코드가 TDD 원칙대로 짜여 있지 않으면 2번 단계에서 QA 에이전트가 의미 없는 테스트를 만든다. 거대한 함수 하나를 통째로 호출하는 테스트는 어디가 깨졌는지 알려주지 않는다. 검증의 정밀도는 코드의 구조에 비례한다.
서브 에이전트의 대부분이 검증 에이전트인 이유도 여기 있다. Code health, API contract, E2E test, Schema guard는 전부 에이전트가 뭔가를 바꿀 때마다 기존 것이 깨지지 않았는지 확인하는 장치인데, 이 장치들이 제대로 돌려면 코드 자체가 검증 가능한 구조여야 한다.
▍마무리
하네스 엔지니어링에서 에이전트를 잘 다룬다는 건, 결국 에이전트가 스스로 품질을 보증할 수 있는 구조를 만드는 일이다.
대표 에이전트가 컨텍스트를 분배하고, 서브 에이전트가 작업을 실행하고, 결과를 종합한다. 이 오케스트레이션이 제대로 돌아가려면 각 단계에서 이전에 되던 것이 여전히 되는지 확인할 수 있어야 하는데, 그 확인의 기반이 테스트다.
시작은 간단해도 된다. 에이전트에게 코드를 시킬 때 테스트 가능한 구조로 짜게 하고, QA 에이전트가 그 코드에서 테스트를 만들게 하고, 에이전트가 스스로 검증하게 하면 된다. 그게 하네스 엔지니어링의 첫걸음이다.
▍참고 자료
- Anthropic, Best Practices for Claude Code — “Give Claude a way to verify its work”
- 전편: 하네스 엔지니어링: 프롬프트 너머의 세계