에이전트 아키텍처: AI 기반 개발 하네스 구축
# 에이전트 아키텍처: AI 기반 개발 하네스 구축
요약: Claude Code은 파일 접근이 가능한 채팅 상자가 아닙니다. 22개의 라이프사이클 이벤트를 갖춘 프로그래밍 가능한 런타임이며, 각 이벤트는 모델이 건너뛸 수 없는 셸 스크립트로 연결할 수 있습니다. hooks를 dispatchers로, dispatchers를 skills로, skills를 agents로, agents를 workflows로 쌓아 올리면 제약 조건을 강제하고, 작업을 위임하며, 세션 간 메모리를 유지하고, 다중 에이전트 심의를 조율하는 자율 개발 harness가 완성됩니다. 이 가이드는 단일 hook부터 10개 에이전트 합의 시스템까지 해당 스택의 모든 계층을 다룹니다. 프레임워크는 필요 없습니다. 모두 bash와 JSON만으로 구현합니다.
Andrej Karpathy는 LLM 에이전트 주변에 자라나는 것을 claws라는 용어로 표현했습니다. 에이전트가 컨텍스트 윈도우 바깥 세계를 붙잡을 수 있게 해주는 hooks, 스크립트, 오케스트레이션을 의미합니다.1 대부분의 개발자는 AI 코딩 에이전트를 대화형 어시스턴트로 취급합니다. 프롬프트를 입력하고, 파일이 편집되는 것을 지켜보고, 다음으로 넘어갑니다. 이런 관점은 생산성을 본인이 직접 감독할 수 있는 범위로 제한합니다.
인프라 관점의 사고 모델은 다릅니다. AI 코딩 에이전트는 LLM 커널을 가진 프로그래밍 가능한 런타임입니다. 모델이 수행하는 모든 동작은 여러분이 제어하는 hooks를 통과합니다. 프롬프트가 아닌 정책을 정의하는 것입니다. 모델은 웹 서버가 nginx 규칙 안에서 작동하는 것과 같은 방식으로 여러분의 인프라 안에서 작동합니다. nginx 앞에 앉아서 요청을 직접 입력하지 않듯이, 설정하고 배포하고 모니터링하면 됩니다.
이 구분이 중요한 이유는 인프라가 복리로 효과를 발휘하기 때문입니다. bash 명령어에서 자격 증명을 차단하는 hook 하나가 모든 세션, 모든 에이전트, 모든 자율 실행을 보호합니다. 평가 기준을 인코딩한 skill은 여러분이 직접 호출하든 에이전트가 호출하든 일관되게 적용됩니다. 코드 보안을 검토하는 에이전트는 여러분이 지켜보든 아니든 동일한 검사를 수행합니다.2
핵심 요약
- Hooks는 실행을 보장하지만, 프롬프트는 보장하지 않습니다. 린팅, 포매팅, 보안 검사 등 모델 동작과 무관하게 매번 반드시 실행되어야 하는 작업에는 hooks를 사용하세요. 종료 코드 2는 동작을 차단합니다. 종료 코드 1은 경고만 표시합니다.3
- Skills는 자동 활성화되는 도메인 전문 지식을 인코딩합니다.
description필드가 모든 것을 결정합니다. Claude은 LLM 추론(키워드 매칭이 아닌)을 사용하여 skill 적용 여부를 판단합니다.4 - Subagents는 컨텍스트 비대화를 방지합니다. 탐색과 분석을 위한 격리된 컨텍스트 윈도우가 메인 세션을 가볍게 유지합니다. 최대 10개까지 병렬로 실행할 수 있습니다.5
- 메모리는 파일 시스템에 존재합니다. 파일은 컨텍스트 윈도우를 넘어 유지됩니다. CLAUDE.md, MEMORY.md, rules 디렉터리, 핸드오프 문서가 구조화된 외부 메모리 시스템을 구성합니다.6
- 다중 에이전트 심의는 사각지대를 발견합니다. 단일 에이전트는 자신의 가정에 의문을 제기할 수 없습니다. 서로 다른 평가 우선순위를 가진 두 개의 독립 에이전트가 quality gates로는 해결할 수 없는 구조적 결함을 포착합니다.7
- harness 패턴이 곧 시스템입니다. CLAUDE.md, hooks, skills, agents, 메모리는 독립된 기능이 아닙니다. 여러분과 모델 사이에 자동화와 함께 확장되는 결정론적 계층으로 구성됩니다.
이 가이드 활용법
| 경험 수준 | 여기서 시작 | 이후 탐색 |
|---|---|---|
| Claude Code을 매일 사용하며 더 활용하고 싶은 경우 | harness 패턴 | Skills 시스템, Hook 아키텍처 |
| 자율 워크플로우를 구축하는 경우 | Subagent 패턴 | 다중 에이전트 오케스트레이션, 프로덕션 패턴 |
| 에이전트 아키텍처를 평가하는 경우 | 에이전트 아키텍처가 중요한 이유 | 의사결정 프레임워크, 보안 고려사항 |
| 팀 harness를 설정하는 경우 | CLAUDE.md 설계 | Hook 아키텍처, 빠른 참조 카드 |
각 섹션은 이전 섹션을 기반으로 합니다. 마지막의 의사결정 프레임워크는 각 문제 유형에 적합한 메커니즘을 선택하기 위한 조회 테이블을 제공합니다.
에이전트 아키텍처가 중요한 이유
Simon Willison은 현재 상황을 하나의 관찰로 정리해요: 코드를 작성하는 비용이 이제 저렴해졌다는 것이죠.8 맞는 말이에요. 하지만 그 결과로 검증이 이제 가장 비용이 많이 드는 부분이 되었어요. 검증 인프라 없이 저렴하게 생산된 코드는 대규모로 버그를 만들어내요. 진짜 효과가 있는 투자는 더 나은 프롬프트가 아니에요. 모델이 놓치는 것을 잡아내는 시스템이에요.
에이전트 아키텍처가 필요한 세 가지 이유가 있어요:
컨텍스트 윈도우는 유한하고 손실이 발생해요. 파일 읽기, 도구 출력, 대화 턴마다 토큰을 소비해요. Microsoft Research와 Salesforce가 15개의 LLM를 200,000건 이상의 시뮬레이션 대화에서 테스트한 결과, 단일 턴에서 멀티 턴으로 전환할 때 평균 39%의 성능 저하가 발생했어요.9 이 저하는 단 두 턴만에 시작되며 예측 가능한 곡선을 따라요: 처음 30분 동안의 정밀한 멀티 파일 편집이 90분이 되면 단일 파일에만 집중하는 터널 비전으로 퇴화해요. 더 긴 컨텍스트 윈도우로는 이 문제가 해결되지 않아요. 같은 연구의 “Concat” 조건(전체 대화를 단일 프롬프트로 제공)에서는 동일한 내용으로 단일 턴 성능의 95.1%를 달성했어요. 성능 저하의 원인은 토큰 한계가 아니라 턴 경계에 있어요.
모델의 동작은 확률적이지, 결정론적이지 않아요. Claude에게 “파일 편집 후 항상 Prettier를 실행하라”고 지시하면 대략 80% 정도만 작동해요.3 모델이 잊어버리거나, 속도를 우선시하거나, 변경 사항이 “너무 작다”고 판단할 수 있어요. 컴플라이언스, 보안, 팀 표준에서 80%는 허용할 수 없는 수준이에요. Hooks는 실행을 보장해요: 모든 Edit 또는 Write가 포매터를 트리거하며, 매번, 예외 없이 실행돼요. 결정론적 방식이 확률적 방식을 이겨요.
단일 관점으로는 다차원적 문제를 놓칠 수 있어요. 하나의 에이전트가 API 엔드포인트를 검토하면서 인증을 확인하고, 입력 살균을 검증하고, CORS 헤더를 확인했어요. 이상 없음. 하지만 침투 테스터로 별도 프롬프트된 두 번째 에이전트가, 해당 엔드포인트가 무제한 쿼리 매개변수를 허용하여 데이터베이스 쿼리 증폭을 통한 서비스 거부 공격을 유발할 수 있다는 것을 발견했어요.7 첫 번째 에이전트는 쿼리 복잡도를 보안 공격 표면으로 다루는 항목이 평가 프레임워크에 없었기 때문에 확인하지 않았어요. 이 격차는 구조적이에요. 아무리 프롬프트 엔지니어링을 해도 해결할 수 없어요.
에이전트 아키텍처는 이 세 가지를 모두 해결해요: hooks가 결정론적 제약을 적용하고, subagents가 컨텍스트 격리를 관리하며, 멀티 에이전트 오케스트레이션이 독립적인 관점을 제공해요. 이들이 함께 harness를 구성해요.
Harness 패턴
harness는 프레임워크가 아니에요. 패턴이에요: AI 코딩 에이전트를 결정론적 인프라로 감싸는 조합 가능한 파일, 스크립트, 규칙의 집합이에요. 구성 요소는 다음과 같아요:
┌──────────────────────────────────────────────────────────────┐
│ THE HARNESS PATTERN │
├──────────────────────────────────────────────────────────────┤
│ ORCHESTRATION │
│ ┌────────────┐ ┌────────────┐ ┌────────────┐ │
│ │ Agent │ │ Agent │ │ Consensus │ │
│ │ Teams │ │ Spawning │ │ Validation│ │
│ └────────────┘ └────────────┘ └────────────┘ │
│ Multi-agent deliberation, parallel research, voting │
├──────────────────────────────────────────────────────────────┤
│ EXTENSION LAYER │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Skills │ │ Hooks │ │ Memory │ │ Agents │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
│ Domain expertise, deterministic gates, persistent state, │
│ specialized subagents │
├──────────────────────────────────────────────────────────────┤
│ INSTRUCTION LAYER │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ CLAUDE.md + .claude/rules/ + MEMORY.md │ │
│ └──────────────────────────────────────────────────────┘ │
│ Project context, operational policy, cross-session memory │
├──────────────────────────────────────────────────────────────┤
│ CORE LAYER │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Main Conversation Context (LLM) │ │
│ └──────────────────────────────────────────────────────┘ │
│ Your primary interaction; finite context; costs money │
└──────────────────────────────────────────────────────────────┘
Instruction Layer: CLAUDE.md 파일과 rules 디렉토리는 에이전트가 프로젝트에 대해 알아야 할 내용을 정의해요. 세션 시작 시와 모든 compaction 이후에 자동으로 로드돼요. 이것은 에이전트의 장기 아키텍처 메모리에요.
Extension Layer: Skills는 컨텍스트에 따라 자동 활성화되는 도메인 전문 지식을 제공해요. Hooks는 매칭되는 모든 도구 호출에서 실행되는 결정론적 게이트를 제공해요. Memory 파일은 세션 간 상태를 유지해요. 커스텀 agents는 특수화된 subagent 구성을 제공해요.
Orchestration Layer: 멀티 에이전트 패턴은 연구, 리뷰, 심의를 위해 독립적인 에이전트를 조율해요. Spawn 예산이 무한 재귀를 방지해요. 합의 검증이 품질을 보장해요.
핵심 인사이트: 대부분의 사용자는 Core Layer에서만 작업하면서 컨텍스트 비대화와 비용 증가를 지켜보고 있어요. 파워 유저는 Instruction과 Extension 레이어를 구성한 다음, Core Layer를 오케스트레이션과 최종 의사결정에만 사용해요.2
디스크에서 Harness의 구조
~/.claude/
├── CLAUDE.md # Personal global instructions
├── settings.json # User-level hooks and permissions
├── skills/ # Personal skills (44+)
│ ├── code-reviewer/SKILL.md
│ ├── security-auditor/SKILL.md
│ └── api-designer/SKILL.md
├── agents/ # Custom subagent definitions
│ ├── security-reviewer.md
│ └── code-explorer.md
├── rules/ # Categorized rule files
│ ├── security.md
│ ├── testing.md
│ └── git-workflow.md
├── hooks/ # Hook scripts
│ ├── validate-bash.sh
│ ├── auto-format.sh
│ └── recursion-guard.sh
├── configs/ # JSON configuration
│ ├── recursion-limits.json
│ └── deliberation-config.json
├── state/ # Runtime state
│ ├── recursion-depth.json
│ └── agent-lineage.json
├── handoffs/ # Session handoff documents
│ └── deliberation-prd-7.md
└── projects/ # Per-project memory
└── {project}/memory/MEMORY.md
.claude/ # Project-level (in repo)
├── CLAUDE.md # Project instructions
├── settings.json # Project hooks
├── skills/ # Team-shared skills
├── agents/ # Team-shared agents
└── rules/ # Project rules
이 구조의 모든 파일은 목적이 있어요. ~/.claude/ 트리는 모든 프로젝트에 적용되는 개인 인프라에요. 각 리포지토리의 .claude/ 트리는 프로젝트별이며 git을 통해 공유돼요. 이 둘이 합쳐져 완전한 harness를 구성해요.
Skills 시스템
Skills는 모델이 호출하는 확장 기능이에요. Claude가 컨텍스트에 따라 자동으로 발견하고 적용하며, 명시적으로 호출할 필요가 없어요.4 여러 세션에 걸쳐 같은 컨텍스트를 반복해서 설명하고 있다면, 바로 그때가 skill을 만들어야 할 시점이에요.
Skill을 만들어야 할 때
| 상황 | 만들어야 할 것 | 이유 |
|---|---|---|
| 매 세션마다 같은 체크리스트를 붙여넣고 있을 때 | Skill | 자동 활성화되는 도메인 전문 지식 |
| 같은 명령어 시퀀스를 명시적으로 실행할 때 | Slash command | 예측 가능한 트리거를 가진 사용자 호출 액션 |
| 컨텍스트를 오염시키지 않는 격리된 분석이 필요할 때 | Subagent | 집중 작업을 위한 별도의 컨텍스트 윈도우 |
| 특정 지시사항이 포함된 일회성 프롬프트가 필요할 때 | 아무것도 안 만들어도 돼요 | 그냥 입력하세요. 모든 것에 추상화가 필요한 건 아니에요. |
Skills는 Claude가 항상 사용할 수 있는 지식이에요. Slash commands는 명시적으로 트리거하는 액션이에요. 둘 사이에서 고민된다면 이렇게 물어보세요: “Claude가 자동으로 적용해야 할까, 아니면 내가 실행 시점을 결정해야 할까?”
Skill 만들기
Skills는 가장 넓은 범위에서 좁은 범위까지 네 곳에 위치할 수 있어요:4
| 범위 | 위치 | 적용 대상 |
|---|---|---|
| 엔터프라이즈 | Managed settings | 조직 내 모든 사용자 |
| 개인 | ~/.claude/skills/<name>/SKILL.md |
본인의 모든 프로젝트 |
| 프로젝트 | .claude/skills/<name>/SKILL.md |
해당 프로젝트만 |
| 플러그인 | <plugin>/skills/<name>/SKILL.md |
플러그인이 활성화된 곳 |
모든 skill에는 YAML frontmatter가 포함된 SKILL.md 파일이 필요해요:
---
name: code-reviewer
description: Review code for security vulnerabilities, performance issues,
and best practice violations. Use when examining code changes, reviewing
PRs, analyzing code quality, or when asked to review, audit, or check code.
allowed-tools: Read, Grep, Glob
---
# Code Review Expertise
## 보안 점검
코드를 리뷰할 때 다음 사항을 확인하세요:
### 입력 검증
- 모든 사용자 입력이 데이터베이스 작업 전에 적절히 정제되는지 확인
- 매개변수화된 쿼리 사용 (SQL에 문자열 보간 금지)
- 렌더링된 HTML 콘텐츠에 대한 출력 인코딩 적용
### 인증
- 모든 보호된 엔드포인트에서 세션 토큰 검증
- 데이터 변경 전 권한 확인
- 소스 코드에 하드코딩된 자격 증명이나 API 키가 없는지 확인
Frontmatter 참조
| 필드 | 필수 | 용도 |
|---|---|---|
name |
예 | 고유 식별자 (소문자, 하이픈, 최대 64자) |
description |
예 | 검색 트리거 (최대 1024자). Claude가 skill 적용 여부를 결정할 때 사용 |
allowed-tools |
아니요 | Claude의 기능 제한 (예: 읽기 전용으로 Read, Grep, Glob) |
disable-model-invocation |
아니요 | 자동 활성화 방지; /skill-name으로만 활성화 |
user-invocable |
아니요 | false로 설정하면 / 메뉴에서 완전히 숨김 |
model |
아니요 | skill 활성화 시 사용할 모델 재정의 |
context |
아니요 | fork로 설정하면 격리된 컨텍스트 창에서 실행 |
agent |
아니요 | 격리된 컨텍스트를 가진 subagent로 실행 |
hooks |
아니요 | 이 skill에만 적용되는 lifecycle hooks 정의 |
$ARGUMENTS |
아니요 | 문자열 치환: /skill-name 뒤에 입력한 사용자 내용으로 대체 |
Description 필드가 핵심이에요
세션 시작 시 Claude Code는 모든 skill의 name과 description을 추출하여 Claude의 컨텍스트에 주입해요. 메시지를 보내면 Claude가 언어 모델 추론을 통해 관련 skill이 있는지 판단합니다. Claude Code 소스 코드의 독립적인 분석에 따르면, skill 설명은 시스템 프롬프트의 available_skills 섹션에 주입되고 모델이 표준 언어 이해를 사용하여 관련 skill을 선택하는 것으로 확인되었습니다.10
나쁜 예:
description: Helps with code
효과적인 예:
description: Review code for security vulnerabilities, performance issues,
and best practice violations. Use when examining code changes, reviewing
PRs, analyzing code quality, or when asked to review, audit, or check code.
효과적인 설명에는 다음이 포함되어 있어요: 무엇을 하는지 (특정 이슈 유형에 대한 코드 리뷰), 언제 사용하는지 (변경 사항 검토, PR, 품질 분석), 그리고 사용자가 자연스럽게 입력하는 트리거 문구 (review, audit, check).
컨텍스트 예산
모든 skill 설명은 컨텍스트 창의 2%로 동적 확장되는 컨텍스트 예산을 공유하며, 폴백 값은 16,000자입니다.4 skill이 많다면 각 설명을 간결하게 유지하세요. SLASH_COMMAND_TOOL_CHAR_BUDGET 환경 변수로 예산을 재정의할 수 있지만,11 더 좋은 방법은 설명을 짧고 정확하게 작성하는 것이에요. 세션 중 /context를 실행하여 제외된 skill이 있는지 확인하세요.
지원 파일과 구성
skill은 같은 디렉토리의 추가 파일을 참조할 수 있어요:
~/.claude/skills/code-reviewer/
├── SKILL.md # Required: frontmatter + core expertise
├── SECURITY_PATTERNS.md # Referenced: detailed vulnerability patterns
└── PERFORMANCE_CHECKLIST.md # Referenced: optimization guidelines
SKILL.md에서 상대 링크로 참조하세요. Claude는 skill이 활성화될 때 필요에 따라 이 파일들을 읽습니다. SKILL.md는 500줄 이하로 유지하고 상세한 참조 자료는 지원 파일로 분리하세요.12
Git을 통한 skill 공유
프로젝트 skill (저장소 루트의 .claude/skills/)은 버전 관리를 통해 공유돼요:4
mkdir -p .claude/skills/domain-expert
# ... write SKILL.md ...
git add .claude/skills/
git commit -m "feat: add domain-expert skill for payment processing rules"
git push
팀원이 pull하면 자동으로 skill을 받게 됩니다. 설치도, 설정도 필요 없어요. 팀 전체에 전문 지식을 표준화하는 가장 효과적인 방법이에요.
프롬프트 라이브러리로서의 skill
단일 목적의 skill을 넘어, 디렉토리 구조가 정리된 프롬프트 라이브러리로 기능해요:
~/.claude/skills/
├── code-reviewer/ # Activates on: review, audit, check
├── api-designer/ # Activates on: design API, endpoint, schema
├── sql-analyst/ # Activates on: query, database, migration
├── deploy-checker/ # Activates on: deploy, release, production
└── incident-responder/ # Activates on: error, failure, outage, debug
각 skill은 전문 지식의 서로 다른 측면을 담고 있어요. 이들이 합쳐지면 Claude가 컨텍스트에 따라 자동으로 활용하는 지식 베이스가 됩니다. 주니어 개발자도 따로 요청하지 않아도 시니어 수준의 가이드를 받을 수 있어요.
skill과 hooks의 조합
skill은 frontmatter에 자체 hooks를 정의하여 해당 skill이 실행되는 동안에만 활성화할 수 있어요. 다른 세션을 오염시키지 않는 도메인별 동작을 만들 수 있습니다:2
---
name: deploy-checker
description: Verify deployment readiness. Use when preparing to deploy,
release, or push to production.
hooks:
PreToolUse:
- matcher: Bash
hooks:
- type: command
command: "bash -c 'INPUT=$(cat); CMD=$(echo \"$INPUT\" | jq -r \".tool_input.command\"); if echo \"$CMD\" | grep -qE \"deploy|release|publish\"; then echo \"DEPLOYMENT COMMAND DETECTED. Running pre-flight checks.\" >&2; fi'"
---
철학 skill은 SessionStart hooks를 통해 자동 활성화되어 명시적 호출 없이도 모든 세션에 품질 제약을 주입해요. skill 자체는 지식이고, hook은 실행 강제입니다. 함께하면 하나의 정책 계층을 형성합니다.
흔한 skill 실수
설명이 너무 광범위한 경우. git 관련 프롬프트(rebase, merge, cherry-pick, 심지어 git status까지)에 활성화되는 git-rebase-helper skill은 세션의 80%에서 컨텍스트를 오염시켜요. 해결 방법은 설명을 좁히거나 disable-model-invocation: true를 추가하고 명시적 /skill-name 호출을 요구하는 것입니다.4
예산을 놓고 경쟁하는 skill이 너무 많은 경우. skill이 많을수록 2% 컨텍스트 예산을 놓고 더 많은 설명이 경쟁해요. skill이 활성화되지 않는다면 /context에서 제외된 항목을 확인하세요. 모호한 skill 여러 개보다 잘 작성된 소수의 skill을 우선시하세요.
중요한 정보가 지원 파일에 묻힌 경우. Claude는 SKILL.md를 즉시 읽지만 지원 파일은 필요할 때만 접근해요. 중요한 정보가 지원 파일에 있으면 Claude가 찾지 못할 수 있습니다. 필수 정보는 SKILL.md에 직접 넣으세요.4
Hook 아키텍처
Hook은 Claude Code 라이프사이클 이벤트에 의해 트리거되는 셸 명령어예요.3 LLM 외부에서 일반 스크립트로 실행되며, 모델이 해석하는 프롬프트가 아니에요. 모델이 rm -rf /를 실행하려 한다고요? 10줄짜리 bash 스크립트가 명령어를 차단 목록과 대조해서 셸이 보기도 전에 거부해요. Hook은 모델의 의도와 관계없이 항상 실행돼요.
사용 가능한 이벤트
Claude Code는 6개 카테고리에 걸쳐 22개의 라이프사이클 이벤트를 제공해요:13
| 카테고리 | 이벤트 | 차단 가능? |
|---|---|---|
| 세션 | SessionStart, SessionEnd, Setup |
아니오 |
| 도구 | PreToolUse, PostToolUse, PostToolUseFailure |
Pre: 예 |
| 사용자 | UserPromptSubmit |
예 |
| 완료 | Stop, SubagentStop, TeammateIdle, TaskCompleted |
예 |
| 컨텍스트 | PreCompact, PostCompact, InstructionsLoaded |
아니오 |
| 설정 | ConfigChange, WorktreeCreate, WorktreeRemove, PermissionRequest, Notification, Elicitation, ElicitationResult, StopFailure |
다양함 |
종료 코드 의미
종료 코드에 따라 Hook이 작업을 차단할지 결정돼요:3
| 종료 코드 | 의미 | 동작 |
|---|---|---|
| 0 | 성공 | 작업이 진행돼요. stdout은 verbose 모드에서 표시돼요. |
| 2 | 차단 오류 | 작업이 중단돼요. stderr가 Claude에 전달되는 오류 메시지가 돼요. |
| 1, 3, 등 | 비차단 오류 | 작업이 계속돼요. stderr가 경고로 표시돼요. |
중요: 모든 보안 Hook은 exit 1이 아닌 exit 2를 사용해야 해요. Exit 1은 비차단 경고예요. 위험한 명령어가 그대로 실행돼요. 팀 전체에서 가장 흔한 Hook 실수예요.14
Hook 설정
Hook은 설정 파일에 위치해요. 공유 Hook은 프로젝트 레벨(.claude/settings.json)에, 개인 Hook은 사용자 레벨(~/.claude/settings.json)에 설정해요:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": ".claude/hooks/validate-bash.sh"
}
]
}
],
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "bash -c 'if [[ \"$FILE_PATH\" == *.py ]]; then black --quiet \"$FILE_PATH\" 2>/dev/null; fi'"
}
]
}
]
}
}
matcher 필드는 도구 이름에 매칭되는 정규식이에요: Bash, Write, Edit, Read, Glob, Grep, Agent, 또는 모든 도구에 대해 *를 사용해요. UserPromptSubmit처럼 도구가 없는 이벤트에는 "" (빈 문자열)을 사용하세요.
Hook 입출력 프로토콜
Hook은 stdin으로 전체 컨텍스트가 포함된 JSON를 받아요:
{
"tool_name": "Bash",
"tool_input": {
"command": "npm test",
"description": "Run test suite"
},
"session_id": "abc-123",
"agent_id": "main",
"agent_type": "main"
}
고급 제어를 위해 PreToolUse Hook은 JSON를 출력해서 도구 입력을 수정하거나, 컨텍스트를 주입하거나, 권한 결정을 내릴 수 있어요:
{
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "allow",
"permissionDecisionReason": "Command validated and modified",
"updatedInput": {
"command": "npm test -- --coverage --ci"
},
"additionalContext": "Note: This database has a 5-second query timeout."
}
}
세 가지 보장 유형
Hook을 작성하기 전에 먼저 물어보세요: 어떤 종류의 보장이 필요한가?14
포맷팅 보장은 사후에 일관성을 확보해요. Write/Edit에 대한 PostToolUse Hook이 파일 변경 후마다 포매터를 실행해요. 포매터가 모든 것을 정규화하기 때문에 모델의 출력은 중요하지 않아요.
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "bash -c 'if [[ \"$FILE_PATH\" == *.py ]]; then black --quiet \"$FILE_PATH\" 2>/dev/null; elif [[ \"$FILE_PATH\" == *.js ]] || [[ \"$FILE_PATH\" == *.ts ]]; then npx prettier --write \"$FILE_PATH\" 2>/dev/null; fi'"
}
]
}
]
}
}
안전 보장은 위험한 작업이 실행되기 전에 차단해요. Bash에 대한 PreToolUse Hook이 명령어를 검사하고 종료 코드 2로 파괴적인 패턴을 차단해요:
#!/bin/bash
# validate-bash.sh — block dangerous commands
INPUT=$(cat)
CMD=$(echo "$INPUT" | jq -r '.tool_input.command')
if echo "$CMD" | grep -qE "rm\s+-rf\s+/|git\s+push\s+(-f|--force)\s+(origin\s+)?main|git\s+reset\s+--hard|DROP\s+TABLE"; then
echo "BLOCKED: Dangerous command detected: $CMD" >&2
exit 2
fi
품질 보장은 결정 시점에서 상태를 검증해요. git commit 명령어에 대한 PreToolUse Hook이 린터나 테스트 스위트를 실행하고 품질 검사에 실패하면 커밋을 차단해요:
#!/bin/bash
# quality-gate.sh — lint before commit
INPUT=$(cat)
CMD=$(echo "$INPUT" | jq -r '.tool_input.command')
if echo "$CMD" | grep -qE "^git\s+commit"; then
if ! LINT_OUTPUT=$(ruff check . --select E,F,W 2>&1); then
echo "LINT FAILED -- fix before committing:" >&2
echo "$LINT_OUTPUT" >&2
exit 2
fi
fi
셸 명령어 외의 Hook 유형
Claude Code는 세 가지 Hook 유형을 지원해요:13
Command Hook (type: "command")은 셸 스크립트를 실행해요. 빠르고 결정적이며 토큰 비용이 없어요.
Prompt Hook (type: "prompt")은 빠른 Claude 모델에 단일 턴 프롬프트를 보내요. 모델이 { "ok": true }를 반환하면 허용하고, { "ok": false, "reason": "..." }를 반환하면 차단해요. 정규식으로 표현할 수 없는 세밀한 평가에 사용하세요.
Agent Hook (type: "agent")은 도구 접근 권한(Read, Grep, Glob)이 있는 subagent를 생성해서 다중 턴 검증을 수행해요. 실제 파일이나 테스트 출력을 검사해야 할 때 사용하세요:
{
"hooks": {
"Stop": [
{
"hooks": [
{
"type": "agent",
"prompt": "Verify all unit tests pass. Run the test suite and check results. $ARGUMENTS",
"timeout": 120
}
]
}
]
}
}
비동기 Hook
Hook은 실행을 차단하지 않고 백그라운드에서 실행할 수 있어요. 알림이나 로깅 같은 중요하지 않은 작업에는 async: true를 추가하세요:13
{
"type": "command",
"command": ".claude/hooks/notify-slack.sh",
"async": true
}
비동기는 알림, 텔레메트리, 백업에 사용하세요. 포맷팅, 검증, 또는 다음 작업 전에 반드시 완료되어야 하는 작업에는 절대 비동기를 사용하지 마세요.
독립적인 Hook 대신 dispatcher 사용
같은 이벤트에 7개의 Hook이 각각 독립적으로 stdin을 읽으면 경쟁 조건이 발생해요. 두 개의 Hook이 동시에 같은 JSON 상태 파일에 쓰면 JSON가 잘려요. 그 파일을 파싱하는 모든 후속 Hook이 깨져요.2
해결책: 이벤트당 하나의 dispatcher가 캐시된 stdin에서 Hook을 순차적으로 실행하는 거예요:
#!/bin/bash
# dispatcher.sh — run hooks sequentially with cached stdin
INPUT=$(cat)
HOOK_DIR="$HOME/.claude/hooks/pre-tool-use.d"
for hook in "$HOOK_DIR"/*.sh; do
[ -x "$hook" ] || continue
echo "$INPUT" | "$hook"
EXIT_CODE=$?
if [ "$EXIT_CODE" -eq 2 ]; then
exit 2 # Propagate block
fi
done
Hook 디버깅
조용히 실패하는 Hook을 디버깅하는 다섯 가지 기법:14
- 스크립트를 독립적으로 테스트하세요. 샘플 JSON를 파이프로 전달해요:
echo '{"tool_input":{"command":"git commit -m test"}}' | bash your-hook.sh - 디버그 출력에 stderr를 사용하세요. stderr에 쓴 내용은 Claude의 컨텍스트에 표시돼요.
- jq 실패에 주의하세요. 잘못된 JSON 경로는 조용히
null을 반환해요. 실제 도구 입력에 대해jq표현식을 테스트하세요. - 종료 코드를 확인하세요.
exit 1을 사용하는 PreToolUse Hook은 작동하는 것처럼 보이면서 실제로는 아무것도 강제하지 않아요. - Hook을 빠르게 유지하세요. Hook은 동기적으로 실행돼요. 모든 Hook을 2초 이내로, 이상적으로는 500ms 이내로 유지하세요.
메모리와 컨텍스트
모든 AI 대화는 유한한 컨텍스트 윈도우 안에서 이루어져요. 대화가 길어지면 시스템은 새로운 내용을 위해 이전 턴을 압축하는데, 이 압축은 손실이 발생해요. 3번째 턴에서 기록한 아키텍처 결정이 15번째 턴까지 살아남지 못할 수도 있어요.9
다중 턴 붕괴의 세 가지 메커니즘
MSR/Salesforce 연구에서는 각각 다른 대응이 필요한 세 가지 독립적인 메커니즘을 확인했어요:9
| 메커니즘 | 발생하는 현상 | 대응 방법 |
|---|---|---|
| 컨텍스트 압축 | 새로운 내용을 수용하기 위해 이전 정보가 버려짐 | 파일시스템에 상태 체크포인팅 |
| 추론 일관성 상실 | 모델이 여러 턴에 걸쳐 자신의 이전 결정과 모순됨 | 새로운 컨텍스트로 반복(Ralph 루프) |
| 조율 실패 | 여러 에이전트가 서로 다른 상태 스냅샷을 보유함 | 에이전트 간 공유 상태 프로토콜 |
전략 1: 파일시스템을 메모리로 활용
컨텍스트 경계를 넘어 가장 안정적으로 유지되는 메모리는 파일시스템에 있어요. Claude Code는 모든 세션 시작 시와 압축 후에 CLAUDE.md와 메모리 파일을 읽어요.6
~/.claude/
├── configs/ # 14 JSON configs (thresholds, rules, budgets)
│ ├── deliberation-config.json
│ ├── recursion-limits.json
│ └── consensus-profiles.json
├── hooks/ # 95 lifecycle event handlers
├── skills/ # 44 reusable knowledge modules
├── state/ # Runtime state (recursion depth, agent lineage)
├── handoffs/ # 49 multi-session context documents
├── docs/ # 40+ system documentation files
└── projects/ # Per-project memory directories
└── {project}/memory/
└── MEMORY.md # Always loaded into context
MEMORY.md 파일은 세션 간의 오류, 결정, 패턴을 기록해요. bash에서 VAR이 0일 때 ((VAR++))가 set -e와 함께 실패한다는 사실을 발견하면 이를 기록해 둬요. 세 번의 세션이 지난 후 Python에서 비슷한 정수 엣지 케이스를 만났을 때, MEMORY.md 항목이 해당 패턴을 떠올려 줘요.15
자동 메모리 (v2.1.32+): Claude Code는 프로젝트 컨텍스트를 자동으로 기록하고 불러와요. 작업하는 동안 Claude가 관찰 내용을 ~/.claude/projects/{project-path}/memory/MEMORY.md에 기록해요. 자동 메모리는 세션 시작 시 처음 200줄을 시스템 프롬프트에 로드해요. 간결하게 유지하고, 상세한 내용은 별도의 주제별 파일에 링크하세요.6
전략 2: 선제적 압축
Claude Code의 /compact 명령은 대화를 요약하고 핵심 결정, 파일 내용, 작업 상태를 보존하면서 컨텍스트 공간을 확보해요.15
압축이 필요한 시점: - 개별 하위 작업을 완료한 후 (기능 구현, 버그 수정) - 코드베이스의 새로운 영역을 시작하기 전 - Claude가 이전 컨텍스트를 반복하거나 잊기 시작할 때 - 집중적인 세션 중 대략 25-30분마다
CLAUDE.md에서의 커스텀 압축 지시사항:
# Summary Instructions
When using compact, focus on:
- Recent code changes
- Test results
- Architecture decisions made this session
전략 3: 세션 핸드오프
여러 세션에 걸치는 작업에는 전체 상태를 담은 핸드오프 문서를 작성하세요:
## Handoff: Deliberation Infrastructure PRD-7
**Status:** Hook wiring complete, 81 Python unit tests passing
**Files changed:** hooks/post-deliberation.sh, hooks/deliberation-pride-check.sh
**Decision:** Placed post-deliberation in PostToolUse:Task, pride-check in Stop
**Blocked:** Spawn budget model needs inheritance instead of depth increment
**Next:** PRD-8 integration tests in tests/test_deliberation_lib.py
Status/Files/Decision/Blocked/Next 구조는 후속 세션에 최소한의 토큰 비용으로 전체 컨텍스트를 제공해요. claude -c(계속하기)로 새 세션을 시작하거나 핸드오프 문서를 읽으면 바로 구현에 들어갈 수 있어요.15
전략 4: 새로운 컨텍스트 반복 (Ralph 루프)
60-90분을 초과하는 세션에서는 반복마다 새로운 Claude 인스턴스를 생성하세요. 상태는 대화 메모리가 아닌 파일시스템을 통해 유지돼요. 각 반복은 전체 컨텍스트 예산을 사용할 수 있어요:16
Iteration 1: [200K tokens] -> writes code, creates files, updates state
Iteration 2: [200K tokens] -> reads state from disk, continues
Iteration 3: [200K tokens] -> reads updated state, continues
...
Iteration N: [200K tokens] -> reads final state, verifies criteria
단일 장시간 세션과 비교해 보세요:
Minute 0: [200K tokens available] -> productive
Minute 30: [150K tokens available] -> somewhat productive
Minute 60: [100K tokens available] -> degraded
Minute 90: [50K tokens available] -> significantly degraded
Minute 120: [compressed, lossy] -> errors accumulate
새로운 컨텍스트 반복 방식은 오리엔트 단계(상태 파일 읽기, git 히스토리 스캔)에 15-20%의 오버헤드가 들지만, 반복마다 전체 인지 자원을 활용할 수 있어요.16 비용 대비 효과 계산은 이래요: 60분 미만의 세션에서는 단일 대화가 더 효율적이에요. 90분을 넘으면 오버헤드에도 불구하고 새로운 컨텍스트 방식이 더 높은 품질의 결과물을 만들어 내요.
안티패턴
10줄만 필요한데 파일 전체를 읽는 경우. 2,000줄짜리 파일 하나를 읽으면 15,000-20,000 토큰이 소비돼요. 줄 오프셋을 활용하세요: Read file.py offset=100 limit=20으로 대부분의 비용을 절약할 수 있어요.15
장황한 오류 출력을 컨텍스트에 유지하는 경우. 버그를 디버깅한 후, 컨텍스트에는 실패한 반복에서 나온 40개 이상의 스택 트레이스가 남아 있어요. 버그 수정 후 /compact 한 번이면 이 불필요한 부담을 해소할 수 있어요.
매 세션마다 모든 파일을 읽으며 시작하는 경우. Claude Code의 glob과 grep 도구가 필요할 때 관련 파일을 찾도록 맡기면, 불필요한 사전 로딩으로 인한 100,000개 이상의 토큰을 절약할 수 있어요.15
Subagent 패턴
Subagent는 복잡한 작업을 독립적으로 처리하는 특수한 Claude 인스턴스예요. 깨끗한 컨텍스트로 시작하며(메인 대화의 오염 없이), 지정된 도구로 작동하고, 결과를 요약 형태로 반환해요. 탐색 결과가 메인 대화를 비대하게 만들지 않고, 결론만 돌아와요.5
기본 제공 Subagent 유형
| 유형 | 모델 | 모드 | 도구 | 용도 |
|---|---|---|---|---|
| Explore | Haiku (빠름) | 읽기 전용 | Glob, Grep, Read, 안전한 bash | 코드베이스 탐색, 파일 찾기 |
| 범용 | 상속 | 전체 읽기/쓰기 | 모든 도구 사용 가능 | 복잡한 조사 + 수정 |
| Plan | 상속 (또는 Opus) | 읽기 전용 | Read, Glob, Grep, Bash | 실행 전 계획 수립 |
커스텀 Subagent 만들기
.claude/agents/ (프로젝트) 또는 ~/.claude/agents/ (개인)에 subagent를 정의하세요:
---
name: security-reviewer
description: Expert security code reviewer. Use PROACTIVELY after any code
changes to authentication, authorization, or data handling.
tools: Read, Grep, Glob, Bash
model: opus
permissionMode: plan
---
You are a senior security engineer reviewing code for vulnerabilities.
When invoked:
1. Identify the files that were recently changed
2. Analyze for OWASP Top 10 vulnerabilities
3. Check for secrets, hardcoded credentials, SQL injection
4. Report findings with severity levels and remediation steps
Focus on actionable security findings, not style issues.
Subagent 설정 필드
| 필드 | 필수 | 용도 |
|---|---|---|
name |
예 | 고유 식별자 (소문자 + 하이픈) |
description |
예 | 호출 시점 (자동 위임을 유도하려면 “PROACTIVELY” 포함) |
tools |
아니요 | 쉼표로 구분. 생략하면 모든 도구를 상속. Agent(agent_type)으로 생성 가능한 에이전트를 제한 가능 |
disallowedTools |
아니요 | 거부할 도구, 상속되거나 지정된 목록에서 제거됨 |
model |
아니요 | sonnet, opus, haiku, inherit (기본값: inherit) |
permissionMode |
아니요 | default, acceptEdits, delegate, dontAsk, bypassPermissions, plan |
maxTurns |
아니요 | subagent가 중단되기 전 최대 에이전트 턴 수 |
memory |
아니요 | 영구 메모리 범위: user, project, local |
skills |
아니요 | 시작 시 subagent 컨텍스트에 자동으로 skills 콘텐츠 로드 |
hooks |
아니요 | 이 subagent 실행에 한정된 라이프사이클 hooks |
background |
아니요 | 항상 백그라운드 작업으로 실행 |
isolation |
아니요 | 격리된 git worktree 복사본을 위해 worktree로 설정 |
Worktree 격리
Subagent는 임시 git worktree에서 작동할 수 있어, 리포지토리의 완전히 격리된 복사본을 제공해요:5
---
name: experimental-refactor
description: Attempt risky refactoring in isolation
isolation: worktree
tools: Read, Write, Edit, Bash, Grep, Glob
---
You have an isolated copy of the repository. Make changes freely.
If the refactoring succeeds, the changes can be merged back.
If it fails, the worktree is discarded with no impact on the main branch.
Worktree 격리는 코드베이스를 손상시킬 수 있는 실험적 작업에 필수적이에요.
병렬 Subagent
Claude Code는 최대 10개의 병렬 subagent를 지원해요.5 독립적인 조사 작업에는 병렬 실행을 활용하세요:
> Have three explore agents search in parallel:
> 1. Authentication code
> 2. Database models
> 3. API routes
각 에이전트는 자체 컨텍스트 윈도우에서 실행되고, 관련 코드를 찾아 요약을 반환해요. 메인 컨텍스트는 깔끔하게 유지돼요.
재귀 가드
생성 제한이 없으면, 에이전트가 에이전트에게 위임하고 그 에이전트가 또 다른 에이전트에게 위임하면서, 각각 컨텍스트를 잃고 토큰을 소모해요. 재귀 가드 패턴은 예산을 강제해요:16
#!/bin/bash
# recursion-guard.sh — enforce spawn budget
CONFIG_FILE="${HOME}/.claude/configs/recursion-limits.json"
STATE_FILE="${HOME}/.claude/state/recursion-depth.json"
MAX_DEPTH=2
MAX_CHILDREN=5
DELIB_SPAWN_BUDGET=2
DELIB_MAX_AGENTS=12
# Read current depth
current_depth=$(jq -r '.depth // 0' "$STATE_FILE" 2>/dev/null)
if [[ "$current_depth" -ge "$MAX_DEPTH" ]]; then
echo "BLOCKED: Maximum recursion depth ($MAX_DEPTH) reached" >&2
exit 2
fi
# Increment depth using safe arithmetic (not ((VAR++)) with set -e)
new_depth=$((current_depth + 1))
jq --argjson d "$new_depth" '.depth = $d' "$STATE_FILE" > "${STATE_FILE}.tmp"
mv "${STATE_FILE}.tmp" "$STATE_FILE"
핵심 교훈: 깊이 제한만이 아닌 생성 예산을 사용하세요. 깊이 기반 제한은 부모-자식 체인을 추적하지만(깊이 3에서 차단), 너비를 놓쳐요: 깊이 1에 23개의 에이전트가 있어도 여전히 “깊이 1”이에요. 생성 예산은 부모당 총 활성 자식 수를 추적하며, 설정 가능한 최대값으로 제한해요. 예산 모델은 대리 지표(너무 많은 중첩 레벨)가 아닌 실제 실패 모드(너무 많은 총 에이전트)에 매핑돼요.7
Agent Teams (리서치 프리뷰)
Agent Teams는 여러 Claude Code 인스턴스를 조율하여 독립적으로 작업하고, 공유 메일박스와 작업 목록을 통해 소통하며, 서로의 발견 사항에 이의를 제기할 수 있어요:5
| 구성 요소 | 역할 |
|---|---|
| Team lead | 팀을 생성하고, 팀원을 생성하며, 작업을 조율하는 메인 세션 |
| Teammates | 할당된 작업을 수행하는 별도의 Claude Code 인스턴스 |
| Task list | 팀원이 선점하고 완료하는 공유 작업 항목 (파일 잠금) |
| Mailbox | 에이전트 간 통신을 위한 메시징 시스템 |
활성화 방법: export CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1
Agent teams와 subagent를 언제 사용해야 하는지:
| Subagent | Agent Teams | |
|---|---|---|
| 통신 | 결과만 보고 | 팀원끼리 직접 메시지 교환 |
| 조율 | 메인 에이전트가 모든 작업 관리 | 공유 작업 목록으로 자율 조율 |
| 적합한 경우 | 결과만 중요한 집중 작업 | 토론과 협업이 필요한 복잡한 작업 |
| 토큰 비용 | 낮음 | 높음 (각 팀원 = 별도의 컨텍스트 윈도우) |
멀티 에이전트 오케스트레이션
단일 에이전트 AI 시스템에는 구조적 맹점이 있어요: 자신의 가정에 스스로 도전할 수 없다는 점이에요.7 멀티 에이전트 심의는 어떤 결정이 확정되기 전에 여러 관점에서 독립적인 평가를 강제해요.
최소 기능 심의(Minimum Viable Deliberation)
에이전트 2개와 규칙 1개로 시작하세요: 에이전트들은 서로의 작업을 보기 전에 독립적으로 평가해야 해요.7
Decision arrives
|
v
Confidence check: is this risky, ambiguous, or irreversible?
|
+-- NO -> Single agent decides (normal flow)
|
+-- YES -> Spawn 2 agents with different system prompts
Agent A: "Argue FOR this approach"
Agent B: "Argue AGAINST this approach"
|
v
Compare findings
|
+-- Agreement with different reasoning -> Proceed
+-- Genuine disagreement -> Investigate the conflict
+-- Agreement with same reasoning -> Suspect herding
이 패턴으로 전체 가치의 80%를 커버할 수 있어요. 나머지는 점진적인 개선을 더할 뿐이에요.
신뢰도 트리거(Confidence Trigger)
모든 작업에 심의가 필요한 건 아니에요. 신뢰도 평가 모듈은 네 가지 차원을 평가해요:17
- 모호성 - 쿼리에 여러 유효한 해석이 있는가?
- 도메인 복잡도 - 전문 지식이 필요한가?
- 리스크 - 결정을 되돌릴 수 있는가?
- 컨텍스트 의존성 - 더 넓은 시스템에 대한 이해가 필요한가?
점수는 세 단계로 매핑돼요:
| 레벨 | 임계값 | 조치 |
|---|---|---|
| HIGH | 0.85+ | 심의 없이 진행 |
| MEDIUM | 0.70-0.84 | 신뢰도 메모를 로깅하고 진행 |
| LOW | 0.70 미만 | 전체 멀티 에이전트 심의 트리거 |
임계값은 작업 유형에 따라 조정돼요. 보안 관련 결정은 0.85 합의가 필요해요. 문서 변경은 0.50이면 충분해요. 이렇게 하면 단순한 작업에 과도한 설계를 방지하면서도 위험한 결정에는 충분한 검토를 보장할 수 있어요.7
상태 머신(State Machine)
7개 단계로 구성되며, 각 단계는 이전 단계가 완료되어야 진행돼요:7
IDLE -> RESEARCH -> DELIBERATION -> RANKING -> PRD_GENERATION -> COMPLETE
|
(or FAILED)
RESEARCH: 독립적인 에이전트들이 주제를 조사해요. 각 에이전트는 서로 다른 페르소나(기술 아키텍트, 보안 분석가, 성능 엔지니어 등)를 부여받아요. 컨텍스트 격리를 통해 조사 단계에서 에이전트들이 서로의 발견 사항을 볼 수 없도록 보장해요.
DELIBERATION: 에이전트들이 모든 조사 결과를 확인하고 대안을 생성해요. 토론(Debate) 에이전트가 충돌 사항을 식별하고, 종합(Synthesis) 에이전트가 모순되지 않는 결과를 결합해요.
RANKING: 각 에이전트가 제안된 모든 접근 방식을 5개의 가중 차원에 따라 점수를 매겨요:
| 차원 | 가중치 |
|---|---|
| 영향도(Impact) | 0.25 |
| 품질(Quality) | 0.25 |
| 실현 가능성(Feasibility) | 0.20 |
| 재사용성(Reusability) | 0.15 |
| 리스크(Risk) | 0.15 |
이중 게이트 검증 아키텍처(Two-Gate Validation Architecture)
두 개의 검증 게이트가 서로 다른 단계에서 문제를 포착해요:7
게이트 1: 합의 검증 (PostToolUse hook). 각 심의 에이전트가 완료된 직후 실행돼요: 1. 단계가 최소 RANKING까지 도달해야 해요 2. 최소 2개 에이전트가 완료되어야 해요 (설정 가능) 3. 합의 점수가 작업 적응형 임계값을 충족해야 해요 4. 어떤 에이전트라도 반대 의견을 냈다면 우려 사항이 문서화되어야 해요
게이트 2: Pride Check (Stop hook). 세션이 종료되기 전에 실행돼요: 1. 다양한 방법론: 여러 고유 페르소나가 반영되어야 해요 2. 모순 투명성: 반대 의견에 문서화된 이유가 있어야 해요 3. 복잡성 처리: 최소 2개의 대안이 생성되어야 해요 4. 합의 신뢰도: 강함(0.85 이상) 또는 보통(0.70-0.84)으로 분류되어야 해요 5. 개선 증거: 최종 신뢰도가 초기 신뢰도를 초과해야 해요
서로 다른 라이프사이클 시점의 두 hooks는 실제 실패가 발생하는 방식에 맞춰요: 일부는 즉각적이고(낮은 점수), 일부는 점진적이에요(낮은 다양성, 반대 의견 문서 누락).7
합의가 위험한 이유
Charlan Nemeth는 1986년부터 2018년 저서 In Defense of Troublemakers에 이르기까지 소수 의견의 역할을 연구했어요. 반대 의견을 가진 구성원이 있는 그룹이 빠르게 합의에 도달하는 그룹보다 더 나은 결정을 내려요. 반대 의견을 내는 사람이 옳을 필요는 없어요. 반대라는 행위 자체가 다수로 하여금 그냥 넘어갔을 가정을 검토하도록 강제해요.18
Wu 등은 LLM 에이전트가 진정으로 토론할 수 있는지 테스트했고, 구조적으로 반대 의견에 대한 인센티브가 없으면 에이전트들이 정확성과 관계없이 가장 자신감 있게 들리는 초기 응답으로 수렴한다는 것을 발견했어요.19 Liang 등은 근본 원인을 “사고의 퇴화(Degeneration-of-Thought)”로 식별했어요: LLM가 한 입장에 대해 신뢰도를 확립하면, 자기 반성으로는 새로운 반론을 생성할 수 없어서 멀티 에이전트 평가가 구조적으로 필수적이에요.20
독립성이 핵심 설계 제약이에요. 동일한 배포 전략을 서로의 결과를 볼 수 있는 상태에서 평가한 두 에이전트는 0.45와 0.48의 점수를 냈어요. 가시성 없이 같은 에이전트: 0.45와 0.72. 0.48과 0.72 사이의 차이가 바로 군집화(herding)의 비용이에요.7
가짜 합의 탐지
순응 탐지 모듈은 에이전트들이 진정한 평가 없이 동의하고 있음을 시사하는 패턴을 추적해요:7
점수 군집화: 모든 에이전트가 10점 척도에서 0.3점 이내로 점수를 매기면, 독립적 평가가 아닌 공유 컨텍스트 오염을 의미해요. 인증 리팩토링을 평가하는 5개 에이전트가 모두 보안 리스크를 7.1에서 7.4 사이로 매겼을 때, 새로운 컨텍스트 격리로 재실행하자 점수가 5.8-8.9로 분산됐어요.
상투적 반대: 에이전트들이 독립적인 이의를 제기하는 대신 서로의 우려 표현을 복사하는 경우.
소수 관점 부재: 상충하는 우선순위를 가진 페르소나들(보안 분석가와 성능 엔지니어는 모든 것에 동의하는 경우가 드물어요)의 만장일치 승인.
순응 탐지기는 명백한 경우(에이전트가 너무 빨리 수렴하는 심의의 약 10-15%)를 포착해요. 나머지 85-90%에 대해서는 합의 및 pride check 게이트가 충분한 검증을 제공해요.
심의에서 효과가 없었던 것
자유 형식 토론 라운드. 데이터베이스 인덱싱 논의에 대한 3라운드의 텍스트 토론은 7,500 토큰의 논쟁을 생산했어요. 라운드 1: 진정한 의견 불일치. 라운드 2: 입장 재진술. 라운드 3: 다른 말로 표현한 동일한 주장. 구조화된 차원 점수 매기기가 자유 형식 토론을 대체하면서 비용은 60% 줄이고 순위 품질은 향상시켰어요.7
단일 검증 게이트. 첫 번째 구현에서는 세션 종료 시 하나의 검증 hook을 실행했어요. 에이전트가 0.52 합의 점수(임계값 미만)로 심의를 완료한 뒤, 세션 종료 hook이 실패를 감지하기까지 관련 없는 작업을 20분 동안 계속했어요. 두 개의 게이트로 분리하자(작업 완료 시 하나, 세션 종료 시 하나) 동일한 문제를 서로 다른 라이프사이클 시점에서 포착할 수 있었어요.7
심의 비용
각 조사 에이전트는 약 5,000 토큰의 컨텍스트를 처리하고 2,000-3,000 토큰의 결과를 생성해요. 에이전트 3개면 결정당 추가로 15,000-24,000 토큰이에요. 에이전트 10개면 약 50,000-80,000 토큰이에요.7
현재 Opus 가격 기준으로, 에이전트 3개 심의 비용은 약 $0.68-0.90이에요. 에이전트 10개 심의 비용은 $2.25-3.00이에요. 시스템은 전체 결정의 약 10%에서 심의를 트리거하므로, 모든 결정에 걸친 분할 상각 비용은 세션당 $0.23-0.30이에요. 이것이 가치 있는지 여부는 잘못된 결정의 비용에 달려 있어요.
심의가 필요한 경우와 불필요한 경우
| 심의 필요 | 건너뛰기 |
|---|---|
| 보안 아키텍처 | 문서 오타 |
| 데이터베이스 스키마 설계 | 변수 이름 변경 |
| API 계약 변경 | 로그 메시지 업데이트 |
| 배포 전략 | 주석 수정 |
| 종속성 업그레이드 | 테스트 픽스처 업데이트 |
CLAUDE.md 설계
CLAUDE.md는 인간을 위한 README가 아니라 AI 에이전트를 위한 운영 정책이에요.21 에이전트는 conventional commits를 왜 사용하는지 이해할 필요가 없어요. 실행할 정확한 명령어와 “완료”가 어떤 상태인지를 알아야 해요.
우선순위 계층 구조(Precedence Hierarchy)
| 위치 | 범위 | 공유 여부 | 사용 사례 |
|---|---|---|---|
| Enterprise managed settings | 조직 | 모든 사용자 | 회사 표준 |
./CLAUDE.md 또는 ./.claude/CLAUDE.md |
프로젝트 | Git을 통해 | 팀 컨텍스트 |
~/.claude/CLAUDE.md |
사용자 | 모든 프로젝트 | 개인 환경 설정 |
./CLAUDE.local.md |
프로젝트 로컬 | 공유 안 함 | 개인 프로젝트 메모 |
.claude/rules/*.md |
프로젝트 규칙 | Git을 통해 | 분류된 정책 |
~/.claude/rules/*.md |
사용자 규칙 | 모든 프로젝트 | 개인 정책 |
규칙 파일은 자동으로 로드되며 CLAUDE.md를 어지럽히지 않고 구조화된 컨텍스트를 제공해요.6
무시되는 것들
다음 패턴은 에이전트 동작에 관찰 가능한 변화를 만들지 못해요:21
명령어 없는 산문 단락. “깔끔하고 잘 테스트된 코드를 지향합니다”는 문서이지 운영 지침이 아니에요. 에이전트는 이를 읽고 테스트 없이 코드를 작성해요. 실행 가능한 지시가 없기 때문이에요.
모호한 지시문. “데이터베이스 마이그레이션에 주의하세요”는 제약 조건이 아니에요. “alembic check를 마이그레이션 적용 전에 실행하세요. 다운그레이드 경로가 없으면 중단하세요.”는 제약 조건이에요.
상충하는 우선순위. “빠르게 움직이고 빠르게 출시하세요” + “포괄적인 테스트 커버리지를 보장하세요” + “실행 시간을 5분 이내로 유지하세요” + “매 커밋 전에 전체 통합 테스트를 실행하세요.” 에이전트는 네 가지를 동시에 충족할 수 없고, 기본적으로 검증을 건너뛰게 돼요.21
강제 수단 없는 스타일 가이드. ruff check --select D 없이 “Google Python 스타일 가이드를 따르세요”라고만 하면 에이전트가 준수 여부를 확인할 수 있는 메커니즘이 없어요.
효과적인 방법
명령어 우선 지시문:
## Build and Test Commands
- Install: `pip install -r requirements.txt`
- Lint: `ruff check . --fix`
- Format: `ruff format .`
- Test: `pytest -v --tb=short`
- Type check: `mypy app/ --strict`
- Full verify: `ruff check . && ruff format --check . && pytest -v`
완료 정의(Closure definitions):
## 완료 기준
작업은 다음 항목이 모두 통과해야 완료된 것으로 간주해요:
1. `ruff check .`가 종료 코드 0으로 완료
2. `pytest -v`가 실패 없이 종료 코드 0으로 완료
3. `mypy app/ --strict`가 종료 코드 0으로 완료
4. 변경된 파일이 스테이징되고 커밋된 상태
5. 커밋 메시지가 컨벤션 형식을 따름: `type(scope): description`
작업별로 구성된 섹션:
## 코드 작성 시
- 파일을 변경할 때마다 `ruff check .`를 실행하세요
- 모든 새 함수에 타입 힌트를 추가하세요
## 코드 리뷰 시
- 보안 이슈를 확인하세요: `bandit -r app/`
- 테스트 커버리지를 검증하세요: `pytest --cov=app --cov-fail-under=80`
## 릴리스 시
- `pyproject.toml`에서 버전을 업데이트하세요
- 전체 테스트 스위트를 실행하세요: `pytest -v && ruff check . && mypy app/`
에스컬레이션 규칙:
## 작업이 막혔을 때
- 3번 시도 후에도 테스트가 실패하면: 중단하고 실패한 테스트와 전체 출력을 보고하세요
- 의존성이 없으면: 먼저 `requirements.txt`를 확인한 후 질문하세요
- 절대 하지 말 것: 오류 해결을 위해 파일을 삭제하거나, force push하거나, 테스트를 건너뛰는 행위
작성 순서
처음부터 시작하는 경우, 다음 우선순위 순서로 섹션을 추가하세요:21
- 빌드 및 테스트 명령어 (에이전트가 유용한 작업을 하려면 이것이 먼저 필요해요)
- 완료 기준 (잘못된 완료 판정을 방지해요)
- 에스컬레이션 규칙 (파괴적인 우회 해결책을 방지해요)
- 작업별 구성 섹션 (불필요한 지시사항 파싱을 줄여요)
- 디렉토리 범위 지정 (모노레포에서 서비스별 지시사항을 격리해요)
처음 네 가지가 제대로 작동하기 전까지 스타일 관련 설정은 건너뛰세요.
파일 가져오기
CLAUDE.md 내에서 다른 파일을 참조할 수 있어요:
See @README.md for project overview
Coding standards: @docs/STYLE_GUIDE.md
API documentation: @docs/API.md
Personal preferences: @~/.claude/preferences.md
가져오기 문법은 상대 경로(@docs/file.md), 절대 경로(@/absolute/path.md), 또는 홈 디렉토리(@~/.claude/file.md)를 지원해요. 최대 깊이는 5단계까지 가져올 수 있어요.6
도구 간 지시사항 호환성
AGENTS.md는 60,000개 이상의 프로젝트에서 채택되고 모든 주요 AI 코딩 도구에서 인식하는 개방형 표준이에요.21 팀에서 여러 도구를 사용한다면 AGENTS.md를 기준 문서로 작성하고 관련 섹션을 도구별 파일에 미러링하세요:
| 도구 | 네이티브 파일 | AGENTS.md 읽기 지원? |
|---|---|---|
| Codex CLI | AGENTS.md | 예 (네이티브) |
| Cursor | .cursor/rules |
예 (네이티브) |
| GitHub Copilot | .github/copilot-instructions.md |
예 (네이티브) |
| Amp | AGENTS.md | 예 (네이티브) |
| Windsurf | .windsurfrules |
예 (네이티브) |
| Claude Code | CLAUDE.md | 아니오 (별도 형식) |
AGENTS.md의 패턴(명령어 우선, 클로저 정의, 작업별 구성)은 도구에 관계없이 모든 지시사항 파일에서 동작해요. 서로 어긋나는 병렬 지시사항 세트를 유지하지 마세요. 하나의 권위 있는 소스를 작성하고 미러링하세요.
지시사항 테스트하기
에이전트가 실제로 지시사항을 읽고 따르는지 검증하세요:
# Check active instructions
claude --print "What instructions are you following for this project?"
# Verify specific rules are active
claude --print "What is your definition of done?"
핵심 테스트: 에이전트에게 빌드 명령어를 설명해 달라고 요청하세요. 명령어를 그대로 재현하지 못한다면, 지시사항이 너무 장황하거나(콘텐츠가 컨텍스트 밖으로 밀려남), 너무 모호하거나(에이전트가 실행 가능한 지시를 추출할 수 없음), 아예 발견되지 않는 것이에요. GitHub의 2,500개 리포지토리 분석에 따르면 모호함이 대부분의 실패 원인이에요.21
프로덕션 패턴
Quality Loop
모든 중요한 변경 사항에 대해 필수로 수행하는 리뷰 프로세스예요:
- 구현 - 코드를 작성해요
- 리뷰 - 모든 줄을 다시 읽어요. 오타, 논리 오류, 불명확한 부분을 찾아요
- 평가 - Evidence gate를 실행해요. 패턴, 엣지 케이스, 테스트 커버리지를 확인해요
- 개선 - 모든 이슈를 수정해요. “나중에”로 미루지 않아요
- 전체 조망 - 통합 지점, 임포트, 인접 코드에서 리그레션을 확인해요
- 반복 - evidence gate 기준 중 하나라도 실패하면 4단계로 돌아가요
- 보고 - 변경 사항, 검증 방법을 나열하고 구체적인 증거를 제시해요
Evidence Gate
“~라고 생각합니다”와 “~일 것입니다”는 증거가 아니에요. 파일 경로, 테스트 출력, 또는 구체적인 코드를 인용하세요.
| 기준 | 필요한 증거 |
|---|---|
| 코드베이스 패턴을 따름 | 패턴 이름과 해당 패턴이 존재하는 파일을 명시하세요 |
| 가장 단순한 동작 솔루션 | 거부한 더 단순한 대안과 그 이유를 설명하세요 |
| 엣지 케이스 처리 | 구체적인 엣지 케이스와 각각의 처리 방법을 나열하세요 |
| 테스트 통과 | 실패 0건을 보여주는 테스트 출력을 붙여넣으세요 |
| 리그레션 없음 | 확인한 파일/기능을 명시하세요 |
| 실제 문제를 해결함 | 사용자의 요구사항과 이를 어떻게 충족하는지 기술하세요 |
어떤 항목이든 증거를 제시할 수 없다면 개선 단계로 돌아가세요.22
오류 처리 패턴
원자적 파일 쓰기. 여러 에이전트가 동일한 상태 파일에 동시에 쓰면 JSON이 손상돼요. .tmp 파일에 먼저 쓴 다음 mv로 원자적으로 이동하세요. OS는 동일 파일시스템에서 mv가 원자적임을 보장해요.17
# Atomic state update
jq --argjson d "$new_depth" '.depth = $d' "$STATE_FILE" > "${STATE_FILE}.tmp"
mv "${STATE_FILE}.tmp" "$STATE_FILE"
상태 손상 복구. 상태가 손상되면 복구 패턴은 크래시 대신 안전한 기본값으로 재생성해요:16
if ! jq -e '.depth' "$RECURSION_STATE_FILE" &>/dev/null; then
# Corrupted state file, recreate with safe defaults
echo '{"depth": 0, "agent_id": "root", "parent_id": null}' > "$RECURSION_STATE_FILE"
echo "- Recursion state recovered (was corrupted)"
fi
((VAR++)) bash 함정. ((VAR++)) 는 VAR이 0일 때 종료 코드 1을 반환해요. 0++이 0으로 평가되고 bash가 이를 false로 처리하기 때문이에요. set -e가 활성화된 상태에서는 스크립트가 종료돼요. 대신 VAR=$((VAR + 1))을 사용하세요.16
영향 범위 분류
모든 에이전트 동작을 영향 범위별로 분류하고 그에 맞게 게이트를 설정하세요:2
| 분류 | 예시 | 게이트 |
|---|---|---|
| 로컬 | 파일 쓰기, 테스트 실행, 린팅 | 자동 승인 |
| 공유 | Git 커밋, 브랜치 생성 | 경고 후 진행 |
| 외부 | Git push, API 호출, 배포 | 사람의 승인 필요 |
Remote Control(모든 브라우저나 모바일 앱에서 로컬 Claude Code에 연결)을 사용하면 “외부” 게이트가 블로킹 대기에서 비동기 알림으로 전환돼요. 이전 작업을 휴대폰에서 리뷰하는 동안 에이전트는 다음 작업을 계속 진행해요.2
자율 실행을 위한 작업 명세
효과적인 자율 작업에는 목표, 완료 기준, 컨텍스트 포인터의 세 가지 요소가 필요해요:16
OBJECTIVE: Implement multi-agent deliberation with consensus validation.
COMPLETION CRITERIA:
- All tests in tests/test_deliberation_lib.py pass (81 tests)
- post-deliberation.sh validates consensus above 70% threshold
- recursion-guard.sh enforces spawn budget (max 12 agents)
- No Python type errors (mypy clean)
CONTEXT:
- Follow patterns in lib/deliberation/state_machine.py
- Consensus thresholds in configs/deliberation-config.json
- Spawn budget model: agents inherit budget, not increment depth
기준은 기계적으로 검증 가능해야 해요: 테스트 통과/실패, 린터 출력, HTTP 상태 코드, 파일 존재 여부 확인 등. 초기에 에이전트에게 “통과하는 테스트를 작성하라”고 요청했더니 assert True와 assert 1 == 1을 생성한 적이 있어요. 기술적으로는 맞지만 실질적으로는 무의미해요.16
| 기준 품질 | 예시 | 결과 |
|---|---|---|
| 모호함 | “테스트가 통과한다” | 에이전트가 사소한 테스트를 작성함 |
| 측정 가능하나 불완전 | “테스트 통과 AND 커버리지 >80%” | 라인은 커버하지만 의미 있는 테스트가 아님 |
| 포괄적 | “모든 테스트 통과 AND 커버리지 >80% AND 타입 에러 없음 AND 린터 클린 AND 각 테스트 클래스가 서로 다른 모듈을 테스트” | 프로덕션 수준의 결과물 |
주의해야 할 실패 모드
| 실패 모드 | 설명 | 예방법 |
|---|---|---|
| 지름길 나선 | 빨리 끝내려고 quality loop 단계를 건너뜀 | Evidence gate가 각 기준에 대한 증거를 요구함 |
| 자신감 신기루 | 검증을 실행하지 않고 “확신합니다”라고 말함 | 완료 보고서에서 모호한 표현을 금지함 |
| 유령 검증 | 이번 세션에서 테스트를 실행하지 않고 통과했다고 주장 | Stop hook이 독립적으로 테스트를 실행함 |
| 미뤄진 부채 | 커밋된 코드에 TODO/FIXME/HACK이 포함됨 | PreToolUse hook이 git commit 시 diff를 스캔함 |
| 파일시스템 오염 | 중단된 반복 작업에서 남은 불필요한 산출물 | 완료 기준에 정리 단계를 포함함 |
구체적인 세션 추적 예시
5개의 스토리가 포함된 PRD를 처리하는 자율 실행의 세션 추적이에요:2
-
SessionStart 실행. Dispatcher가 주입하는 항목: 현재 날짜, 프로젝트 감지, 철학적 제약 조건, 비용 추적 초기화. 5개의 hooks, 총 180ms.
-
에이전트가 PRD를 읽고 첫 번째 스토리를 계획.
UserPromptSubmit실행. Dispatcher가 주입하는 항목: 활성 프로젝트 컨텍스트, 세션 드리프트 기준선. -
에이전트가 Bash를 호출하여 테스트 실행.
PreToolUse:Bash실행. 자격 증명 확인, 샌드박스 검증, 프로젝트 감지. 90ms. 테스트 실행.PostToolUse:Bash실행: 활동 하트비트 기록, 드리프트 확인. -
에이전트가 Write를 호출하여 파일 생성.
PreToolUse:Write실행: 파일 범위 확인.PostToolUse:Write실행: 린트 확인, 커밋 추적. -
에이전트가 스토리를 완료.
Stop실행. 품질 게이트 확인: 에이전트가 증거를 인용했는가? 모호한 표현은? diff에 TODO 코멘트가 있는가? 어떤 확인이라도 실패하면 종료 코드 2를 반환하고 에이전트가 계속 진행. -
독립 검증: 새로운 에이전트가 이전 에이전트의 자체 보고를 신뢰하지 않고 테스트 스위트를 실행.
-
3개의 코드 리뷰 에이전트가 병렬로 생성. 각각 독립적으로 diff를 리뷰. 리뷰어 중 누구라도 CRITICAL을 플래그하면 해당 스토리는 큐로 돌아감.
-
스토리 통과. 다음 스토리 로드. 5개 스토리 모두에 대해 이 사이클이 반복.
5개 스토리에서 실행된 총 hooks: ~340회. hooks에 소요된 총 시간: ~12초. 이 오버헤드 덕분에 하룻밤 자율 실행에서 3건의 자격 증명 유출, 1건의 파괴적 명령어, 2건의 불완전한 구현을 방지했어요.
보안 고려사항
샌드박스
Claude Code는 네트워크 접근과 파일시스템 작업을 제한하는 샌드박스에서 실행돼요. 샌드박스는 모델이 임의의 네트워크 요청을 보내거나 프로젝트 디렉토리 외부의 파일에 접근하는 것을 방지해요.13
권한 경계
권한 시스템은 여러 수준에서 작업을 제어해요:
| 수준 | 제어 대상 | 예시 |
|---|---|---|
| 도구 권한 | 사용 가능한 도구 | subagent를 Read, Grep, Glob으로 제한 |
| 파일 권한 | 수정 가능한 파일 | .env, credentials.json 쓰기 차단 |
| 명령어 권한 | 실행 가능한 bash 명령어 | rm -rf, git push --force 차단 |
| 네트워크 권한 | 접근 가능한 도메인 | MCP 서버 연결용 허용 목록 |
프롬프트 인젝션 방어
Skills와 hooks는 프롬프트 인젝션에 대한 심층 방어를 제공해요:
도구 제한이 있는 Skills는 손상된 프롬프트가 쓰기 권한을 획득하는 것을 방지해요:
allowed-tools: Read, Grep, Glob
PreToolUse hooks는 모델이 어떤 프롬프트를 받았는지와 관계없이 모든 도구 호출을 검증해요:
# Block credential file access regardless of prompt
if echo "$FILE_PATH" | grep -qE "\.(env|pem|key|credentials)$"; then
echo "BLOCKED: Sensitive file access" >&2
exit 2
fi
Subagent 격리는 피해 범위를 제한해요. permissionMode: plan으로 설정된 subagent는 프롬프트가 손상되더라도 변경을 수행할 수 없어요.
Hook 보안
환경 변수를 헤더에 삽입하는 HTTP hooks는 임의의 환경 변수 유출을 방지하기 위해 명시적인 allowedEnvVars 목록이 필요해요:13
{
"type": "http",
"url": "https://api.example.com/notify",
"headers": {
"Authorization": "Bearer $MY_TOKEN"
},
"allowedEnvVars": ["MY_TOKEN"]
}
사람과 에이전트의 책임 분담
에이전트 아키텍처의 보안은 사람과 에이전트 간의 명확한 책임 분담이 필요해요:17
| 사람의 책임 | 에이전트의 책임 |
|---|---|
| 문제 정의 | 파이프라인 실행 |
| 신뢰도 임계값 설정 | 임계값 내 실행 |
| 합의 요건 정의 | 합의 계산 |
| quality gate 기준 설정 | quality gate 적용 |
| 오류 분석 | 오류 탐지 |
| 아키텍처 결정 | 아키텍처 옵션 제시 |
| 도메인 컨텍스트 주입 | 문서 생성 |
핵심 패턴은 이래요: 사람은 조직적 맥락, 윤리적 판단, 전략적 방향이 필요한 결정을 담당하고, 에이전트는 광범위한 가능성 공간에서의 계산적 탐색이 필요한 결정을 담당해요. Hooks가 이 경계를 강제해요.
재귀적 Hook 적용
Hooks는 subagent 작업에도 발동돼요.13 Claude가 Agent tool을 통해 subagent를 생성하면, subagent가 사용하는 모든 도구에 대해 PreToolUse와 PostToolUse hooks가 실행돼요. 재귀적 hook 적용이 없으면 subagent가 보안 게이트를 우회할 수 있어요. SubagentStop 이벤트를 사용하면 subagent 완료 시 정리 또는 검증 작업을 실행할 수 있어요.
이건 선택사항이 아니에요. 보안 hooks 없이 subagent를 생성하는 에이전트는 메인 대화의 게이트가 아무것도 하지 않는 동안 main에 force-push하거나, 인증 파일을 읽거나, 파괴적인 명령어를 실행할 수 있는 에이전트예요.
비용도 아키텍처다
비용은 운영상의 부수적 고려가 아니라 아키텍처적 결정이에요.2 세 가지 수준이 있어요:
토큰 수준. 시스템 프롬프트 압축이에요. 튜토리얼 코드 예제를 제거하고(모델은 이미 API를 알고 있어요), 파일 간 중복 규칙을 통합하고, 설명을 제약 조건으로 대체하세요. “민감한 경로와 일치하는 도구 호출을 거부하세요”는 인증 정보를 읽으면 안 되는 이유에 대한 15줄짜리 설명과 동일한 역할을 해요.
에이전트 수준. 긴 대화 대신 새로운 에이전트를 생성하세요. 자율 실행에서 각 스토리는 깨끗한 컨텍스트를 가진 새 에이전트를 받아요. 각 에이전트가 새로 시작하기 때문에 컨텍스트가 비대해지지 않아요. 메모리 대신 브리핑: 모델은 30단계의 누적된 컨텍스트를 탐색하는 것보다 명확한 브리핑을 더 잘 실행해요.
아키텍처 수준. 작업이 무상태일 때는 MCP보다 CLI 우선이에요. 일회성 평가를 위한 claude --print 호출은 비용이 적고 연결 오버헤드도 없어요. MCP는 도구가 지속적 상태나 스트리밍이 필요할 때 적합해요.
결정 프레임워크
각 메커니즘을 사용할 시점:
| 문제 | 사용할 것 | 이유 |
|---|---|---|
| 편집할 때마다 코드 포맷팅 | PostToolUse hook | 매번 결정적으로 실행되어야 함 |
| 위험한 bash 명령어 차단 | PreToolUse hook | 실행 전에 차단해야 하며, exit code 2 사용 |
| 보안 리뷰 패턴 적용 | Skill | 컨텍스트에 따라 자동 활성화되는 도메인 전문성 |
| 컨텍스트 오염 없이 코드베이스 탐색 | Explore subagent | 격리된 컨텍스트, 요약만 반환 |
| 실험적 리팩토링을 안전하게 실행 | Worktree 격리 subagent | 실패 시 변경사항 폐기 가능 |
| 여러 관점에서 코드 리뷰 | 병렬 subagents 또는 Agent Team | 독립적 평가가 사각지대 방지 |
| 되돌릴 수 없는 아키텍처 결정 | 다중 에이전트 심의 | 신뢰도 트리거 + 합의 검증 |
| 세션 간 결정사항 유지 | MEMORY.md | 파일시스템은 컨텍스트 경계를 넘어 유지됨 |
| 팀 표준 공유 | 프로젝트 CLAUDE.md + .claude/rules/ | Git으로 배포되고 자동으로 로드됨 |
| 프로젝트 빌드/테스트 명령어 정의 | CLAUDE.md | 에이전트가 검증할 수 있는 명령어 중심 지침 |
| 장시간 자율 개발 실행 | Ralph loop (새 컨텍스트 반복) | 반복마다 전체 컨텍스트 예산, 파일시스템 상태 |
| 세션 종료 시 Slack 알림 | 비동기 Stop hook | 논블로킹, 세션 속도 저하 없음 |
| 커밋 전 품질 검증 | git commit에 대한 PreToolUse hook | 린트/테스트 실패 시 커밋 차단 |
| 완료 기준 강제 | Stop hook | 작업 완료 전 에이전트 중단 방지 |
Skills vs Hooks vs Subagents
| 차원 | Skills | Hooks | Subagents |
|---|---|---|---|
| 호출 방식 | 자동 (LLM 추론) | 결정적 (이벤트 기반) | 명시적 또는 자동 위임 |
| 보장 수준 | 확률적 (모델이 결정) | 결정적 (항상 발동) | 결정적 (격리된 컨텍스트) |
| 컨텍스트 비용 | 메인 컨텍스트에 주입 | 제로 (LLM 외부에서 실행) | 별도의 컨텍스트 윈도우 |
| 토큰 비용 | 설명 예산 (윈도우의 2%) | 제로 | subagent당 전체 컨텍스트 |
| 적합한 용도 | 도메인 전문성 | 정책 적용 | 집중 작업, 탐색 |
FAQ
hooks가 몇 개면 너무 많은 건가요?
개수가 아니라 성능이 제약이에요. 각 hook은 동기적으로 실행되므로, 총 hook 실행 시간이 매칭되는 모든 도구 호출에 추가돼요. 사용자 수준과 프로젝트 수준 설정에 걸쳐 95개의 hooks도 각 hook이 200ms 이내에 완료되면 눈에 띄는 지연 없이 실행돼요. 주의할 임계값은 이래요: PostToolUse hook이 모든 파일 편집에 500ms 이상을 추가하면 세션이 느려지게 돼요. hooks를 배포하기 전에 time으로 프로파일링하세요.14
hooks가 Claude Code의 명령어 실행을 차단할 수 있나요?
네. PreToolUse hooks는 exit code 2로 종료하여 모든 도구 작업을 차단해요. Claude Code는 보류 중인 작업을 취소하고 hook의 stderr 출력을 모델에 보여줘요. Claude는 거부 사유를 확인하고 더 안전한 대안을 제안해요. Exit 1은 작업이 계속 진행되는 논블로킹 경고예요.3
hook 설정 파일은 어디에 두어야 하나요?
Hook 설정은 프로젝트 수준 hooks의 경우 .claude/settings.json에(리포지토리에 커밋되어 팀과 공유), 사용자 수준 hooks의 경우 ~/.claude/settings.json에 두면 돼요. 둘 다 존재할 때는 프로젝트 수준 hooks가 우선해요. 작업 디렉토리 문제를 피하려면 스크립트 파일에 절대 경로를 사용하세요.14
모든 결정에 심의가 필요한가요?
아니요. 신뢰도 모듈은 네 가지 차원(모호성, 복잡성, 위험도, 컨텍스트 의존성)에 걸쳐 결정을 점수화해요. 전체 신뢰도가 0.70 미만인 결정만 심의를 트리거하며, 이는 전체 결정의 약 10% 정도예요. 문서 수정, 변수 이름 변경, 일상적인 편집은 심의를 완전히 건너뛰어요. 보안 아키텍처, 데이터베이스 스키마 변경, 되돌릴 수 없는 배포는 일관되게 심의를 트리거해요.7
의견 불일치를 만들어내도록 설계된 시스템을 어떻게 테스트하나요?
성공 경로와 실패 경로 모두 테스트하세요. 성공: 에이전트들이 생산적으로 의견이 다르고 합의에 도달해요. 실패: 에이전트들이 너무 빨리 수렴하거나, 합의에 도달하지 못하거나, 생성 예산을 초과해요. 엔드투엔드 테스트는 결정론적 에이전트 응답으로 각 시나리오를 시뮬레이션하여, 검증 게이트가 문서화된 모든 실패 모드를 잡는지 확인해요. 프로덕션 심의 시스템은 세 개 계층에 걸쳐 141개의 테스트를 실행해요: 48개의 bash 통합 테스트, 81개의 Python 단위 테스트, 12개의 엔드투엔드 파이프라인 시뮬레이션.7
심의의 지연 시간 영향은 어느 정도인가요?
3개 에이전트 심의는 30-60초의 실제 시간이 추가돼요(에이전트들은 Agent tool을 통해 순차적으로 실행돼요). 10개 에이전트 심의는 2-4분이 추가돼요. 합의와 pride check hooks는 각각 200ms 이내에 실행돼요. 주요 병목은 오케스트레이션 오버헤드가 아니라 에이전트당 LLM 추론 시간이에요.7
CLAUDE.md 파일은 얼마나 길어야 하나요?
각 섹션은 50줄 이내, 전체 파일은 150줄 이내로 유지하세요. 긴 파일은 컨텍스트 윈도우에 의해 잘리므로, 가장 중요한 지침을 앞에 배치하세요: 스타일 선호도보다 명령어와 클로저 정의를 먼저 두세요.21
Claude Code 외의 다른 도구에서도 사용할 수 있나요?
아키텍처 원칙(결정적 게이트로서의 hooks, 도메인 전문성으로서의 skills, 격리된 컨텍스트로서의 subagents, 메모리로서의 파일시스템)은 개념적으로 모든 에이전트 시스템에 적용돼요. 구체적인 구현은 Claude Code의 라이프사이클 이벤트, 매처 패턴, Agent tool을 사용해요. AGENTS.md는 동일한 패턴을 Codex, Cursor, Copilot, Amp, Windsurf로 확장해요.21 harness 패턴은 도구에 구애받지 않지만, 구현 세부사항은 도구별로 다를 수 있어요.
빠른 참조 카드
Hook 설정
{
"hooks": {
"PreToolUse": [{"matcher": "Bash", "hooks": [{"type": "command", "command": "script.sh"}]}],
"PostToolUse": [{"matcher": "Write|Edit", "hooks": [{"type": "command", "command": "format.sh"}]}],
"Stop": [{"matcher": "", "hooks": [{"type": "agent", "prompt": "Verify tests pass. $ARGUMENTS"}]}],
"SessionStart": [{"matcher": "", "hooks": [{"type": "command", "command": "setup.sh"}]}]
}
}
Skill 프론트매터
---
name: my-skill
description: What it does and when to use it. Include trigger phrases.
allowed-tools: Read, Grep, Glob
---
Subagent 정의
---
name: my-agent
description: When to invoke. Include PROACTIVELY for auto-delegation.
tools: Read, Grep, Glob, Bash
model: opus
permissionMode: plan
---
Instructions for the subagent.
종료 코드
| 코드 | 의미 | 용도 |
|---|---|---|
| 0 | 성공 | 작업 허용 |
| 2 | 차단 | 보안 게이트, 품질 게이트 |
| 1 | 비차단 경고 | 로깅, 안내 메시지 |
주요 명령어
| 명령어 | 용도 |
|---|---|
/compact |
컨텍스트 압축, 결정 사항 보존 |
/context |
컨텍스트 할당 및 활성 skills 확인 |
/agents |
subagents 관리 |
claude -c |
가장 최근 세션 이어서 진행 |
claude --print |
단발성 CLI 호출 (대화 없음) |
# <note> |
메모리 파일에 메모 추가 |
/memory |
자동 메모리 확인 및 관리 |
파일 위치
| 경로 | 용도 |
|---|---|
~/.claude/CLAUDE.md |
개인 전역 설정 |
.claude/CLAUDE.md |
프로젝트 설정 (git 공유) |
.claude/settings.json |
프로젝트 hooks 및 권한 |
~/.claude/settings.json |
사용자 hooks 및 권한 |
~/.claude/skills/<name>/SKILL.md |
개인 skills |
.claude/skills/<name>/SKILL.md |
프로젝트 skills (git 공유) |
~/.claude/agents/<name>.md |
개인 subagent 정의 |
.claude/agents/<name>.md |
프로젝트 subagent 정의 |
.claude/rules/*.md |
프로젝트 규칙 파일 |
~/.claude/rules/*.md |
사용자 규칙 파일 |
~/.claude/projects/{path}/memory/MEMORY.md |
자동 메모리 |
변경 이력
| 날짜 | 변경 사항 |
|---|---|
| 2026-03-24 | 최초 게시 |
참고 문헌
-
Andrej Karpathy의 LLM 에이전트 위에 구축하는 새로운 레이어 “claws” 개념. HN 토론 (406 포인트, 917 댓글). ↩
-
저자의 구현 사례. 84개 hooks, 48개 skills, 19개 agents, 약 15,000줄의 오케스트레이션 코드. Claude Code as Infrastructure에 문서화. ↩↩↩↩↩↩↩↩
-
Anthropic, “Claude Code Hooks: Exit Codes.” docs.anthropic.com. Exit 0은 허용, exit 2는 차단, exit 1은 경고. ↩↩↩↩↩
-
Anthropic, “Extend Claude with Skills.” code.claude.com/docs/en/skills. Skill 구조, 프론트매터 필드, LLM 기반 매칭, 2% 컨텍스트 예산. ↩↩↩↩↩↩↩
-
Anthropic, “Claude Code Sub-agents.” code.claude.com/docs/en/sub-agents. 격리된 컨텍스트, worktree 지원, 에이전트 팀. ↩↩↩↩↩
-
Anthropic, “Claude Code Documentation.” docs.anthropic.com/en/docs/claude-code. 메모리 파일, CLAUDE.md, 자동 메모리. ↩↩↩↩↩
-
저자의 다중 에이전트 심의 시스템. 10개 연구 페르소나, 7단계 상태 머신, 141개 테스트. Multi-Agent Deliberation에 문서화. ↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩
-
Simon Willison, “Writing code is cheap now.” Agentic Engineering Patterns. ↩
-
Laban, Philippe 외, “LLMs Get Lost In Multi-Turn Conversation,” arXiv:2505.06120, 2025년 5월. Microsoft Research 및 Salesforce. 15개 LLM, 200,000건 이상의 대화, 평균 39% 성능 저하. ↩↩↩
-
Mikhail Shilkov, “Inside Claude Code Skills: Structure, Prompts, Invocation.” mikhail.io. Skill 탐색, 컨텍스트 주입,
available_skills프롬프트 섹션에 대한 독립 분석. ↩ -
Claude Code 소스 코드,
SLASH_COMMAND_TOOL_CHAR_BUDGET. github.com/anthropics/claude-code. ↩ -
Anthropic, “Skill Authoring Best Practices.” platform.claude.com. 500줄 제한, 보조 파일, 명명 규칙. ↩
-
Anthropic, “Claude Code Hooks: Lifecycle Events.” docs.anthropic.com. 22개 라이프사이클 이벤트, hook 유형, 비동기 hooks, HTTP hooks. ↩↩↩↩↩↩
-
저자의 Claude Code hooks 튜토리얼. 5개의 프로덕션 hooks를 처음부터 구축. Claude Code Hooks Tutorial에 문서화. ↩↩↩↩↩
-
저자의 50개 세션에 걸친 컨텍스트 윈도우 관리 경험. Context Window Management에 문서화. ↩↩↩↩↩
-
저자의 Ralph Loop 구현. 파일시스템 상태를 활용한 새로운 컨텍스트 반복, 스폰 예산. The Ralph Loop에 문서화. ↩↩↩↩↩↩↩
-
저자의 심의 시스템 아키텍처. 3,500줄의 Python, 12개 모듈, 신뢰도 트리거, 합의 검증. Building AI Systems: From RAG to Agents에 문서화. ↩↩↩
-
Nemeth, Charlan, In Defense of Troublemakers: The Power of Dissent in Life and Business, Basic Books, 2018. ↩
-
Wu, H., Li, Z., and Li, L., “Can LLM Agents Really Debate?” arXiv:2511.07784, 2025. ↩
-
Liang, T. 외, “Encouraging Divergent Thinking in Large Language Models through Multi-Agent Debate,” EMNLP 2024. ↩
-
저자의 실제 리포지토리 기반 AGENTS.md 분석. AGENTS.md Patterns에 문서화. 참고: GitHub Blog, “How to Write a Great agents.md: Lessons from Over 2,500 Repositories.” ↩↩↩↩↩↩↩↩
-
저자의 quality loop 및 evidence gate 방법론. Jiro Craftsmanship 시스템의 일부. ↩