하네스 엔지니어링의 핵심: 에이전트 오케스트레이션과 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줄이고 전역 상태에 의존하면, 어떤 테스트를 짜야 할지 에이전트도 알 수 없다. 반대로 코드가 잘 구조화되어 있으면, QA 에이전트는 각 함수의 입출력을 보고 경계값, 예외 케이스, 통합 시나리오를 자동으로 도출할 수 있다.
여기에 또 하나의 이유가 있다. 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 기반 개발을 적용하면 이 루프가 구체적으로 이렇게 돌아간다.
- 에이전트가 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”
- 전편: 하네스 엔지니어링: 프롬프트 너머의 세계