본문으로 건너뛰기

© 2026 Molayo

Dev.to헤드라인2026. 05. 26. 23:13

코딩 에이전트를 위한 하네스(Harness) 구축하기: 8가지 실패 모드와 8가지 기둥

요약

코딩 에이전트의 성능을 극대화하기 위해 모델 주변에 구축해야 하는 '하네스(Harness)' 시스템의 개념과 구성 요소를 설명합니다. 지침, 도구, 권한, 컨텍스트, 검증을 핵심 기둥으로 삼아 에이전트가 프로젝트를 이해하고 작업을 수행하는 체계를 다룹니다.

핵심 포인트

  • 하네스는 모델을 감싸는 지침, 도구, 권한, 컨텍스트, 검증 계층임
  • Claude Code와 Codex는 대표적인 하네스 사례임
  • 훌륭한 하네스는 기존 도구들을 결합하여 에이전트의 컨텍스트를 확보함
  • 에이전트가 프로젝트의 규칙과 컨벤션을 이해하도록 돕는 것이 핵심임

AI를 활용해 제품을 만드는 팀들은 대개 두 가지 제품을 만들게 됩니다. 하나는 그들이 출시하는 제품 자체이고, 다른 하나는 그 제품을 만드는 데 에이전트(Agent)를 유용하게 만들어 주는 에이전트 주변의 시스템입니다.

우리는 Nimbalyst를 출시하기 위해 이러한 시스템을 구축했습니다. 우리는 이를 '팀 하네스(team harness)'라고 부릅니다. 이 포스트는 이를 구축하며 우리가 배운 점에 관한 것입니다.

하네스(Harness)란 무엇인가

하네스는 모델 주변을 감싸는 내구성이 있는 계층입니다: 지침(Instructions), 도구(Tools), 권한(Permissions), 컨텍스트(Context), 그리고 검증(Verification)이 그것입니다.

이런 의미에서 Claude CodeCodex는 하네스입니다. 각각은 시스템 프롬프트(System Prompt), 도구 인터페이스(Tool Surface), 권한 모델(Permission Model), 그리고 실행 루프(Execution Loop)로 모델을 감싸고 있습니다. Anthropic과 OpenAI가 바로 그 계층을 소유하고 있습니다.

여러분의 팀은 그 다음 상위 계층을 소유합니다: 에이전트가 여러분과 함께 파일, 작업(Tasks), 다이어그램(Diagrams), 디프(Diffs), 그리고 결정 사항들을 가지고 제품 작업을 수행하는 워크스페이스(Workspace)입니다. 이 계층은 여러분의 팀이 축적한 지식을 담고 있습니다: 어떻게 무언가를 만드는지, 이미 무엇을 결정했는지, 무엇이 무엇과 연결되어 있는지, 에이전트가 어디에서 활동할 수 있는지, 그리고 에이전트가 자신의 작업을 어떻게 확인하는지에 대한 지식입니다.

컨텍스트(Context)와 하네스(Harness) 사이의 경계는 모호해질 수 있습니다. 티켓(Ticket)이나 명세서(Spec)는 작업에 특화된 컨텍스트이지만, 해당 티켓을 검색 가능하고, 연결 가능하며, 버전 관리가 되고, 어떤 에이전트에 의해서도 검색(Retrievable)될 수 있게 만드는 메커니즘은 하네스의 일부입니다.

훌륭한 하네스에서 완전히 새로운 것은 거의 없습니다. 그것은 대부분 여러분의 프로젝트 주변에 조립된 다른 사람들의 부품들입니다: Claude Code, Codex, MCP, Playwright, 트래커(Tracker), 다이어그램 도구, 에디터(Editor), 테스트 러너(Test Runner), 여러분의 리포지토리(Repository), 여러분의 문서(Docs) 등입니다. 하네스는 에이전트가 작업을 위해 적절한 컨텍스트를 가져오고 자신이 생성한 것을 검증할 수 있도록 이러한 조각들을 결합하는 방식입니다.

이 포스트의 나머지 부분에서는 각 기둥(Pillar)과 이를 위해 우리가 구축한 것들을 살펴봅니다.

1. 컨텍스트 (Context)

목표: 프로젝트를 파악하는 것.

이것이 해결하는 실패 모드 (Failure mode): 에이전트가 코드베이스(codebase), 규칙, 결정 사항 또는 컨벤션(conventions)을 알지 못하여, 마치 이 프로젝트를 처음 보는 것처럼 모든 문제를 해결하려고 합니다.

