HARNESS ENGINEERING · PART 4 요약 · 花叔 (2026-04)

실전 — 빈 파일에서
완전한 하네스까지

개념은 끝났다. 이제 손을 움직인다. 첫 지시 파일의 생성부터 지시층·제약층·능력층·기억층을 거쳐 열 마리의 말을 동시에 달리게 하는 편성층까지 — 하네스를 실제로 쌓아 올리는 전 과정을 다룬다.

§13

공백에서 시작: 당신의 첫 하네스

From Scratch: Your First Harness

한 번에 완성하려 하지 마라. 빈 파일 하나, 실수하는 agent 하나, 새 규칙 한 줄. 3개월 뒤 돌아보면 그 파일이 곧 당신의 하네스다.

세 도구, 세 개의 출발점

어떤 AI 코딩 도구를 쓰든 하네스의 출발점은 같다 — 빈 지시 파일 하나. 차이는 파일명과 위치뿐이다.

Claude Code — CLAUDE.md

bash프로젝트 루트
touch CLAUDE.md

세션 기동 시 자동으로 읽는다. 추가 설정도 명령 등록도 필요 없다. 3층 상속을 지원한다 — ~/.claude/CLAUDE.md(전역, 모든 프로젝트) → 프로젝트 루트(프로젝트 레벨) → 하위 디렉터리(상층 덮어쓰기). 형식은 평범한 Markdown으로 특수 문법이 없다.

Codex CLI — AGENTS.md

bash프로젝트 루트
touch AGENTS.md

기동 시 프로젝트 루트에서 현재 작업 디렉터리까지 층별로 순회하며 각 층에서 AGENTS.override.md → AGENTS.md → fallback 파일명 순으로 확인한다. 병합 전략은 루트에서 리프로 이어 붙이되 가까운 쪽이 먼 쪽을 덮어쓴다. OpenAI는 약 100줄을 유지하며 백과사전이 아닌 지도로 삼아 docs/의 상세 문서를 가리키라고 권고한다.

Cursor — .cursor/rules/

bash초기 단일 파일 .cursorrules는 deprecated
mkdir -p .cursor/rules
touch .cursor/rules/project.mdc
mdcMarkdown + YAML frontmatter
---
description: 프로젝트 공통 규범
globs: "**/*"
alwaysApply: true
---
# 규칙은 여기에 쓴다

Cursor의 독자성은 glob scoping — 규칙을 특정 파일이나 디렉터리에만 발효시킬 수 있어 대형 프로젝트에서 실용적이다.

빈 파일에서 시작, 실수가 이끈다

파일은 만들었다. 무엇을 쓰는가? — 아무것도 쓰지 않는다. 게으름이 아니다.

Mitchell Hashimoto · Ghostty에서의 실천
agent가 실수하는 것을 발견할 때마다, 시간을 들여 같은 실수를 두 번 다시 저지르지 못하게 하는 해법을 엔지니어링한다.
그의 AGENTS.md는 모든 줄이 과거의 실수 하나에 대응한다. 파일은 살아 있고 계속 자란다. 3개월 뒤 그 파일은 당신 장면의 실제 문제만으로 채워진 고도 맞춤형 하네스가 된다.

구체적 시연 — React 프로젝트의 첫 10개 규칙

막 인수한 React 프로젝트를 가정한다. 빈 파일에서 시작해 처음 10개의 규칙이 어떻게 생기는지 본다.

RULE 01 · agent가 테스트를 잘못 돌렸다
테스트

agent가 npm test를 썼지만 프로젝트는 Vitest를 쓴다.

markdown
# 테스트
- 테스트 실행: `pnpm vitest run`
- 단일 파일: `pnpm vitest run src/path/to/test.ts`
RULE 02 · 잘못된 패키지 매니저
패키지 관리

npm으로 설치해 package-lock.json과 pnpm-lock.yaml이 충돌했다.

markdown
# 패키지 관리
- pnpm만 사용, npm과 yarn 금지
- 의존성 설치: `pnpm add`
RULE 03 · 프로젝트 구조를 모른다
프로젝트 구조 — 지도 한 장 추가

컴포넌트를 엉뚱한 디렉터리에 놓았다.

markdown
# 프로젝트 구조
- src/components/ — 공유 UI 컴포넌트
- src/features/   — 기능 모듈별 비즈니스 코드
- src/lib/        — 유틸과 서드파티 래핑
- src/api/        — API 요청 계층. 요청 로직을 컴포넌트에 쓰지 말 것
RULE 04 · TypeScript enum 사용
코드 스타일

팀 규범은 enum 대신 union type이다.

markdown
# 코드 스타일
- TypeScript enum 금지, literal union type 사용
  ❌ enum Status { Active, Inactive }
  ✅ type Status = 'active' | 'inactive'
RULE 05 · main에 직접 push
Git 규범
markdown
# Git 규범
- main 브랜치에 직접 push 절대 금지
- feature/ 브랜치 생성 후 PR로 병합
- commit message는 영문, 형식: type(scope): description
RULE 06 · 거대 컴포넌트 생성
아키텍처 원칙

컴포넌트 하나가 500줄, 가독성이 최악이었다.

markdown
# 아키텍처 원칙
- 단일 컴포넌트 파일 200줄 이하
- 150줄 초과 시 자식 컴포넌트 분리 검토
- 비즈니스 로직은 커스텀 hook으로 추출, 컴포넌트는 렌더링만
RULE 07 · 불필요한 의존성 도입
의존성 관리

단순 기능 하나를 위해 거대한 라이브러리를 설치했다.

markdown
# 의존성 관리
- 새 의존성 추가 전 기존 의존성으로 가능한지 확인
- 네이티브 API와 프로젝트 기존 라이브러리 우선
- date-fns 설치됨 — moment나 dayjs를 들이지 말 것
RULE 08 · lint 없이 커밋
커밋 전 검사
markdown
# 커밋 전 검사
- 커밋 전 필수 실행: `pnpm lint && pnpm type-check`
- lint 오류는 반드시 수정, eslint-disable 불허
RULE 09 · 조악한 에러 처리
에러 처리

