DX 하네스 v2: 복사형 도구에서 사내 개발 운영 플랫폼까지
규칙 문서가 아니라 같은 행동을 만드는 하네스
공통 정책과 소유권 경계, ./harness CLI와 doctor, Claude Code·Codex의 규칙 집행 방식, 회귀 검증과 패키징 구조까지 직접 설계하고 구현했습니다.
Spec Kit·Superpowers·Playwright MCP는 제가 만든 도구가 아닙니다. 각 도구의 역할을 구분하고, 하나의 작업 흐름과 검증 기준 안에서 동작하도록 선택하고 통합했습니다.
하네스를 만들며 가장 중요하게 본 질문은 다음과 같았습니다.
규칙이 문서에 존재하는 것을 넘어, 어떤 AI 에이전트와 세션을 사용하더라도 같은 지점에서 멈추고 같은 검증을 수행하게 만들 수 있는가?
결론부터 말하면 같은 규칙을 여러 파일에 복사하는 것만으로는 충분하지 않았습니다. Claude Code와 Codex는 규칙을 읽는 위치, hook을 호출하는 시점, 명령을 해석하는 방식이 달랐습니다. 그래서 규칙의 완성 기준을 문서의 동일성이 아니라 같은 상황에서 같은 행동이 검증되는 상태로 바꿨습니다.
Jenkins 제거에서 반복 가능한 개발 운영으로
처음 목적은 Jenkins 서버와 플러그인을 직접 관리해야 하는 부담을 줄이는 것이었습니다. 여러 프로젝트가 같은 서버와 배포 대기열을 사용했고, 환경변수도 Jenkins UI에 모여 있어 어떤 프로젝트와 환경의 값이 실제 배포에 사용되는지 추적하기 어려웠습니다.
GitHub Actions와 Infisical로 옮기면서 서버 운영과 시크릿 관리 문제는 줄일 수 있었습니다. 그러나 workflow와 설정 파일을 프로젝트마다 복사하고, 저장소 구조·브랜치·환경·시크릿 경로를 사람이 다시 판단한다면 Jenkins만 제거됐을 뿐 반복 작업은 그대로 남습니다.
그래서 목표를 CI 도구 교체에서 확장했습니다. 프로젝트를 시작하고, 계획하고, 구현하고, 검증하고, 배포하는 과정을 같은 기준으로 반복할 수 있는 운영 구조를 만들기로 했습니다. Jenkins 전환과 Infisical의 상세 구성은 각각의 별도 심화 인사이트에서 다루고, 이 글은 그 이후 하네스 구조가 어떻게 발전했는지에 집중합니다.
하네스는 어떻게 발전했는가
Jenkins 제거와 배포 자동화
→ v1 공통 파일 복사·동기화
→ ./harness CLI와 doctor
→ Claude Code·Codex 규칙 집행과 패리티 검증
→ Spec Kit·Feature Hub 기반 계획 정본화
→ harness.lock·버전 캐시·소유권 경계
→ 감사·회귀 테스트·릴리스 게이트
→ 멀티 세션 실행 격리 실험
초기에는 배포 자동화에서 시작했지만, 실제 프로젝트에 반복 적용하면서 설치·업데이트·규칙 집행·계획 상태·검증·세션 운영까지 범위가 확장됐습니다. 마지막 멀티 세션 단계는 모든 프로젝트에 적용되는 핵심 기능이 아니라 제한된 프로젝트에서 검증한 운영 실험입니다.
v1: 파일을 복사하면 시작은 쉽지만 변경을 전파하기 어렵다
v1에서는 공통 정책과 skill을 각 프로젝트 저장소에 복사했습니다. 프로젝트 하나를 처음 준비할 때는 필요한 파일이 저장소 안에 모두 있어 이해하기 쉬웠습니다.
하지만 약 2개월 동안 사용하면서 프로젝트마다 공통 파일의 버전이 달라지는 문제가 생겼습니다. 규칙을 개선해도 이미 만들어진 프로젝트에는 자동으로 전달되지 않았고, 같은 변경을 여러 저장소에 다시 복사하고 커밋해야 했습니다.
이 경험을 통해 재사용의 기준을 바꿨습니다. 재사용은 같은 파일을 여러 프로젝트에 복사하는 것이 아니라, 공통 변경을 각 프로젝트의 소유권을 침범하지 않고 안전하게 전파할 수 있는 구조여야 했습니다.
CLI와 doctor: 사람이 기억하던 절차를 실행 가능한 계약으로
파일을 배치하는 것만으로는 신규 프로젝트와 기존 프로젝트를 같은 상태로 만들 수 없었습니다. 프로젝트 구조, 패키지 매니저, 브랜치와 환경 매핑, 시크릿 연결, AI 규칙과 skill 경로를 사람이 직접 확인하면 작업자와 세션에 따라 순서와 결과가 달라질 수 있었습니다.
./harness CLI는 이 절차를 하나의 진입점으로 묶습니다. 프로젝트 profile에 따라 허용 경로, 패키지 매니저, 앱 구조와 필요한 규칙을 구성합니다. 외부 저장소나 시크릿처럼 실제 상태를 바꾸는 작업은 자동화 뒤에 숨기지 않고 사용자 판단이 필요한 단계로 드러냅니다.
초기화 명령이 성공했다고 해서 올바르게 설치됐다고 판단하지도 않았습니다. ./harness doctor가 필수 파일, 버전 상태, skill link, hook과 profile을 다시 읽어 현재 상태를 진단합니다.
CLI가 원하는 상태를 만든다면 doctor는 실제 상태가 그 계약과 일치하는지 확인합니다. 내부 도구로서 중요한 것은 명령 수가 아니라 사람이 기억하던 절차를 반복 실행하고 다시 진단할 수 있게 만드는 것이었습니다.
같은 문장을 복사해도 Claude Code와 Codex는 다르게 행동했다
패리티 문제를 실제로 확인한 사례가 있었습니다.
제가 기대한 작업 흐름은 명세를 작성한 뒤 clarify가 필요한지 판단하고, 그 결과를 사용자에게 보고한 다음 명시적인 codi-auto-loop 요청이 있을 때까지 멈추는 것이었습니다.
Claude Code에서는 이 흐름대로 동작했지만 Codex가 사용자 확인 지점에서 멈추지 않고 다음 계획 단계까지 진행한 사례가 있었습니다.
이를 특정 에이전트가 한 번 지시를 잘못 이해한 문제로만 보지 않았습니다. Claude Code와 Codex는 규칙 주입 시점과 command·skill 호출 방식이 다르기 때문에 같은 내용을 적어 두더라도 행동이 달라질 수 있다고 판단했습니다.
이후 다음 handoff를 양 런타임의 공통 계약으로 고정했습니다.
명세 작성
→ clarify 필요성 판단
→ 필요 여부와 생략 사유를 사용자에게 보고
→ 사용자의 명시적인 codi-auto-loop 요청 대기
→ 승인 후 계획·작업 분해 진행
공통 원칙은 .harness/policies에 두고, Claude Code에는 rules·settings·hook, Codex에는 AGENTS·rules·preflight·PreToolUse hook으로 각 런타임에 맞게 연결했습니다.
여기서 끝내지 않고 같은 상황에서 양쪽이 동일한 handoff를 노출하는지 회귀 테스트로 검증했습니다. 위험 명령과 보호 브랜치 차단도 동일한 guardrail 구현과 실제 hook payload fixture를 통해 확인했습니다.
이 경험을 통해 규칙은 작성돼 있는가보다 실제 행동으로 반복 검증되는가가 더 중요하다는 결론을 내렸습니다.
채팅이 아니라 spec을 작업 상태의 정본으로
여러 단계에 걸친 작업을 대화 기록에만 남기면 새로운 세션이나 다른 에이전트가 코드베이스 전체를 다시 살펴보고 이전 판단을 복원해야 합니다. 대화가 길어질수록 현재 결정과 과거에 폐기된 선택을 구분하기도 어려워집니다.
그래서 중간 규모 이상의 작업은 spec.md, plan.md, tasks.md, verification.md에 목표·결정·작업 상태·검증 결과를 남기도록 했습니다. 작업 중인 기능은 미완료 task를 기준으로 이어서 진행하고, Feature Hub와 ROADMAP.md는 기능 간 상태를 보여 주는 진입점으로 사용했습니다.
Spec Kit을 도입한 이유도 문서를 많이 만들기 위해서가 아닙니다. 설계 단계에서는 사용자와 질의응답을 통해 방향을 확정하고, 실행 단계에서는 승인된 문서와 미완료 작업을 기준으로 진행하기 위해서였습니다.
규칙과 결정이 문서에 남아 있으면 새로운 에이전트나 세션이 코드베이스 전체를 반복해서 탐색하고 이전 판단을 다시 복원해야 하는 범위를 줄일 수 있다고 판단했습니다.
운영에서 발견한 마찰을 다시 규칙과 검증으로 돌려보내다
하네스의 규칙은 처음부터 완성된 것이 아닙니다. 실제 프로젝트와 대화 기록에서 반복되는 마찰을 확인하고, 재현 가능한 문제는 정책·hook·테스트·릴리스 게이트로 되돌려 보냈습니다.
예를 들어 사용 중인 도구가 실제 작업 흐름에서 얼마나 호출되는지 대화 기록을 기준으로 측정했습니다. 약 5주간의 초기 감사와 후속 재측정을 거쳐 GStack을 유지할 필요성을 다시 판단했고, 브라우저 검증은 Claude Code와 Codex 양쪽에서 사용할 수 있는 Playwright MCP로 대체했습니다.
코드 주석에 기능 번호나 문서 출처를 반복해서 적어 사람에게 필요한 설명보다 작업 이력이 더 많이 노출되는 문제도 있었습니다. 이를 계기로 주석은 사람에게 필요한 이유·제약·기술 부채를 설명하고, 작업 provenance는 spec과 Git 이력에 남기도록 규칙을 분리했습니다.
다운스트림에 전달해야 하는 변경이 CHANGELOG에서 반복적으로 누락된 문제는 주의 문구를 하나 더 추가하는 것으로 끝내지 않았습니다. 다운스트림에 영향을 주는 변경은 CHANGELOG와 릴리스 검증을 함께 통과하도록 게이트를 보강했습니다.
이런 과정을 통해 하네스는 규칙 파일을 배포하는 도구에서 실제 운영 편차를 다시 검증 가능한 계약으로 바꾸는 내부 제품으로 발전했습니다.
harness.lock: 공통 변경과 프로젝트 소유권을 분리하다
복사형 배포의 한계를 해결하기 위해 공유 본체와 프로젝트 소유 파일을 분리했습니다.
공통 정책, hook, shared skill과 검증 규칙은 하네스가 관리합니다. 앱 코드, 프로젝트 profile, local skill과 프로젝트 전용 규칙은 각 프로젝트가 소유합니다.
다운스트림 프로젝트는 harness.lock으로 사용할 버전을 선언하고, 머신의 버전 캐시에서 해당 버전을 받아 사용합니다. 진행 중인 세션의 버전은 바꾸지 않고 다음 세션 시작 시점에 반영하며, 필요하면 특정 버전으로 고정하거나 되돌릴 수 있도록 했습니다.
프로젝트가 작성한 파일을 공통 업데이트가 덮어쓰지 않도록 소유권 경계도 검증합니다. 하네스가 실제로 배포했던 파일만 오래된 공통 파일로 판단하고, 배포 이력이 없는 파일은 프로젝트 파일로 보고 보존합니다.
업데이트 로직과 검증 항목은 복사 방식보다 복잡해졌습니다. 그럼에도 공통 변경을 빠르게 전파한다는 이유로 진행 중인 프로젝트 설정이나 팀 규칙을 잃지 않는 것이 더 중요하다고 판단했습니다.
멀티 세션: 규칙 통일 다음에는 실행 환경 격리가 필요했다
단일 세션의 작업 흐름을 정리한 뒤에는 여러 세션이 같은 목표를 나누어 수행하는 방식을 실험했습니다.
이 테스트는 모든 하네스 프로젝트의 기본 기능이 아닙니다. PHP 그누보드 데이터베이스 마이그레이션 프로젝트에서 약 2주 동안 진행한 운영 확장 실험입니다.
planner는 사용자와 설계·우선순위·승인 경계를 정하고, worker는 독립된 작업을 구현하고 검증하며, shipper는 작업 결과와 남은 위험을 모으는 구조를 사용했습니다.
처음에는 worktree를 분리하면 충분할 것으로 봤지만 실제 실행에서는 브라우저 테스트 데이터, container, database schema와 port까지 격리해야 했습니다. 코드 경로가 다르더라도 실행 자원을 공유하면 한 worker의 상태가 다른 worker의 검증에 영향을 줄 수 있기 때문입니다.
세션 간 전달도 채팅만으로 처리하지 않았습니다. 목표, 결정, 테스트 명령과 결과, 남은 작업을 spec과 handoff 기록에 남기고 다음 세션이 필요한 상태만 읽어 이어서 진행하도록 했습니다.
아직 자동화하지 못한 부분도 있습니다. 언제 context를 compact하거나 clear할지 자동으로 판단하는 문제는 해결하지 못했습니다. 너무 이른 전환은 판단 근거를 잃게 하고, 너무 늦은 전환은 현재 작업과 관련 없는 기록을 계속 유지하게 만듭니다.
현재까지의 결론은 에이전트나 세션 수 자체보다 실행 자원의 격리, 명시적인 역할 경계와 durable handoff의 품질이 병렬 작업의 신뢰도를 결정한다는 것입니다.
적용 범위와 비용
2026-08-20 기준 하네스는 11개 프로젝트에 적용됐고, 그중 8개가 실제 운영 중이며 팀원 3명이 사용하고 있습니다. 하네스의 전체 구성과 설계·구현은 제가 혼자 담당했지만, 실제 사용 과정에서 팀원과 여러 프로젝트가 보여 준 편차를 다시 규칙과 검증에 반영했습니다.
저는 여러 사람이 함께 작업하는 프로젝트라면 처음부터 규칙 검증 구조를 두는 편이 좋다고 생각합니다. 어떤 에이전트를 사용하더라도 코드와 문서, 아키텍처, 커밋·PR·주석 규칙이 같은 방향으로 유지돼야 하기 때문입니다.
과거 여러 사람의 손을 거쳐 규칙이 일정하지 않았던 프로젝트에 AI 에이전트를 처음 적용했을 때, 기존 코드마다 다른 기준이 오히려 에이전트의 판단을 혼란스럽게 만든 경험도 있었습니다.
개인 프로젝트도 이후 팀원이 합류하거나 여러 세션이 이어서 작업할 가능성이 있다면 처음부터 최소한의 규칙과 검증 구조를 두는 편이 좋다고 생각합니다.
물론 비용도 있습니다. 파일 삭제와 위험 작업에 확인 절차가 생기고, PR 생성이 완전히 자동화되지 않으며, 작업 규모에 따라 문서가 늘어나고 사용자에게 판단을 묻는 지점도 많아집니다.
그래서 모든 작업에 같은 무게의 절차를 적용하지 않고 작업 크기와 위험도에 따라 필요한 단계와 검증 수준을 다르게 선택하도록 했습니다. 번거로움을 없애는 것이 목적이 아니라, 사용자의 판단이 필요한 지점과 자동으로 처리해도 되는 지점을 명확히 구분하는 것이 목적입니다.
회고
가장 중요한 교훈은 규칙이 문서에 존재하는 것보다 Claude Code와 Codex가 같은 행동을 하도록 검증되는 것이 중요하다는 점입니다.
재사용 역시 파일을 복사하는 것이 아니었습니다. 공통 변경을 프로젝트 소유권을 침범하지 않고 안전하게 전파하고, 문제가 생기면 특정 버전으로 돌아갈 수 있어야 실제 운영에서 재사용할 수 있었습니다.
마지막으로 내부 도구의 가치는 기능 수보다 팀이 같은 방식으로 반복할 수 있는 일을 얼마나 늘렸는가에 있다고 생각합니다.
Jenkins 제거는 시작점이었습니다. 하네스가 최종적으로 관리하게 된 것은 파일이나 명령 목록이 아니라, 사람과 AI 에이전트가 같은 기준으로 계획하고 구현하고 검증하는 반복 가능한 작업 방식이었습니다.