컨텍스트(Context)는 우리 프로젝트에 특화된 모든 것을 의미합니다: 코드, 사양(specs), 설계 문서(design docs), 트래커 항목(tracker items), 데이터 모델(data models), 과거의 결정 사항, 컨벤션, 예시 및 레시피(recipes) 등이 포함됩니다.

우리의 하네스(harness)에서 이는 다음과 같은 의미를 갖습니다:

  • 코드, 사양, 계획 및 목업(mockups)이 에이전트가 직접 읽고 편집할 수 있는 형식의 로컬 파일로 존재합니다.
  • 아키텍처 다이어그램(Architecture diagrams)이 슬라이드 데크에 갇힌 스크린샷 대신 Excalidraw 파일로 존재합니다.
  • 결정 사항은 채팅 기록에 파묻히지 않고 트래커 항목(tracker items)으로 캡처됩니다.
  • 버그 이력(Bug histories)을 검색할 수 있어, 에이전트가 증상, 근본 원인(root cause) 및 이전 수정 사항을 확인할 수 있습니다.
  • CLAUDE.mdAGENTS.md와 같은 루트 지침 파일(Root instruction files)이 세션 시작 시 로드되어 에이전트가 나머지 정보들을 참조할 수 있도록 안내합니다.
  • 경로 범위 지정 규칙 파일(Path-scoped rule files)은 에이전트가 관련 디렉토리에 접근할 때만 로드됩니다. 예를 들어, 렌더러(renderer) 코드에는 React 규칙이 나타나고, iOS 패키지에는 Swift 규칙이 나타납니다.
  • 스킬 시스템(skill system)은 반복되는 작업에 대한 재사용 가능한 지침을 보유합니다: 테스트 작성 방법, 분석 이벤트(analytics events) 추가 방법, 패키지 출시 방법 또는 실패하는 화면을 디버깅하는 방법 등입니다.
  • 사용자별 영구 메모리(Persistent per-user memory)는 세션 전반에 걸쳐 선호도와 검증된 접근 방식을 캡처합니다.

렌더러 코드를 편집하는 에이전트는 iOS 규칙을 로드하지 않고 React 규칙을 로드합니다. 회귀(regression)를 수정하는 에이전트는 코드를 작성하기 전에 이전 버그, 근본 원인 및 수정 사항을 찾아냅니다. 각 세션은 프롬프트(prompt)로부터 다시 유도되는 대신, 팀의 축적된 결정 사항이 이미 범위(scope) 내에 포함된 상태로 시작됩니다.

2. 출처 (Provenance)

목표: '왜'를 추적하는 것.

이것이 해결하는 실패 모드 (Failure mode): 에이전트가 이미 존재하는 산출물(artifacts) 간의 연결 고리를 탐색할 수 없어, 모든 변경 사항 뒤에 숨겨진 논리(reasoning)를 매번 다시 설명하거나 재발견해야 합니다.

Provenance(출처/기원)는 코드 변경 사항이 이를 생성한 의도(intent)와 어떻게 연결된 상태를 유지하는지를 의미합니다. 각 변경 사항이 왜 존재하는지에 대한 지속적이고 타입이 지정된(typed) 기록이며, 파일, 세션, 트래커 항목(tracker item), 커밋(commit) 등 어느 방향에서든 탐색할 수 있어야 합니다. 근본적인 데이터 구조는 아티팩트(artifacts) 간의 연결을 담은 타입 지정 그래프(typed graph)이며, 그 가치는 "왜 이것이 이런 방식으로 되어 있는가?"라고 물었을 때 답변을 얻을 수 있다는 점에 있습니다.