빈 catch 블록과 console.log가 도처에 있었다.

markdown
# 에러 처리
- 빈 catch 블록 불허
- API 오류는 src/lib/error.ts의 AppError 클래스로 통일
- 사용자 노출 오류는 친화적 안내로, 기술 세부 노출 금지
RULE 10 · API 호출이 산재
API 계층
markdown
# API 계층
- 모든 API 요청은 src/api/ 하위 모듈에서 발신
- 프로젝트가 래핑한 apiClient 사용 (src/lib/api-client.ts)
- 컴포넌트에서 fetch 직접 호출 금지

10개의 규칙 중 허공에서 나온 것은 하나도 없다. 모든 규칙 뒤에 구체적인 문제가 있다 — 이것이 실수 주도 하네스다.

세 가지 기동 조언

조언 1 · 지도를 주되 설명서를 주지 마라

지시 파일은 지도여야 한다 — 프로젝트 구조, 파일 관계, 핵심 제약. 매 단계를 못 박지 마라. AI에게 필요한 것은 방향 감각이지 경직된 절차가 아니다. OpenAI의 실천이 이를 증명한다 — AGENTS.md 약 100줄은 목차와 포인터일 뿐이며 docs/의 상세 문서를 가리킨다.

조언 2 · 실수마다 규칙 한 줄

Mitchell Hashimoto의 핵심 방법이다. 빈 파일에서 시작해 agent가 실수 하나를 저지르면 한 줄을 더한다. 예단하지 말고 추측하지 마라. 3개월 뒤 그 파일이 당신의 하네스다 — 전부 당신 장면의 실제 문제이므로 고도로 맞춤화되어 있다.

조언 3 · AI로 AI를 검사하라

Anthropic의 Evaluator 발상이다. AI에게 자기 검사를 시키지 마라. 가장 간단한 방법 — 작성이 끝나면 새 대화를 열고 결과를 붙여 넣은 뒤 「모든 문제를 찾아내라」고 한다. 두 번째 AI가 첫 번째 AI의 누락을 얼마나 찾아내는지 놀랄 것이다.

3+1 도구 기동 조견표

차원Claude CodeCodex CLICursorGitHub Copilot
파일명CLAUDE.mdAGENTS.md.cursor/rules/*.mdccopilot-instructions.md
위치프로젝트 루트프로젝트 루트.cursor/rules/ 디렉터리.github/ 디렉터리
형식순수 Markdown순수 MarkdownMarkdown + YAML frontmatter순수 Markdown
계층전역 → 프로젝트 → 하위 디렉터리override → agents → team_guide전역 → 프로젝트 (glob 지원)전역 → 프로젝트
자동 로드매 세션기동 시 순회활성 조건별
하드 제약Hooks (deny)Sandbox없음없음
최신 동향v2.1.90 /powerup 교육데스크톱 App + GPT-5.3Background AgentsAgent Mode 출시
권장 시작 분량20–50줄50–100줄.mdc당 20–30줄20–50줄

지금 쓰는 도구를 고르고, 해당 빈 파일을 만들고, 일을 시작한다. agent가 실수하면 한 줄 더한다. 이것이 당신의 첫 하네스다.

§14

지시층: AI에게 지도 한 장을

The Instruction Layer: Give AI a Map, Not a Manual

CLAUDE.md, AGENTS.md, .cursor/rules/ — 본질은 같은 일이다. 그러나 어떻게 쓰는가에 따라 결과는 크게 다르다.

파일 하나에서 3층 아키텍처로

structureClaude Code 3층 상속 — 뒤에 로드될수록 우선
~/.claude/CLAUDE.md        → 전역 지시 (모든 프로젝트)
프로젝트루트/CLAUDE.md      → 프로젝트 레벨 지시
프로젝트하위디렉터리/CLAUDE.md → 하위 디렉터리 지시 (상층 덮어쓰기)

전역층에 범용 선호(pnpm 사용, commit message 영문 등), 프로젝트층에 프로젝트 고유의 아키텍처 제약, 하위 디렉터리층에 모듈 특정 규칙을 둔다. 공중계정 글을 쓸 때 iOS 개발 규칙의 간섭을 받지 않는다.

라우터 패턴

저자가 실전에서 길러 낸 패턴으로, 서로 다른 유형의 작업을 동시에 관리할 때 적합하다. 루트 CLAUDE.md는 라우팅만 한다.

markdown루트 CLAUDE.md — 200줄 이내 유지
# 워크스페이스 라우팅
과제 수신 후 워크스페이스를 먼저 판별하고 해당 CLAUDE.md를 읽는다:

| 키워드            | 워크스페이스   | 읽을 파일                     |
|-------------------|---------------|-------------------------------|
| 글쓰기, 공중계정   | 공중계정 글쓰기 | /01-공중계정 글쓰기/CLAUDE.md |
| 샤오홍슈, 노트     | 샤오홍슈 글쓰기 | /02-샤오홍슈 글쓰기/CLAUDE.md |
| 영상 스크립트      | 영상 제작      | /03-영상 제작/CLAUDE.md       |
| 코드, Demo        | 실험 프로젝트  | /09-실험 프로젝트/            |

과제가 모호함 → 확인 질문
복수 워크스페이스 관련 → 순차 로드
Boris Cherny · Claude Code 창시자
비대한 CLAUDE.md 파일은 Claude가 당신의 진짜 지시를 무시하게 만든다!
"Bloated CLAUDE.md files cause Claude to ignore your actual instructions!" — CLAUDE.md의 내용은 매 세션 컨텍스트에 로드된다. 지시 파일이 차지하는 공간이 클수록 실제 과제의 공간이 줄어든다. 라우터 패턴은 매번 관련 규칙만 로드되도록 보장한다.

AGENTS.md — 목차 포인터 모드

OpenAI Codex 팀은 유사하되 더 극단적인 길을 갔다. AGENTS.md는 약 100줄로 목차와 포인터 역할만 하고 docs/의 상세 문서를 가리킨다.

markdownAGENTS.md 예시
# 프로젝트 개요
[프로젝트명] — 기술 스택: React + FastAPI + PostgreSQL

# 핵심 명령
- 개발 서버: `pnpm dev`  ·  테스트: `pnpm test`  ·  타입 체크: `pnpm type-check`

# 아키텍처 가이드   → docs/ARCHITECTURE.md (~200줄, 코드베이스 지도)
# 설계 결정         → docs/design-docs/ (핵심 아키텍처 결정 기록)
# 활성 과제         → docs/exec-plans/ (현재 Sprint와 기술 부채)
# 제품 명세         → docs/product-specs/ (기능 명세, 내비게이션 색인)

# 의존 계층 (강제 집행)
Types → Config → Repo → Service → Runtime → UI
각 비즈니스 도메인 내 코드는 고정 방향으로만 의존. 위반 시 CI가 차단.

초대형 단일 파일을 시도했다가 나쁜 결과를 확인했다. agent는 작고 안정적인 진입점 + 전문 지식을 가리키는 구조에서 더 잘 동작한다.

Cursor Rules의 베스트 프랙티스

Cursor의 규칙 시스템에는 중요한 차별점이 있다 — glob scoping. 파일 경로별로 다른 규칙을 걸 수 있다.

mdc.cursor/rules/api-layer.mdc — API 코드를 편집할 때만 활성
---
description: API 계층 코딩 규범
globs: src/api/**/*.ts
alwaysApply: false
---
# API 계층 규범
- 모든 API 함수는 반환 타입 주석 필수
- 오류 처리는 프로젝트 통일 AppError 클래스 사용
- 요청 파라미터와 응답 타입은 동일 파일 상단에 정의
- API 계층에서 비즈니스 로직 판단 금지
활성 모드설명적합한 용도
alwaysApply: true매 세션 자동 로드공통 규범, 프로젝트 구조
glob 매칭파일이 컨텍스트에 있을 때 활성모듈 특정 규칙
수동 @mention사용자가 명시적으로 트리거가끔 필요한 특수 규칙
AI 판단description 기반 자동 결정상황 의존적 규범

