
3. harness-starter-kit은 마법이 아니다. 에러를 빠르게 드러내기 위한 것이다
요약
harness-starter-kit을 활용한 에이전트 개발 경험을 공유합니다. 이 키트는 에이전트를 즉시 똑똑하게 만들기보다, 에러를 빠르게 발견하고 기록하며 검사할 수 있는 구조를 제공하는 데 목적이 있습니다.
핵심 포인트
- harness-starter-kit은 에러를 발견하고 기록하는 장소를 제공함
- 에이전트의 실수를 줄이기 위해 decision/failure docs 활용
- 기존 프로젝트의 워크플로우를 유지하며 커스텀 체크 가능
- Django 및 Next.js 프로젝트를 통한 실전 테스트 진행
안녕하세요. 한국 출신의 주니어 개발자입니다.
일본어는 도구의 도움을 받으며 다듬고 있습니다. 조금 부자연스러운 표현이 있더라도 양해 부탁드립니다.
지난 기사에서는 harness-starter-kit을 실제 프로젝트에 도입해 본 첫 경험을 작성했습니다.
그때 제가 가장 신경 썼던 부분은 다음과 같은 것들이었습니다.
- 에이전트(Agent)가 템플릿을 대충 복사하지는 않을까
- 기존 프로젝트의 구조를 망가뜨리지는 않을까
- 아무도 유지보수하지 않아
docs/디렉토리만 늘어나는 것은 아닐까
이번에는 그 후 dogfood를 계속하면서 배운 점을 작성합니다.
harness의 가치는 에이전트를 즉시 똑똑하게 만드는 것이 아닐지도 모릅니다.
더 현실적인 가치는 에러를 빠르게 드러내고, 그 에러를 리포지토리(Repository)에 기억시키는 것입니다.
처음에는 저도 이렇게 생각했습니다.
프로젝트에 AGENTS.md, 검사 스크립트, decision docs, failure docs가 있다면 에이전트의 실수는 분명히 줄어들 것이라고 말입니다.
지금은 그렇게 말하기에는 조금 이르다고 생각합니다.
에이전트는 여전히 실수를 합니다.
예를 들어, 다음과 같은 일이 일어날 수 있습니다.
- 경계 조건(Boundary condition)을 잊어버림
- 현재 프로젝트에 맞지 않는 구현을 작성함
- 검사를 하나 누락함
- 어떤 실패를 일시적인 문제로 치부하고 넘어가 버림
- 변경해서는 안 되는 생성 파일을 편집함
그래서 지금의 저는 이렇게 말하지 않습니다.
harness-starter-kit에 의해 에이전트가 똑똑해졌다.
오히려 이렇게 말하고 싶습니다.
harness-starter-kit은 일부 에러를 발견하고, 기록하고, 검사하고, 재사용할 수 있는 장소를 만든다.
이 두 가지는 상당히 다릅니다.
현재 저는 주로 두 개의 실제 프로젝트에서 이 스타터 키트(Starter kit)를 테스트하고 있습니다.
하나는 Django 프로젝트입니다.
harness_starter_kit_django
다른 하나는 Next.js 프로젝트입니다.
today-bus
이 두 가지는 역할이 조금 다릅니다.
Django dogfood repo는 안정적인 샘플에 가까운 존재입니다.
그 안에는 다음과 같은 것들이 있습니다.
AGENTS.md
docs/decisions/
docs/failures/
scripts/check_harness.py
.github/workflows/harness-check.yml
.harness/source.json
- adoption report / update report
이 프로젝트에서 확인할 수 있었던 점이 있습니다.
starter kit은 대상 프로젝트를 특정 공통 구조로 바꿀 필요가 없습니다.
Django 프로젝트가 원래 가지고 있는 커맨드(Command)나 워크플로우(Workflow)에 맞출 수 있습니다.
예를 들어, 이 repo의 normal check는 Python다운 형태입니다.
python scripts/check_harness.py
이 래퍼(Wrapper)는 대략 다음과 같은 체크를 실행합니다.
- docs drift check
- structure check
- encoding hygiene check
- effectiveness plan check
manage.py check
manage.py test
동일한 체크를 GitHub Actions에도 연결했습니다.
이 repo는 저에게 다음과 같은 dogfood 사례입니다.
안정적인 local / CI harness의 dogfood 샘플.
한편으로는 문제도 발견되었습니다.
local kit reference에 refresh gap이 있었던 것입니다.
즉, target repo가 기록하고 있는 starter kit source와 현재 starter kit의 최신 내용 사이에 차이가 발생할 수 있습니다.
그렇기 때문에 /harness update와 .harness/source.json이 중요해집니다.
그렇지 않으면 harness를 채택한 후, 대상 repo가 어떤 버전의 kit을 참조하고 있는지 알기 어려워지기 때문입니다.
또 다른 dogfood repo는 today-bus입니다.
이것은 Next.js 프로젝트이며, 목적은 다음과 같습니다.
구미역 열차 시간에 맞추기 위해, 언제 출발해야 하는지, 어느 버스 정류장까지 걸어가야 하는지, 어떤 버스를 타야 하는지를 계산합니다.
이 프로젝트는 많은 외부 데이터 소스 (external data sources)에 의존하고 있습니다.
- TAGO public transit API
- Gumi BIS timetable
- TMAP walking route
- OpenRouteService walking route
- Kakao map input
그렇기 때문에 Django dogfood 보다 복잡합니다.
여기서 자주 발생하는 문제는 단순한 lint error가 아닙니다.
- live API와 mock fallback을 어떻게 분리할 것인가
- provider가 빈 결과 (empty result)를 반환했을 때 어떻게 처리할 것인가
- service key를 client에 노출하지 않는 것
- 외부 API 파라미터의 대소문자가 일치하지 않는 것
- live smoke check를 default gate에 포함시켜도 되는가
- failure note에 단순히 "문제가 있었다"라고만 적는 것이 아니라, 재발 방지 방법까지 적는 것
Today Bus의 normal gate는 현재 다음과 같습니다.
npm run check:harness
대략 다음과 같은 처리를 실행합니다.
npm run lint
npm run test:planner
npm run typecheck
...
여기서 test:planner는
deterministic local test입니다.
live API에 의존하지 않으므로, normal gate에 넣기 쉬운 테스트입니다.
반면, TAGO / TMAP / OpenRouteService의 live smoke check는 쉽게 default gate에 넣어서는 안 됩니다.
이것들은 다음 요소들에 의존하기 때문입니다.
- credentials
- network
- quota
- provider uptime
- 현재 공공 데이터의 상태
이러한 구분은 저에게 중요했습니다.
이전이었다면 단순히 이렇게 생각했을지도 모릅니다.
API smoke check가 있다면 전부 실행하면 된다고 말이죠.
지금은 조금 더 신중합니다.
deterministic local check는 normal gate에 넣습니다.
live API check는 그것이 정말로 안정적이고 안전하며, default verification에 적합한 경우를 제외하고는 focused/manual 상태로 유지합니다.
Today Bus에서 한 번, npm run check:harness가
실패한 적이 있습니다.
처음에는 나쁜 소식처럼 보였습니다.
하지만 나중에 보니, 이것은 harness가 제대로 작동한 사례였습니다.
실패한 것은 다음 명령어였습니다.
npm run typecheck
에러는 .next/dev/types/validator.ts를
가리키고 있었습니다.
이것은 Next.js dev server가 생성하는 타입 파일이며, 애플리케이션의 소스 코드가 아닙니다.
문제는 "app source의 구현이 틀렸다"는 것이 아니었습니다.
활성화된 dev server가 stale / malformed 된 generated artifact를 남겼고, tsc가 그것을 읽어버린 것이 문제였습니다.
여기서 중요한 점은 다음과 같습니다.
.next/ 하위의 생성된 파일을 수동으로 수정해서는 안 된다.
check를 통과시키기 위해 generated output을 편집해서는 안 된다.
결과적으로 다음과 같이 대응했습니다.
next typegen && tsc --noEmit --incremental false
즉, npm run typecheck를 하기 전에 Next.js generated types를 업데이트하고, 그 후에 TypeScript check를 실행하도록 했습니다.
이 실패는 채팅 로그에만 남지 않았습니다.
failure record로서 다음 파일에 남았습니다.
docs/failures/0005-next-dev-validator-typecheck-artifact.md
동시에, decision(결정 사항)도 기록했습니다.
docs/decisions/0017-refresh-next-generated-types-before-typecheck.md
여기에, 현재 제가 harness의 가치를 느끼는 이유가 있습니다.
이전 같았으면, 이 문제는 이렇게 끝났을지도 모릅니다.
"다음부터는
next typegen
을 먼저 실행하자."
그리고 다음 새로운 세션에서는 또 잊어버립니다.
지금은, repo의 durable memory (지속성 메모리)가 되었습니다.
- 무엇이 실패했는가
- 왜 실패했는가
- 무엇을 변경해서는 안 되는가
- 현재의 대체책은 무엇인가
- 어떤 check (검사)가 다시 이를 탐지할 수 있는가
이전부터 failure note (실패 기록)를 작성하는 일은 있었습니다.
하지만 지금은, "무슨 일이 일어났는가"만을 적는 것으로는 부족하다고 생각합니다.
예를 들어, 다음과 같은 기록입니다.
어떤 API 파라미터의 대소문자가 틀렸다
어떤 provider (제공자)가 이상한 error (에러)를 반환했다
어떤 CI가 실패했다
물론, 이러한 기록에도 의미는 있습니다.
하지만, 검사(inspection)로 이어지지 않는다면, "읽으면 도움이 되지만, 동일한 실패를 방지할 수는 없는 문서"가 되기 쉽습니다.
그래서 kit에서는 다음의 사고방식을 강조하고 있습니다.
failure memory (실패 메모리)는 detection (탐지) 또는 prevention (방지)으로 이어져야 합니다.
즉, docs/failures/*.md에는 다음과 같은 정보가 필요합니다.
- 어떤 test (테스트)가 이 실패를 탐지하는가
- 어떤 fixture (픽스처)가 이 케이스를 커버하는가
- 어떤 smoke check (스모크 체크)가 검증할 수 있는가
- 어떤 lint / drift check (린트 / 드리프트 체크)가 이를 차단하는가
- 자동화할 수 없는 경우, 어떤 manual review point (수동 검토 지점)에서 확인하는가
Today Bus의 TAGO 파라미터 대소문자 문제는 그 한 예입니다.
어떤 endpoint (엔드포인트)가 필요로 했던 것은 다음 이름이었습니다.
nodeid
하지만 실수로 다음과 같이 취급했습니다.
nodeId
이 작은 차이로 인해, provider는 단일 버스 정류장에서의 필터링을 수행하지 않고 검색 범위가 넓어졌으며, 경우에 따라서는 rate limit (속도 제한)에 근접하게 되었습니다.
이 문제는 failure note에 적는 것으로 끝내지 않았습니다.
planner/provider test (플래너/프로바이더 테스트)에도 연결했습니다.
단순히 "nodeid의 대소문자에 주의"라고 적는 것보다, 이쪽이 훨씬 더 신뢰할 수 있습니다.
이 과정에서 한 가지 더 명확해진 것이 있습니다.
Harness Doctor는 유용하지만, 에이전트가 강해졌음을 증명하는 도구는 아닙니다.
Doctor가 볼 수 있는 것은, repo에 durable evidence (지속성 증거)가 있는지 여부입니다.
- agent instructions (에이전트 지침)
- local checks (로컬 검사)
- decision records (결정 기록)
- failure records (실패 기록)
- adoption report (채택 보고서)
- CI / validation hints (CI / 검증 힌트)
이것은 harness health signal (harness 건강 신호)입니다.
하지만 다음 사항들은 증명할 수 없습니다.
- 에이전트가 잘못된 파일을 변경하기 어려워졌는가
- 동일한 버그를 반복하기 어려워졌는가
- reviewer (검토자)의 재작업이 줄었는가
- first-pass verification (1차 검증)의 성공률이 높아졌는가
이것들은 task outcome records (작업 결과 기록)나 effectiveness report (효과성 보고서)를 통해 확인해야 합니다.
그래서 지금은 다음과 같이 나누고 있습니다.
Harness health:
repo에 durable rules / checks / memory가 있는가
Agent effectiveness:
...
이것이 제가 이 프로젝트를 과도하게 홍보하고 싶지 않은 이유이기도 합니다.
말할 수 있는 것은 다음과 같습니다.
이 kit는 규칙, 체크, 실패 경험을 리포지토리에 두는 데 도움을 주었습니다.
하지만 아직 이렇게는 말할 수 없습니다.
에이전트의 품질이 명확히 향상되었다고 증명할 수는 없습니다.
후자에는 더 많은 실제 작업 데이터가 필요합니다.
지금 저는 target repo의 harness가 성숙했는지 여부를 docs의 유무만으로 판단하지 않습니다.
오히려 다음과 같은 시그널을 보고 있습니다.
-
에이전트가
AGENTS.md -
프로젝트 규칙을 읽을 수 있는지 - normal verification gate (정상 검증 게이트)가 명확한지
-
deterministic local checks (결정론적 로컬 체크)가 normal gate에 포함되어 있는지
-
live / slow / credential-based checks (라이브 / 슬로우 / 자격 증명 기반 체크)가 분리되어 있는지
-
docs/decisions/에 실제 구조적 의사결정이 기록되어 있는지 -
docs/failures/에 반복하고 싶지 않은 실패가 기록되어 있는지 - failure note (실패 노트)가 test / fixture / smoke check (테스트 / 피스처 / 스모크 체크)로 이어지는지 -
/harness update가 파일 덮어쓰기가 아닌 selective refresh (선택적 새로고침)로 작동하는지 -
Harness Doctor의 점수와 effectiveness claim (효과성 주장)이 분리되어 설명되어 있는지
하나하나를 뜯어보면 복잡하지 않습니다.
다만, 이것들이 결합되면 에이전트의 작업이 단발적인 채팅 컨텍스트 (chat context)에 의존하는 것을 줄여줍니다.
지금의 저에게 harness-starter-kit은 단순한 installer (설치 프로그램)가 아닙니다.
오히려 다음과 같은 루프 (loop)입니다.
규칙을 발견한다
리포지토리에 기록한다
가능한 한 검사(check)로 만든다
...
첫 adoption (도입) 단계만 보면, 단순히 몇 개의 파일을 추가한 것처럼 보일 수도 있습니다.
하지만 지속적으로 dogfood (자사 제품 사용)를 해보면, 정말 가치 있는 것은 feedback loop (피드백 루프)라는 것을 알게 됩니다.
특히 실패가 발생한 후, repo (리포지토리)는 다음과 같은 질문을 던질 수 있게 됩니다.
- 이 실패를 기록해야 하는가
- 기록한다면, 어떤 check (체크)가 이를 감지할 수 있는가
- check가 없다면, 그 이유는 무엇인가
- 이 규칙을 AGENTS, ADR, failure note, final report 중 어디에 두어야 하는가
- 이 변경 사항을 normal gate에 넣어야 하는가, 아니면 focused/manual (집중/수동) 상태로 유지해야 하는가
이러한 질문들은 에이전트의 업무를 "코드를 작성하고 끝"내는 것으로 만들지 않기 위한 것입니다.
앞으로도 더 많은 실제 프로젝트에서 evidence (증거)를 수집하고 싶습니다.
예를 들어, 다음과 같은 것들입니다.
- 더 많은 adoption report (도입 보고서)
- 더 많은 task outcome records (작업 결과 기록)
- Go / Rust / iOS / Rails / Laravel 프로필
- monorepo (모노레포) 도입 사례
- GitLab CI 도입 노트
- 더 이해하기 쉬운 workflow diagram (워크플로우 다이어그램)
- README onboarding (온보딩) 개선
그리고 다음 사항도 계속 관찰하고 싶습니다.
동일한 종류의 agent mistake (에이전트 실수)가 정말로 줄어드는가.
아니면, 적어도 이전보다 더 빨리 발견되게 되는가.
Doctor score (닥터 점수)가 올라가는 것만으로는 불충분합니다.
정말로 가치 있는 것은 다음과 같은 일들입니다.
- reviewer (리뷰어)의 재작업 (rework)이 줄어든다
- known failure (알려진 실패)의 재발이 줄어든다
- check가 문제를 더 빨리 표면화한다
- 새로운 세션에서도 프로젝트 컨텍스트 (project context)를 이어받기 쉬워진다
GitHub:
Cursor / Claude Code / Codex와 같은 coding agent (코딩 에이전트)를 자주 사용하면서,
"새로운 세션마다 프로젝트 규칙을 다시 설명해야 하는 것"에 어려움을 겪고 계신 분이 있다면 꼭 확인해 보세요.
이 접근 방식에 문제가 있다고 생각하신다면, 언제든 솔직하게 지적해 주세요.
저는 아직 주니어 개발자이기에, 미사여구보다는 실제로 도움이 되는 피드백을 원합니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Qiita AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기