우리의 하네스(harness)에서 이는 다음을 의미합니다:

  • 트래커 항목(tracker items), 계획(plans), 사양(specs), 다이어그램(diagrams), 목업(mockups), 세션(sessions), 디프(diffs), 파일(files), 커밋(commits), 그리고 결정(decisions) 간의 타입 지정 링크 그래프(typed link graph).
  • 동일한 워크스페이스(workspace) 내에서 해당 아티팩트들을 위한 퍼스트 클래스 에디터(First-class editors)를 제공하여, 링크가 실제 작업 중인 콘텐츠로 연결되도록 함.
  • 파일 편집 이력을 이를 생성한 세션과 연결하여, 어떤 파일이든 해당 파일을 작성한 대화 내용을 보여줌.
  • 팀이 보유한 다양한 종류의 의도(intent)를 위한 트래커 항목 타입: 버그(bug), 기능(feature), 결정(decision), 계획(plan), 인시던트(incident).
  • 아키텍처 선택이 왜 이루어졌는지 기록하는 결정 트래커 항목(Decision tracker items)을 통해, 향후 세션에서 "왜 이것이 이런 방식으로 되어 있는가?"라고 물었을 때 추측 대신 답변을 얻을 수 있도록 함.
  • 수정 코드가 작성되기 전, 문제를 발견하는 즉시 등록되는 버그 트래커 항목(Bug tracker items)을 통해 증상과 근본 원인(root cause)이 수정 사항에 계속 붙어 있도록 함.
  • 서로 다른 에이전트(agents)가 세션 중에 동일한 그래프를 탐색할 수 있도록 하는 MCP(Model Context Protocol) 인터페이스.

버그는 실패한 스크린샷, 수정 세션, 디프(diff), 그리고 커밋에 연결될 수 있습니다. 기능 요청(feature request)은 계획, 목업, 구현 세션, 그리고 릴리스 노트(release note)에 연결될 수 있습니다. Git은 무엇이 변했는지를 포착합니다. Provenance는 우리가 왜, 그리고 어떻게 그곳에 도달했는지를 포착합니다.

3. Capability (역량)

목표: 행동하고 관찰하기.

이 항목이 해결하는 실패 모드(Failure mode): 에이전트가 세상에 작용하거나 자신이 수행한 일을 관찰할 수 없어, 텍스트 채널에 갇힌 채 사용자에게 모든 명령어를 실행하고 모든 출력을 붙여넣어 달라고 요청하는 상황.

Capability는 에이전트가 라이브 상태(live state)에서 행동하고 자신이 수행한 일을 검증할 수 있게 하는 도구들을 다룹니다: 로그 읽기, 실행 중인 데이터베이스 쿼리, UI 제어, 스크린샷 찍기, 테스트 실행, 그리고 결과가 올바를 때까지 루프(looping)를 도는 것 등입니다.

우리의 하네스(harness)에서 이는 다음을 의미합니다:

  • 실시간 애플리케이션 로그를 읽고, 안전하지 않은 직접 접근 대신 앱을 통해 실행 중인 데이터베이스에 쿼리하는 MCP 도구들.
  • 애플리케이션 자체를 구동하는 도구들: 재시작(restart), 재로드(reload), 확장 프로그램 설치, 코드 핫 리로드(hot-reload).
  • 실행 중인 UI 내부에서 JavaScript를 실행하여 DOM, 상태(state), 또는 아톰(atoms)을 검사하는 렌더러-평가(renderer-eval) 도구.
  • 열려 있는 모든 파일의 렌더링된 콘텐츠를 캡처하는 스크린샷 도구.
  • 에이전트가 실행 중인 앱과 상호작용하고, 스크린샷을 찍고, 결과를 확인할 수 있도록 하는 Playwright 기반의 UI 루프.
  • 에이전트가 매일 사용하는 서드파티 시스템(GitHub, 분석 대시보드, 브라우저, 트래커 등)을 감싸는 MCP 도구들.
  • 에이전트가 테스트, 스크립트, 안전한 코드 수정(codemods)을 실행할 수 있고, 사용자에게 출력을 붙여넣어 달라고 요청하는 대신 wrangler tail, curl, gh 등을 실행할 수 있는 샌드박스 쉘(sandboxed shell).
  • 팀이 자체적인 MCP 도구를 작성하고 워크스페이스 내부에 배포할 수 있는 확장 SDK(extension SDK).

React 컴포넌트를 변경한 후, 에이전트는 화면을 열고 스크린샷을 확인할 수 있습니다. 영속성 로직(persistence logic)을 변경한 후에는 해당 행(row)이 실제로 변경되었는지 확인할 수 있습니다. 세상에 작용하고 그 결과를 관찰할 수 있는 에이전트는 종종 스스로 루프를 닫을(close its own loop) 수 있습니다.

4. 워크플로 (Workflow)

목표: 아크(arcs)를 재사용하는 것.

이것이 해결하는 실패 모드(Failure mode): 에이전트가 모든 작업 수행 방식을 매번 새로 발명하여, 동일한 종류의 작업임에도 매번 형태가 달라지고 세션마다 기본 사항을 다시 설명해야 하는 상황.