수렴 — 지시 파일은 같은 것이 되어 가고 있다

CLAUDE.md, AGENTS.md, .cursorrules, .windsurfrules, copilot-instructions.md, GEMINI.md, .clinerules, CONVENTIONS.md — 이름은 달라도 본질은 하나다: Markdown 파일로 AI에게 프로젝트 규칙을 알린다. 추세는 이미 「발생」을 넘어 표준화 단계다. 2026년 3월 AGENTS.md가 Linux 재단 산하 Agentic AI Foundation 관리로 편입되었고, 배후에는 Sourcegraph·OpenAI·Google·Cursor·Factory가 있다. Windsurf는 2026년 초부터 AGENTS.md를 자동 인식해 같은 저장소의 규칙을 Windsurf와 Codex CLI가 함께 읽는다. GitHub Copilot의 .instructions.md도 점점 AGENTS.md를 닮아 가고, Google은 GEMINI.md를 내놓았다. 통일 표준은 「가능성」이 아니라 「시기」의 문제다. 다만 기다릴 필요는 없다 — 어떤 형식으로 쓰든 내용의 80%(프로젝트 구조, 코딩 규범, 테스트 명령, 아키텍처 제약)는 도구 간 공용이다.

차원Claude CodeCodex CLICursor
파일 형식순수 Markdown순수 MarkdownMDC (Markdown + YAML)
계층 수3 (전역/프로젝트/하위)4 (override/agents/team_guide/.agents)2 (전역/프로젝트)
Glob Scoping없음 (하위 디렉터리로 구현)없음있음 (frontmatter의 globs)
팀 공유git 커밋git 커밋git 커밋
임포트 문법@path/to/file없음없음
도구 간 호환아니오Windsurf 자동 호환아니오

지시 파일을 잘 쓰는 세 원칙

원칙 1 — 경직된 절차가 아니라 방향 감각

✕ 경직된 절차

컴포넌트 생성 시: 1) src/components/에 폴더 생성 2) index.tsx 생성 3) types.ts 생성 4) styles.module.css 생성 5) index.tsx에 styles 임포트 6) default export…

망라해 보이지만 완전히 일치하지 않는 상황을 만나면 agent가 갇힌다.

✓ 방향 감각

# 컴포넌트 규범
· 공유 컴포넌트는 src/components/
· 스타일은 Tailwind, CSS Modules 금지
· 단일 파일 <200줄, 넘으면 분리
· Props는 interface로 정의

agent에게 판단의 공간을 남기면서도 이탈을 막는다.

원칙 2 — 매뉴얼보다 가드레일 우선

「이렇게 해야 한다」보다 「이렇게 하면 안 된다」가 낫다. OpenAI의 아키텍처 불변량은 반직관적이지만 유효한 표현을 쓴다 — 여기에 무엇이 존재하지 않는가를 선언한다.

markdown
# 아키텍처 불변량
- 이 프로젝트는 ORM을 쓰지 않는다. 모든 DB 작업은 원시 SQL
- UI 계층은 DB에 직접 접근하지 않는다. 반드시 Service 계층 경유
- 전역 상태관리 라이브러리는 존재하지 않는다. React Context + hooks 사용
- 마이크로서비스 통신은 일절 없다. 이것은 모놀리식 애플리케이션이다

존재하지 않는 것을 알리는 편이 존재하는 것을 알리는 것보다 해공간을 더 잘 좁힌다. 선택지 배제가 열거보다 컨텍스트를 절약한다.

원칙 3 — 실수 → 기록 → 반복의 플라이휠

Boris Cherny의 CLAUDE.md는 약 100줄로 대다수 개발자의 500–1000줄보다 짧지만 효과는 더 좋다. agent가 실제로 저지른 실수만 기록하기 때문이다. 그는 이를 복리 엔지니어링(Compounding Engineering)이라 부른다 — 「Claude가 뭔가를 잘못하는 것을 볼 때마다 CLAUDE.md에 추가해 다음번 반복을 막는다.」 팀은 PR에서 @.claude 태그로 갱신하며, 축적되면 파일이 팀의 제도적 지식이 된다. 모든 줄에 스스로 묻는다 — 지우면 agent가 실수하는가? 아니라면 지운다. 지시 파일을 간결하게 유지하는 최고의 판단 기준이다.

써야 할 것 vs 쓰지 말아야 할 것

써야 할 것쓰지 말아야 할 것
agent가 추측 못 할 명령 (예: pnpm vitest run)agent가 코드를 읽으면 아는 것 (예: React 사용)
기본값과 다른 코드 스타일 규칙표준 언어 관례
테스트 지시와 선호 테스트 러너상세 API 문서 (링크면 충분)
브랜치 명명, PR 관례자주 바뀌는 정보
프로젝트 특유의 아키텍처 결정튜토리얼과 장문 해설
흔한 함정과 비자명한 동작「깨끗한 코드를 쓰라」류 자명한 원칙

좋은 지시 파일은 입사 첫날 시니어 동료가 건네는 비망록처럼 읽힌다 — 핵심 정보, 흔한 구덩이, 담당자. 교육 매뉴얼이 아니라 생존 가이드다.

§15

제약층: 권고와 제약은 별개다

The Constraint Layer: Suggestions vs. Enforcement

지시 파일에 「main에 push하지 마라」고 쓰는 것은 권고다. hooks로 프로그램 층에서 막는 것이 제약이다. 이 구별이 하네스가 art에서 engineering으로 넘어가는 전환점이다.

근본적인 구별

CLAUDE.md에 이렇게 썼다고 하자 — - main 브랜치에 직접 push 절대 금지. 이것은 권고다. Claude는 대체로 준수하지만 보장은 없다. 컨텍스트가 길어지거나 과제가 복잡해지거나 모델이 가끔 엇나가면 규칙이 무시될 수 있다. 이제 방식을 바꾼다.

jsonClaude Code hooks 설정
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash(git push*main*)",
        "handler": {
          "type": "shell",
          "command": "echo 'DENY: main 브랜치 직접 push 금지'"
        }
      }
    ]
  }
}

이것은 제약이다. Claude가 무슨 생각을 하든, 컨텍스트가 얼마나 혼란하든, main으로의 push 명령은 실행 전에 차단된다. 프로그램 레벨이고 확정적이며 우회 불가능하다.

Anthropic 공식 문서
CLAUDE.md의 지시는 권고적이지만, hooks는 확정적이며 동작의 발생을 보장한다.
"Unlike CLAUDE.md instructions which are advisory, hooks are deterministic and guarantee the action happens." — 권고와 제약은 완전히 별개의 일이다.

Claude Code의 Hooks 시스템

Hooks는 Claude Code의 결정적 무기다. 2026년 4월 기준(v2.1.90) 20여 종의 생명주기 이벤트를 지원하며 자주 쓰는 것은 일곱이다.

이벤트트리거 시점핵심 능력
PreToolUse도구 호출 전deny로 작업 차단 — 보안 정책의 핵심 집행점. defer 결정 지원(headless 세션 일시정지·재개)
PostToolUse도구 호출 후감사, 로깅, 자동 포매팅
SessionStart세션 기동 시동적 컨텍스트 로드, 환경 초기화
Stopagent 정지 시확정적 완료 검사
PermissionRequest권한 요청 시자동화 승인, Slack 등으로 라우팅
PermissionDenied자동 모드 거부 후거부된 작업 기록, 대안 트리거
PostCompact컨텍스트 압축 후압축 이벤트 대응

가장 핵심은 PreToolUse — deny 신호로 특정 작업을 프로그램 층에서 저지할 수 있는 것은 모든 AI 코딩 도구 가운데 유일하다.

실용적인 hooks 네 가지

EXAMPLE 01
파일 편집 후 자동 lint

Claude가 파일을 편집할 때마다 ESLint를 자동 실행한다. 불합격이면 Claude가 오류 출력을 보고 스스로 수정한다.

json.claude/settings.json
{ "hooks": { "PostToolUse": [ {
  "matcher": "Edit|Write",
  "handler": { "type": "shell",
    "command": "npx eslint --fix \"$CLAUDE_TOOL_ARG_file_path\" 2>&1 | true" }
} ] } }
EXAMPLE 02
핵심 설정 파일 수정 금지

프로덕션 환경 설정을 agent의 우발적 수정으로부터 보호한다.

json
{ "hooks": { "PreToolUse": [ {
  "matcher": "Edit(.env*)|Edit(*.production.*)",
  "handler": { "type": "shell",
    "command": "echo 'DENY: 프로덕션 설정 파일은 보호됨. 직접 수정 불허'" }
} ] } }
EXAMPLE 03
코드 생성 후 자동 타입 체크

TypeScript 파일 수정 즉시 타입 체크. Claude가 타입 오류를 보고 자율 수정하며 사용자가 일깨울 필요가 없다.

json
{ "hooks": { "PostToolUse": [ {
  "matcher": "Edit(*.ts)|Edit(*.tsx)",
  "handler": { "type": "shell",
    "command": "npx tsc --noEmit 2>&1 | head -20" }
} ] } }
EXAMPLE 04
커밋 전 테스트 필수 통과
json
{ "hooks": { "PreToolUse": [ {
  "matcher": "Bash(git commit*)",
  "handler": { "type": "shell",
    "command": "pnpm test --run 2>&1 || echo 'DENY: 테스트 미통과, 커밋 금지'" }
} ] } }