워크플로는 코딩 세션의 형태를 의미합니다: 어떻게 시작하는지, 어떻게 계획하는지, 어떻게 도움을 받는지, 그리고 어떻게 병렬화(parallelize)하는지에 대한 것입니다.

우리의 하네스에서 이는 다음과 같습니다:

  • 반복적으로 실행하는 단계(plan, implement, review, release)를 위해 .claude/commands/ 내에 저장된 저장소 로컬(Repo-local) 슬래시 명령어(slash commands).
  • 사소하지 않은 작업(non-trivial work)을 위해 표준적인 '계획 후 실행(plan-then-execute)' 아크(arc)를 사용하여, 에이전트가 파일을 수정하기 전에 접근 방식에 대해 확정(commit)하도록 함.
  • 조사(investigate), 설계(design), 구현(implement)의 진행 과정을 통해, 연구와 계획이 코드와 뒤섞이지 않고 별도의 단계로 수행되도록 함.
  • 광범위한 탐색을 수행하고 메인 세션의 컨텍스트(context)를 보호하기 위해 탐색, 계획, 구현을 담당하는 하위 에이전트(Subagents) 활용.
  • 테스트 작성, 분석 이벤트(analytics events) 추가, 패키지 출시와 같이 재사용 가능한 습관을 위한 스킬 시스템(skill system).

/release-alpha 명령어는 버전 업(version-bump), 변경 사항(changelog), 태그(tag) 단계를 매번 동일한 방식으로 실행합니다. /investigate에 이어 /design을 실행하면, 빈 프롬프트(prompt)에서 처음부터 다시 시작하는 대신 다음 세션에서 이어서 작업할 수 있는 계획 문서(plan document)가 생성됩니다. 워크플로 레이어(workflow layer)는 각 세션이 매번 똑같은 과정을 반복하며 새로 만드는 것을 방지합니다.

5. 절제 (Restraint)

목표: 범위를 벗어나지 않기.

이것이 해결하는 실패 모드(Failure mode): 에이전트를 막을 수 있는 장치가 없어서 에이전트가 위험한 행동을 수행하며, 절제력이 없는 유능한 에이전트는 당신이 예상한 것보다 더 빠르게 그 일을 저지릅니다.

절제는 에이전트가 잘못된 일을 빠르게 수행하지 못하도록 막는 방법입니다. 이는 엄격한 규칙(hard rules), 승인 경계(approval boundaries), 권한 범위(permission scopes), 도구 허용 목록(tool allowlists), 예산 제한(budget limits), 그리고 감사 추적(audit trail)을 포함합니다.

우리의 하네스에서 이는 다음을 의미합니다:

  • 에이전트가 특정 파일이나 디렉토리를 편집하지 못하도록 차단하는 경로 범위 지정 규칙 (Path-scoped rules).
  • .env 파일을 읽거나 자격 증명(credentials)을 건드리는 등 에이전트가 절대 해서는 안 되는 작업에 대한 지침 파일 내의 엄격한 규칙 (Hard rules). 각 규칙에는 왜 그런 규칙이 필요한지를 가르쳐준 과거의 사례가 포함됩니다.
  • 도구별 권한 범위 (Per-tool permission scopes) 및 허용 목록 (allowlists).
  • 공유 상태나 비용이 발생하는 상태를 건드리는 작업에 대한 승인 흐름 (Approval flows): main 브랜치로의 푸시(push), 테이블 삭제(drop a table), 유료 API 호출, 또는 파괴적인 셸 명령(destructive shell command) 실행 등.
  • "파일 편집 가능"과 "모든 작업 가능"을 분리하는 워크스페이스 신뢰 모드 (Workspace trust modes).
  • 승인, 도구 호출(tool calls), 파일 변경 사항에 대한 지속적인 감사 추적 (Durable audit trail).
  • 에이전트가 실제로 무엇을 변경했는지 명확하게 보여주는 검토 인터페이스 (Review surfaces).