흥미로운 디테일 — Claude에게 hooks를 스스로 쓰게 할 수 있다. 「모든 파일 편집 후 eslint를 돌리는 hook을 써라」고 말하면 구성까지 해 준다. agent가 스스로에게 제약을 채운다.

OpenAI의 하드 제약 — 기계화된 강제 집행

Codex CLI에는 hooks가 없지만 OpenAI 팀은 다른 하드 제약 체계를 썼다. 핵심 철학 — 「코드의 어디가 나쁜지 말로 표현할 수 있다면, 다음 단계는 그것을 써 내리는 것이다.」 구체적으로 3층이다.

Codex의 Sandbox — 물리적 격리

모드파일 접근네트워크
workspace-write (기본)워크스페이스만 쓰기 가능차단
danger-full-access전체 디스크 쓰기 가능개방

.git/.codex/는 full-access 모드에서도 항상 보호된다. 가장 단순하고 거친 제약 — agent가 못 하는 일은 그냥 못 한다. 규칙으로 하지 말라고 말하는 것이 아니라 환경 층에서 할 수 없게 만든다.

제약 스펙트럼 — 부드러움에서 단단함으로

구두 알림 규칙 파일 Hooks Linter CI Sandbox
제약 유형성질집행자우회 가능도구 지원
대화 중 구두 알림즉시적, 일회성사용자모든 도구
CLAUDE.md / AGENTS.md 규칙지속적, 권고적모델 준수모든 도구
Hooks (PreToolUse deny)지속적, 강제적프로그램 실행아니오Claude Code
커스텀 Linter지속적, 강제적정적 분석아니오모든 도구 (자체 구축)
CI 차단지속적, 강제적CI 시스템아니오모든 도구 (자체 구축)
Sandbox 격리지속적, 물리적운영체제아니오Codex CLI

오른쪽으로 갈수록 제약이 단단하다. 단단할수록 신뢰할 수 있지만 유연성은 떨어진다. 좋은 하네스는 이 층들의 조합이다 — 전부 최강으로도, 전부 최약으로도 쓰지 않는다. 대부분의 규칙은 지시 파일이면 충분하고, 소수의 핵심 안전선만 hooks나 CI로 지킨다.

권고인가 제약인가 — 판단법

권고 (지시 파일)

CLAUDE.md에 쓴다: 「데이터베이스 마이그레이션 파일을 삭제하지 마라」

대체로 준수되지만 보장은 없다. 컨텍스트가 길고 과제가 복잡하면 무시될 수 있다. 코딩 규범·스타일 선호·아키텍처 지침에 적합.

제약 (Hooks / CI / Sandbox)

PreToolUse hook이 migrations/ 디렉터리 삭제 작업을 가로챈다.

100% 신뢰 가능, 컨텍스트의 영향을 받지 않는다. 보안 레드라인·프로덕션 보호·비가역 작업 차단에 적합.

규칙 하나가 권고여야 하는지 제약이어야 하는지의 판단 — 스스로 묻는다: agent가 이 규칙을 위반하면 후과는 무엇인가. 코드 스타일 불일치? 성가시지만 치명적이지 않다 — 권고. 프로덕션 DB 삭제? 재앙적 후과 — 반드시 제약. main 브랜치 push? revert 가능하지만 번거롭다 — 제약. 변수 이름? review 때 고치면 된다 — 권고. 제약이 지키는 것은 마지노선이지 취향이 아니다.

제약이 전환점이다

도구들을 조사하면 분명한 경계선이 보인다 — 프로그램 레벨의 하드 제약을 제공하는 것은 Claude Code와 Codex CLI뿐이다. Cursor·Windsurf·GitHub Copilot·Aider는 프롬프트 레벨 규칙만 있다. Claude Code의 hooks는 프로그래머블(임의 로직으로 approve/deny 결정), Codex CLI의 sandbox는 정책식(프리셋 레벨 선택, 커스텀 로직 불가), 나머지 도구의 규칙은 권고적(AI가 「따라야 하지만」 「어길 수도 있는」)이다. Cline은 제3의 길 — Plan/Act 이중 모드로 「사회적 제약」을 구현한다. Plan 모드는 분석만 하고 수정하지 않으며, Act 모드는 매 단계 인간 승인을 요구한다. 기술로 agent를 저지하는 것이 아니라 프로세스로 인간 확인을 보장하는 방식이다.

Birgitta Boeckeler · ThoughtWorks
agent의 신뢰도와 안정성을 높이는 데 필요한 것은 바로 해공간의 제한이다. 제약이 많을수록 오히려 신뢰할 수 있다.
인간 조직과 같은 이치다. 규칙 없는 팀은 자유가 아니라 혼란이다. 경계가 명확한 팀의 구성원이 오히려 경계 안에서 마음껏 일한다. 하네스는 AI의 힘을 제한하지 않는다. AI의 힘을 신뢰할 수 있게 만든다.
§16

능력층과 기억층

Capability and Memory

지시와 제약이 agent가 「어떤 규칙을 아는가」를 관장한다면, 능력층은 「무엇을 할 수 있는가」를, 기억층은 「무엇을 기억하는가」를 관장한다. 이 두 층이 agent의 천장을 결정한다.

능력 — 전부 집어넣는 것이 아니다

agent가 할 수 있는 일의 양은 연결된 도구의 수에 달렸지만, 도구는 많을수록 좋은 것이 아니다. 컨텍스트 윈도는 유한하고, 도구 설명 하나가 늘 때마다 실제 작업 공간이 줄어든다. Claude Code의 Skills 시스템이 이 모순을 푼다. .claude/skills/ 아래 .md 파일 하나가 능력 하나를 정의한다 — 무엇을 하는지, 언제 트리거되는지. 평소에는 컨텍스트를 점유하지 않다가 Claude가 현재 과제에 따라 로드 여부를 스스로 판단한다. .md 파일 하나로 새 능력을 정의한다. 코드도 SDK도 불필요 — 모든 AI 코딩 도구 중 문턱이 가장 낮은 확장 방식이다. 저자의 skills 디렉터리에는 수십 개가 있다 — 샤오홍슈 삽화, 페이슈 동기화, 영상 스크립트 교열, 정보 검색.

Skills 설계 원칙

각 skill은 한 가지 일만 하고, 설명은 동료에게 한마디로 건네는 부탁처럼 쓴다. 「글을 페이슈에 발행해 줘」가 「페이슈 API 문서 생성 절차를 실행」보다 낫다. AI는 설명을 보고 로드 여부를 판단하므로 설명이 모호하면 트리거되지 않는다.

MCP — 하나의 프로토콜로 모든 것을 연결

Skills가 로컬 능력이라면, agent가 외부 세계와 연결될 때의 답은 Model Context Protocol(MCP)이 현재 표준에 가장 가깝다. 하나의 프로토콜로 AI 코딩 도구를 데이터베이스·API·웹·GitHub·Jira·Slack에 연결한다. Claude Code·Cline·Windsurf가 네이티브 지원한다. MCP는 AI 코딩 도구의 USB 포트가 되어 가고 있다. Block(구 Square)의 오픈소스 Goose가 이 길을 가장 멀리 갔다 — MCP로 GitHub부터 Google Drive, Docker, Kubernetes까지 3,000+ 서비스에 연결된다. Stripe의 Minions도 MCP와 도구 확장에 깊이 의존해 주당 1,300+ PR을 자동 생성·병합한다. Codex CLI의 도구 정의는 상대적으로 제한적(코드 읽기쓰기와 명령 실행에 집중), Cursor는 @docs로 외부 문서를 컨텍스트로 참조, GitHub Copilot은 Extensions 생태, Aider는 가장 순수하게 확장 없이 코드 편집에만 집중한다.

도구 설계의 원칙 — ACI

Anthropic이 Building Effective Agents에서 제시한 저평가된 개념 — Agent-Computer Interface(ACI). 도구의 문서와 테스트에 들이는 공은 UI 설계에 들이는 공만큼 중요하다.

✓ 좋은 도구 설계
  • 이름이 AI에게 의도를 전달한다: search_knowledge_base
  • 모든 도구에 명확한 파라미터 설명과 예시
  • 도구는 한 가지 일을 하고 결과를 반환한다
  • 오류 메시지가 어디가 잘못됐는지 알려 준다
✕ 나쁜 도구 설계
  • 모호한 명명: process_data — 무슨 데이터를? 무엇으로?
  • 파라미터 설명 부재, AI가 추측에 의존
  • 도구 하나가 다섯 가지 일과 부작용 더미를 반환
  • 오류가 「실패」만 말하고 이유를 말하지 않음

LangChain의 LLMToolSelectorMiddleware는 빠른 LLM으로 현재 과제에 필요한 도구를 사전 선별해 모든 도구 설명을 컨텍스트에 밀어 넣지 않는다 — 도구가 많아지면 선택 자체도 공학화가 필요하다.

기억 — 다음 격전지

2026년 초 AI 코딩 도구들의 기억 능력 격차는 크다. 대부분이 아직 정적 파일 단계에 머물러 있다.

도구자동 기억수동 기억세션 간 지속
Claude Codeauto-memory (관찰 자동 저장)MEMORY.md + CLAUDE.md
WindsurfCascade Memories (자동 생성)Rules
ClineMemory Bank MCP (구성 필요).clinerules
Codex CLI없음AGENTS.md정적 파일
Cursor없음.cursor/rules/정적 파일
GitHub Copilot없음instructions.md정적 파일
Aider없음CONVENTIONS.md정적 파일

동적 기억을 가진 도구는 셋뿐이고 나머지는 전부 인간이 지시 파일을 손으로 관리한다. 기억 시스템의 세 층위 — AI가 스스로 기억할 것을 결정 / 도구 호출로 명시적 관리 / 인간이 파일을 수동 갱신 — 의 격차가 한눈에 보인다.

Claude Code의 Memory 시스템 — 세 메커니즘의 상보

Anthropic은 agent가 컨텍스트 윈도 밖에서 지식을 유지하게 하는 memory 도구 공개 베타도 발표했다. Claude가 Pokemon을 플레이하며 정확한 스텝 카운트를 유지하고, 컨텍스트 리셋 후 자기 노트를 읽어 수 시간 시퀀스를 이어 간 사례 — 장기 과제에서 이 능력은 결정적이다.

지식 베이스 관리

기억이 「agent가 무엇을 기억하는가」라면, 지식 베이스는 「agent가 전문 지식을 어디서 찾는가」다. 저자의 글쓰기 프로젝트를 예로 들면 주제별 분류다.

structure
_knowledge_base/
├── INDEX.md
├── 기술도구/
├── 업계인물/
├── 제품발표/
├── 보고서자료/
└── 방법론/

주제 하나를 조사할 때마다 성과를 해당 분류에 저장하고 출처 URL과 날짜를 첨부한다. agent가 글을 쓸 때 관련 파일을 자동 검색한다. 지식 베이스는 자료 더미가 아니라 agent가 언제든 찾아볼 수 있는 색인이다. OpenAI Codex 팀은 더 급진적이다 — ExecPlan이라는 자기완결적 설계 문서를 만들고, Google Docs의 기획을 저장소로, Slack의 결정을 markdown으로 이관했다. 저장소가 유일한 진실의 원천이어야 한다. agent가 볼 수 없는 것은 존재하지 않는 것과 같다.

컨텍스트 관리 — 많을수록 좋은 것이 아니다