실제로 이는 에이전트가 렌더러(renderer) 코드는 리팩터링할 수 있지만 배포 스크립트는 실행할 수 없게 하고, 개발용 데이터베이스는 쿼리할 수 있지만 운영(production) 데이터베이스는 건드릴 수 없게 하며, 유료 서드파티 API를 검증 없이 호출하지 않고 테스트 루프에 토큰을 소비하도록 허용하는 것을 의미합니다. 절제(Restraint)는 능력(capability)과 쌍을 이루는 기둥입니다. 에이전트에게 제공하는 모든 새로운 도구에는 그에 걸맞은 범위(scope)가 지정되어야 하며, 그렇지 않으면 에이전트가 잘못된 컨텍스트에서 해당 도구를 사용하는 순간 그것은 부채(liability)가 됩니다. 우리는 이 두 가지를 함께 구축합니다.

6. 검증 (Verification)

목표: 수정 사항을 증명하는 것.

이 단계가 해결하는 실패 모드: 에이전트가 증거 없이 "수정 완료"라고 환각(hallucinate)을 일으키는 경우입니다. 즉, 자신만만한 발표와 실제로 작동하는 변경 사항은 서로 다른 문제입니다.

검증은 에이전트가 변경 사항을 반환하기 전에 해당 변경이 제대로 작동함을 증명하는 방법입니다. 이는 테스트, 타입 체크(type checks), 버그의 실패 우선 재현(fail-first reproduction), 그리고 에이전트 자신의 도구 호출에 대한 시뮬레이션 실행을 포함합니다.

우리의 하네스에서 이는 다음을 의미합니다:

  • 실패 테스트 우선 원칙 (failing-test-first discipline): 수정 사항을 작성하기 전에 실패하는 테스트를 먼저 작성하여, 다음 에이전트가 다시 실행할 수 있도록 버그에 대한 재현 방법 (reproduction)을 남깁니다.
  • 여러 패키지에 걸쳐 실행되며 로직 수준의 변경 사항에 대해 빠른 피드백을 제공하는 Vitest 단위 테스트 (unit suite).
  • 실제 흐름을 위한 Playwright 엔드 투 엔드 (E2E) 테스트. 실패 지점이 한 곳을 가리킬 수 있도록 실행당 하나의 스펙 (spec)을 사용합니다.
  • E2E 스펙이 실제 모델 비용을 지불하지 않고도 AI 도구 호출을 가짜로 수행(fake)하고 에이전트가 수행한 작업을 검증(assert)할 수 있게 해주는 AI 도구 시뮬레이터 (AI tool simulator).
  • 에이전트가 테스트를 실행하기도 전에 드리프트 (drift)를 포착할 수 있도록 루프 내에 내장된 빠른 타입 체크 (type checks).

동기화 버그에 대한 수정은 깨진 문서를 열고 본문이 로드되는지 검증하는 Playwright 스펙에서 시작하며, 그 후 에이전트는 해당 스펙이 통과(green)될 때까지 코드를 수정합니다. 렌더러 변경의 경우, 에이전트가 완료했다고 주장하기 전에 단위 테스트 스위트와 타입 체크를 실행합니다.

에이전트가 변경 사항이 엔드 투 엔드 (end-to-end)로 작동함을 보여줄 수 없다면, 작업이 완료된 것이 아닙니다.

7. 시각적 인터페이스 (Visual interface)

목표: 작업 내용을 보여주는 것.

이 항목이 해결하는 실패 모드 (Failure mode): 에이전트가 유용한 형태로 인간에게 결과를 보여줄 수 없어, 결정 사항, 차이점 (diffs), 그리고 결과물 (artifacts)이 아무도 제대로 검토하지 않는 채팅 텍스트의 벽 속으로 사라져 버리는 경우.

많은 소프트웨어 작업은 시각적입니다. 마크다운 (Markdown) 검토, UI 목업 (mockups), 아키텍처 다이어그램, 데이터 모델, 차이점 (diffs), 스크린샷, 스케치는 작업 입력의 일부이지 단순한 프레젠테이션 장식이 아닙니다. 따라서 이들은 에이전트가 작업을 수행하는 워크스페이스 (workspace)에 속해야 합니다.

시각적 인터페이스는 에이전트가 작업하는 곳이자, 우리가 에이전트가 수행한 내용을 동일한 장소에서 검토하는 곳입니다. 음성, 대화형 프롬프트 (interactive prompts), 그리고 워크스루 (walkthroughs)는 텍스트나 정적 시각 자료가 적절한 형식이 아닐 때 동일한 워크스페이스가 조율하는 채널들입니다.

우리의 하네스 (harness)에서 이는 다음을 의미합니다:

AI 자동 생성 콘텐츠

본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0