기억과 지식 베이스는 모두 컨텍스트에 무언가를 밀어 넣는다. 그러나 윈도에는 물리적 한계가 있다. Anthropic이 발견한 컨텍스트 부패(context rot) — 토큰이 많을수록 모델의 정확한 정보 상기 능력이 떨어진다. 기술적 지원 폭과 무관하게 약 100만 토큰에서 뚜렷한 성능 천장이 있다. 더 기괴한 발견 — Sonnet 4.5는 자기 컨텍스트 윈도를 인식한 최초의 모델로, 한계 접근을 감지하면 조기에 마무리하려 들고 잔여 토큰 추정은 정밀하지만 틀렸다(컨텍스트 불안). 압축만으로 부족해 컨텍스트 리셋이 Sonnet 4.5 시대의 필수 수단이 되었고, Opus 4.5에서 이 행동이 저절로 소멸했다 — 모델의 진보가 하네스의 복잡성을 해소하고 있다.

전략메커니즘적합한 장면
Compaction초기 대화를 요약하고 축약된 히스토리 위에서 계속연속성이 중요한 장기 과제
Context Reset윈도를 완전히 비우고 구조화된 인계 상태로 새 세션 기동컨텍스트 불안이 심각할 때
새 세션과제 전환 시 새 대화를 연다무관한 과제 사이

Claude Code 공식 문서의 직관적 판단 기준 — Claude를 두 번 넘게 교정해도 여전히 틀리면, 비우고 다시 시작하는 편이 낫다. 실패한 방안으로 오염된 컨텍스트 위에서 계속 고치면 갈수록 비뚤어진다.

능력층·기억층 종합 대조

차원Claude CodeCodex CLICursorWindsurfGitHub Copilot
능력 확장Skills + MCP + Hooks데스크톱 App + GPT-5.3Background Agents + BugBotMCPAgent Mode + Extensions
무코드 확장Skills (순수 .md)없음없음없음없음
동적 기억auto-memory없음없음Cascade Memories없음
세션 간3중 상보정적 파일정적 파일워크스페이스 바인딩정적 파일
컨텍스트 관리/compact + /clear과제 중 조정 가능Composer 컨텍스트M-Query 검색Agent 모드 자체 관리

능력층의 추세는 MCP 표준화, 기억층은 아직 각자도생이다. 이 두 층은 향후 1년 내 빠르게 평준화될 것이다 — 기억 없는 agent는 정말 고통스럽기 때문이다.

§17

편성층: 열 마리의 말을 동시에 달리게

Orchestration: Running Ten Horses at Once

agent 하나가 못 푸는 문제를 agent 열이 반드시 푼다는 보장은 없다. 그러나 편성이 옳다면, 열 개의 agent는 하나의 agent가 영원히 못 하는 일을 해낸다. 언제 멀티 Agent를 쓰고 어떻게 쓰는가를 다룬다.

말 한 마리에서 말 떼로

앞의 모든 장은 단일 agent의 하네스였다. 그러나 실제 프로젝트의 많은 과제는 agent 하나로 감당이 안 된다. 똑똑하지 않아서가 아니다 — 컨텍스트 윈도가 물리적 한계다. 프런트엔드·백엔드·DB·테스트·문서를 하나의 agent가 동시에 다루면 컨텍스트가 차는 순간 성능이 절벽처럼 떨어진다(약 100만 토큰이 천장). 그래서 각자의 컨텍스트 윈도를 가진 복수의 agent가 필요하다. 문제는 — 누가 이들을 조율하는가.

Boris의 10–15 동시 세션 — 사람이 편성기가 된다

가장 소박한 편성 — 인간이 편성기 노릇을 한다. Boris Cherny(Claude Code 창시자)는 일상적으로 10–15개의 동시 세션을 유지한다. 터미널 5개(1–5번 번호, 셸 별칭 za·zb·zc로 전환), 브라우저 5–10개, 아침에 띄워 두고 나중에 확인하는 모바일 세션. 각 세션은 독립 git worktree 위에서 돌아 코드가 충돌하지 않는다. 일부 엔지니어는 코드를 쓰지 않고 로그와 조회 전용인 「분석」 worktree를 따로 둔다. 고급 아키텍처가 아니지만 Boris는 이것이 팀 내부의 the single biggest productivity unlock이라 말한다.

1. worktree 복수 생성
과제마다 독립 작업 디렉터리, 코드 완전 격리
2. worktree별 세션 기동
터미널 번호로 전환, 핵심 세션은 OS 알림
3. 과제 배분
세션마다 독립 모듈/기능 하나, 상호 불간섭
4. 인간 조율
세션 간 전환, 결과 리뷰, 충돌 해소, 코드 병합

장점은 완전한 통제. 단점은 계속 지켜봐야 하고 과제 간 의존 관계가 당신 머릿속에만 존재한다는 것.

Anthropic의 3-Agent 아키텍처 — 사람 없이 조율하려면

Planner
1–4문장 프롬프트 → 완전한 제품 명세. 제품 맥락과 고수준 설계에 집중, 세부 구현은 불관여 — 과도한 기술 지시는 하류 연쇄 오류를 낳는다
Generator
Sprint당 기능 하나. 매 Sprint 전 Evaluator와 Sprint Contract를 협상해 「완료」의 정의에 합의 — 사용자 스토리와 테스트 가능한 구현 사이의 간극을 잇는다
Evaluator
아키텍처의 영혼. Playwright MCP로 구동 중인 앱과 상호작용 — UI 기능·API 엔드포인트·DB 상태를 실제 QA처럼 테스트하고 설계 품질·독창성·공예 수준을 채점
핵심 통찰 — 다시 강조할 가치가 있다
엄격한 독립 평가자를 엔지니어링하는 것이, 생성자에게 자기비판을 가르치는 것보다 훨씬 쉽다. 역할 분리가 적대적 역학을 만들고, 회의적인 Evaluator의 비판적 피드백이 Generator의 돌파를 돕는다.
방안시간비용결과
단일 Agent (Solo)20분$9핵심 기능 사용 불가
3-Agent (Full Harness)6시간$200완전히 동작하는 애플리케이션

20배 이상 비싸지만 단일 Agent의 산출은 아예 쓸 수 없다 — 더 많은 돈으로 더 잘 만든 것이 아니라, 이 돈을 쓰지 않으면 아예 안 되는 것이다. 흥미로운 후일담 — 모델이 Sonnet 4.5에서 Opus 4.6으로 오르자 Sprint 메커니즘이 완전히 제거되었다. 모델이 장기 과제를 원생 처리하고 Evaluator는 전 과정 종료 후 1회 평가로 바뀌었다. 모델의 진보가 편성을 단순화하고 있다.

당신도 쓸 수 있다 — Planner/Generator/Evaluator의 서민판

Planner → Plan Mode
복잡한 과제는 Claude Code의 Plan Mode(Shift+Tab 두 번)로 상세 구현 계획부터. Boris의 팁 — 한 Claude가 계획을 쓰고, 두 번째 Claude를 「staff engineer」로 기동해 계획을 심사
Generator → Normal Mode
계획 확정 후 auto-accept 모드로 코드 작성. 일이 틀어지면 밀어붙이지 말고 Plan Mode로 돌아가 재계획
Evaluator → 새 세션
완성 후 완전히 새 대화를 열어 결과를 붙여 넣고 「모든 문제를 찾아내라」. 새 컨텍스트의 AI는 자기 코드에 대한 편견이 없다

3-Agent 아키텍처의 서민판이다. 복잡한 시스템을 세울 필요 없이 대화 창 세 개면 충분하다.

Agent Teams — Claude Code 내장 멀티 Agent

Claude Code의 Agent Teams는 agent 간 직접 통신을 지원하는 현재 유일한 방안이다. 한 세션이 team lead가 되어 과제를 배분하고 결과를 종합하며, teammate들은 lead를 거치지 않고 직접 통신할 수 있다. 각 agent는 독립 컨텍스트 윈도를 갖는다. Boris의 수동 모드 대비 강점은 자동 조율 — 큰 과제를 기술하면 lead가 스스로 쪼개고 배분하고 수거한다. 병렬 조사, 독립 모듈 개발, 경쟁 가설 디버깅에 적합하다.

Writer/Reviewer 병렬 패턴

멀티 Agent가 꼭 복잡한 아키텍처일 필요는 없다. 가장 실용적인 패턴은 아마 가장 단순한 것 — 하나는 쓰고, 하나는 심사한다. Anthropic 공식 권장 — 한 Claude가 코드를 쓰고, 다른 Claude가 완전히 새 컨텍스트로 심사한다. 자기 코드에 대한 편견을 회피한다. 이 패턴은 배치 처리로 확장된다.

bash파일별 독립 처리 — 실패가 다른 파일에 영향을 주지 않는다
for file in $(cat files.txt); do
  claude -p "Migrate $file from React to Vue. Return OK or FAIL." \
    --allowedTools "Edit,Bash(git commit *)"
done

병렬도는 동시에 몇 개의 프로세스를 돌릴 의향이 있는가에 달렸다.

Stripe의 Pipeline 편성

Slack 메시지
Minion 트리거
자동 코딩
자동화 테스트
PR — review 대기

엔지니어가 Slack에 메시지 한 통을 보내고 자리를 뜨면 돌아왔을 때 PR이 준비되어 있다. 주당 1,300+ PR, 전부 인간 수기 코드 제로. 핵심 인프라 — 각 Minion은 표준화된 AWS EC2 인스턴스(devbox) 위에서 돌며 Stripe 전체 코드 트리, 예열된 Bazel·타입 체크 캐시가 사전 설치되어 있다. warm pool에서 devbox 기동은 10초 미만. Stripe의 핵심 통찰 — Minions가 동작하는 첫째 이유는 AI 모델과 거의 무관하며, LLM 이전부터 인간 엔지니어를 위해 쌓은 다년의 인프라 덕분이다. 전면적 테스트 커버리지, 합성 end-to-end 테스트, 신속 롤백의 블루-그린 배포. 하네스는 인프라 위에 세워진다. 인프라가 나쁘면 하네스도 서지 않는다. 모든 AI 생성 PR은 여전히 인간 review를 거치되 자동화된 신뢰 신호에 크게 의존한다 — 인간은 여전히 loop 안에 있고, 위치만 바뀌었다.

언제 멀티 Agent를 쓰는가

멀티 Agent 편성은 매혹적이지만 대부분의 장면은 단일 Agent로 충분하다. Anthropic이 Building Effective Agents에서 준 판단 기준 — 단일 LLM 호출로 풀리는 일에 Agent를 쓰지 마라. Agent는 단계 수를 예측할 수 없고 고정 경로를 하드코딩할 수 없는 개방형 문제에 적합하다. 같은 논리를 한 층 올리면 — 단일 Agent로 풀리는 일에 멀티 Agent를 쓰지 마라.

장면권장 모드이유
버그 수정, 기능 추가단일 Agent컨텍스트가 충분하고 병렬 수요가 없다
모듈 하나 리팩터링단일 Agent + Plan Mode전역 시야가 필요하며 쪼개면 오히려 컨텍스트를 잃는다
독립 모듈 5개 동시 수정수동 멀티 세션 (Boris 모드)과제가 독립적이고 agent 간 통신이 불필요
코드 작성 + 코드 심사Writer/Reviewer 이중 세션자기 심사 편향 제거
복잡한 풀스택 앱을 제로부터Planner/Generator/Evaluator과제가 전후단을 가로지르며 계획과 검증이 필요
대규모 마이그레이션 / 배치 처리Pipeline 스크립트 편성고도로 반복적이고 병렬화 가능
주당 1000+ PR의 엔터프라이즈 규모Stripe Minions식 플랫폼전용 인프라가 필요
Part 4의 결론

편성의 복잡도는 과제의 복잡도에 걸맞아야 한다. 대화 창 세 개로 끝나는 일에 Agent Teams를 세울 필요가 없다. 가장 단순한 것에서 시작하고, 정말 필요해졌을 때 업그레이드한다.