Claude Code Hook 시스템 완전정리: AI 코딩을 자동화하는 확실한 방법
Claude Code가 파일을 저장할 때마다 자동으로 포맷팅, 위험한 명령을 실행하려 하면 자동으로 차단, 세션 시작 시 컨텍스트 자동 주입 — 이 모든 게 Hook 시스템으로 가능합니다. Hook은 Claude Code의 행동에 확실한 규칙을 심어주는 자동화 기능입니다.

1. Hook이란? — 확정적 자동화
AI의 확률적 행동에 확정적 규칙을
Claude Code는 LLM 기반이라 항상 똑같이 행동한다는 보장이 없습니다. "파일 수정 후 Prettier 돌려줘"라고 CLAUDE.md에 써놓아도, 가끔 빼먹을 수 있죠. Hook은 이 문제를 해결합니다.
| 비교 | CLAUDE.md 지시 | Hook |
|---|---|---|
| 실행 보장 | 확률적 (LLM이 판단) | 확정적 (무조건 실행) |
| 동작 방식 | "~해주세요" 요청 | 이벤트 발생 시 자동 실행 |
| 커스텀 | 자연어 지시 | 쉘 스크립트, HTTP, 프롬프트 |
| 차단 가능 | 불가 (권고만 가능) | 가능 (exit 2로 차단) |
핵심 원리: "확률적 시스템에 확정적 제어를 부여한다."
Hook의 기본 구조
이벤트 발생 → 매처 패턴 확인 → 매칭되면 Hook 실행 → 결과에 따라 진행/차단

2. 14가지 이벤트 타입
Hook이 실행되는 시점
Claude Code에는 14가지 라이프사이클 이벤트가 있고, 각 이벤트에 Hook을 걸 수 있습니다.
세션 이벤트
| 이벤트 | 시점 | 활용 예시 |
|---|---|---|
| SessionStart | 세션 시작/재개 시 | 환경 설정, 컨텍스트 주입 |
| InstructionsLoaded | CLAUDE.md 로드 시 | 규칙 파일 추가 로드 |
| PreCompact | 컨텍스트 압축 전 | 중요 정보 보존 |
| SessionEnd | 세션 종료 시 | 로그 저장, 정리 |
도구 이벤트
| 이벤트 | 시점 | 활용 예시 |
|---|---|---|
| UserPromptSubmit | 사용자 입력 전처리 | 프롬프트 검증 |
| PreToolUse | 도구 실행 전 | 위험 명령 차단 |
| PermissionRequest | 권한 확인 시 | 자동 승인/거부 |
| PostToolUse | 도구 실행 후 | 자동 포맷팅, 린트 |
| PostToolUseFailure | 도구 실패 후 | 에러 로깅 |
에이전트/팀 이벤트
| 이벤트 | 시점 | 활용 예시 |
|---|---|---|
| SubagentStart | 서브에이전트 시작 | 에이전트 설정 |
| SubagentStop | 서브에이전트 종료 | 결과 검증 |
| Stop | Claude 응답 완료 | 최종 검증 |
| Notification | 알림 발생 | 데스크톱 알림 |

3. Hook 설정 방법
settings.json에서 설정
Hook은 settings.json 파일에서 설정합니다.
| 파일 위치 | 범위 | 비고 |
|---|---|---|
~/.claude/settings.json |
모든 프로젝트 | 사용자 전역 |
.claude/settings.json |
현재 프로젝트 | Git 커밋 가능 |
.claude/settings.local.json |
현재 프로젝트 | .gitignore 대상 |
기본 설정 형식
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "npx prettier --write $(echo $TOOL_INPUT | jq -r '.file_path')",
"timeout": 30
}
]
}
]
}
}
구성 요소
| 요소 | 설명 | 예시 |
|---|---|---|
| 이벤트 | Hook이 걸리는 시점 | PostToolUse, PreToolUse |
| matcher | 실행 조건 (정규식) | "Edit|Write", "Bash" |
| type | Hook 종류 | command, http, prompt, agent |
| command | 실행할 명령 | "npx prettier --write ..." |
| timeout | 타임아웃(초) | 30 |
| async | 비동기 실행 | true / false |
/hooks 커맨드로 관리
# Claude Code 안에서
> /hooks
# 대화형 메뉴가 열림:
# - 현재 Hook 목록 보기
# - 새 Hook 추가
# - 기존 Hook 수정/삭제
# - 전체 Hook 비활성화

4. 4가지 Hook 타입
Command Hook — 쉘 명령 실행
가장 기본적인 타입입니다. 쉘 스크립트를 실행하고, stdin으로 이벤트 데이터를 받습니다.
{
"type": "command",
"command": "bash .claude/hooks/format.sh",
"timeout": 30
}
HTTP Hook — 원격 서버 호출
외부 서비스로 이벤트 데이터를 POST합니다. 팀 단위 로깅이나 중앙 관리에 적합합니다.
{
"type": "http",
"url": "https://logging.example.com/hooks",
"headers": {
"Authorization": "Bearer $API_TOKEN"
},
"allowedEnvVars": ["API_TOKEN"],
"timeout": 10
}
Prompt Hook — LLM 판단
Haiku 모델에게 판단을 위임합니다. 단일 턴으로 실행되며 {"ok": true/false, "reason": "..."}를 반환합니다.
{
"type": "prompt",
"prompt": "이 코드 변경이 테스트를 깨뜨릴 가능성이 있나요? JSON으로 답하세요.",
"model": "claude-3-5-haiku-20241022",
"timeout": 30
}
Agent Hook — 멀티턴 에이전트
서브에이전트를 생성해 파일 읽기, 명령 실행 등 복합 검증을 수행합니다.
{
"type": "agent",
"prompt": "테스트 스위트를 실행하고 결과를 분석하세요. $ARGUMENTS",
"timeout": 120,
"max_turns": 50
}
| 타입 | 실행 방식 | 비동기 | 차단 가능 | 활용 |
|---|---|---|---|---|
| Command | 쉘 명령 | 가능 | 가능 | 포맷팅, 린트, 검증 |
| HTTP | HTTP POST | 가능 | 가능 | 로깅, 중앙 관리 |
| Prompt | LLM 단일턴 | 불가 | 가능 | 판단, 분류 |
| Agent | 멀티턴 에이전트 | 불가 | 가능 | 복합 검증, 테스트 |

5. 입출력 형식과 종료 코드
Hook이 받는 입력 (stdin / POST body)
Hook은 JSON 형태로 이벤트 데이터를 받습니다.
{
"session_id": "abc123",
"cwd": "/path/to/project",
"hook_event_name": "PreToolUse",
"tool_name": "Bash",
"tool_input": {
"command": "rm -rf node_modules"
}
}
PostToolUse 입력 (도구 실행 후)
{
"hook_event_name": "PostToolUse",
"tool_name": "Edit",
"tool_input": {
"file_path": "src/main.ts"
},
"tool_response": "파일이 수정되었습니다."
}
종료 코드의 의미
| 종료 코드 | 의미 | Claude에게 전달 |
|---|---|---|
| 0 | 성공, 계속 진행 | stdout이 컨텍스트에 추가 |
| 2 | 차단! 실행 중지 | stderr가 피드백으로 전달 |
| 그 외 | 성공으로 처리 | stderr 로그만 기록 |
차단 예시
#!/bin/bash
# 위험한 명령 차단
INPUT=$(cat)
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command')
if echo "$COMMAND" | grep -qE "rm -rf|DROP TABLE"; then
echo "차단: 파괴적 명령은 허용되지 않습니다" >&2
exit 2 # ← 차단!
fi
exit 0 # ← 통과

6. 실전 예제 모음
예제 1: 파일 수정 후 자동 Prettier
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "jq -r '.tool_input.file_path' | xargs npx prettier --write"
}
]
}
]
}
}
예제 2: 보호 파일 수정 차단
#!/bin/bash
# .claude/hooks/protect-files.sh
INPUT=$(cat)
FILE=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')
for pattern in ".env" "package-lock.json" ".git/"; do
if [[ "$FILE" == *"$pattern"* ]]; then
echo "차단: $FILE은 보호된 파일입니다" >&2
exit 2
fi
done
exit 0
예제 3: 세션 시작 시 컨텍스트 주입
{
"hooks": {
"SessionStart": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "echo '주의: Bun 사용, npm 금지. 커밋 전 bun test 필수. 현재 스프린트: 인증 리팩토링'"
}
]
}
]
}
}
예제 4: 컨텍스트 압축 후 규칙 재주입
{
"hooks": {
"SessionStart": [
{
"matcher": "compact",
"hooks": [
{
"type": "command",
"command": "echo '중요: Bun 사용 필수. npm 사용 금지. 커밋 전 테스트 실행 필수.'"
}
]
}
]
}
}
예제 5: 데스크톱 알림 (Claude가 대기 중일 때)
{
"hooks": {
"Notification": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "osascript -e 'display notification \"Claude Code가 입력을 기다립니다\" with title \"Claude Code\"'"
}
]
}
]
}
}
예제 6: 비동기 테스트 실행
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "npm test",
"async": true,
"timeout": 60
}
]
}
]
}
}

7. 매처 패턴 상세
도구 이름 매칭
매처(matcher)는 정규식으로, 도구 이름과 매칭됩니다.
| 매처 패턴 | 매칭 대상 |
|---|---|
"Bash" |
Bash 도구만 |
"Edit|Write" |
Edit 또는 Write |
"mcp__.*" |
모든 MCP 도구 |
"mcp__github__.*" |
GitHub MCP 도구만 |
"" (빈 문자열) |
모든 도구 |
이벤트별 매칭 대상
| 이벤트 | 매칭 대상 | 예시 |
|---|---|---|
| PreToolUse | 도구 이름 | "Bash", "Edit|Write" |
| PostToolUse | 도구 이름 | "Edit|Write" |
| SessionStart | 시작 방식 | "startup", "resume", "compact" |
| SubagentStart | 에이전트 타입 | "Explore", "Plan" |
| Notification | 알림 종류 | "permission_prompt" |
MCP 도구 매칭
MCP 도구 이름 형식: mcp__<서버이름>__<도구이름>
예시:
- mcp__github__search_repositories
- mcp__slack__send_message
- mcp__filesystem__read_file
매처:
- "mcp__github__.*" → GitHub 서버의 모든 도구
- "mcp__.*__write.*" → 모든 서버의 write 관련 도구

8. Hook vs MCP 서버
언제 Hook, 언제 MCP?
| 비교 | Hook | MCP 서버 |
|---|---|---|
| 실행 시점 | 이벤트 발생 시 자동 | Claude가 필요할 때 호출 |
| 제어 방향 | 반응적 (이벤트 → 실행) | 능동적 (Claude → 도구) |
| 결정권 | 개발자가 설정 | Claude가 판단 |
| 확정성 | 100% 확정적 | 확률적 (LLM 판단) |
| 차단 | 가능 (exit 2) | 불가 |
| 활용 | 포맷팅, 검증, 차단, 로깅 | API 연동, DB, 외부 서비스 |
함께 쓰는 예시
시나리오: GitHub PR 자동 검증
1. Claude가 MCP 서버로 GitHub PR 내용을 읽음
→ MCP 서버가 GitHub API 호출
2. Claude가 코드를 수정함
→ PostToolUse Hook이 자동으로 Prettier 실행
3. Claude가 커밋하려 함
→ PreToolUse Hook이 테스트 통과 여부 확인
4. 테스트 실패 시
→ Hook이 exit 2로 커밋 차단

9. 디버깅과 보안
Hook 디버깅 방법
| 방법 | 설명 |
|---|---|
/hooks |
현재 설정된 Hook 목록 확인 |
Ctrl+O |
상세 모드 — Hook 출력 확인 |
claude --debug |
전체 실행 디버그 로그 |
| 수동 테스트 | echo '{"tool_name":"Bash"}' | ./hook.sh |
흔한 문제 해결
Hook이 실행되지 않는 경우:
- 매처 패턴이 도구 이름과 정확히 일치하는지 확인 (대소문자 구분)
- 이벤트 타입이 올바른지 확인
"command not found" 에러:
- 절대 경로 사용:
"/home/user/.claude/hooks/script.sh" - 스크립트 실행 권한:
chmod +x script.sh
Stop Hook 무한루프:
# stop_hook_active 체크 필수!
INPUT=$(cat)
if [ "$(echo "$INPUT" | jq -r '.stop_hook_active')" = "true" ]; then
exit 0 # 이미 Hook 실행 중이면 종료
fi
보안 주의사항
| 주의사항 | 설명 |
|---|---|
| Hook 코드 리뷰 | 신뢰할 수 없는 프로젝트의 Hook은 반드시 검토 |
| 절대 경로 사용 | PATH 조작을 통한 코드 주입 방지 |
| 입력 검증 | JSON 파싱 시 shell injection 주의 |
| 환경 변수 보호 | HTTP Hook에서 allowedEnvVars로 제한 |
| 비밀 정보 | .claude/settings.local.json은 .gitignore에 추가 |

10. 자주 묻는 질문 (FAQ)
Q: Hook으로 Claude의 행동을 완전히 제어할 수 있나요?
A: 완전한 제어는 아닙니다. Hook은 특정 이벤트 시점에 자동화를 추가하는 것이지, Claude의 모든 판단을 대체하지는 않습니다. CLAUDE.md와 함께 사용하면 가장 효과적입니다.
Q: Hook이 여러 개 설정되면 순서는?
A: 같은 이벤트에 여러 Hook이 있으면 설정 순서대로 실행됩니다. 하나가 차단(exit 2)하면 나머지는 실행되지 않습니다.
Q: 비동기 Hook은 어떤 상황에서 쓰나요?
A: 테스트 실행처럼 결과를 기다리지 않아도 되는 작업에 적합합니다. 비동기 Hook은 차단 기능을 사용할 수 없습니다.
Q: Windows에서도 Hook이 작동하나요?
A: 네, 작동합니다. 다만 쉘 스크립트 대신 PowerShell이나 Windows 호환 명령어를 사용해야 합니다. Git Bash가 설치되어 있으면 bash 스크립트도 사용 가능합니다.
Q: Hook으로 파일을 자동 생성할 수 있나요?
A: 가능합니다. PostToolUse에서 스크립트를 실행해 파일을 생성하거나 수정할 수 있습니다. 다만 Claude의 컨텍스트에 자동 반영되지는 않으므로, 필요시 Claude에게 알려줘야 합니다.
Q: MCP 도구에도 Hook을 걸 수 있나요?
A: 네! MCP 도구 이름은 mcp__<서버>__<도구> 형식이므로, "mcp__github__.*"처럼 매처를 설정하면 됩니다.
Claude Code 시리즈 네비게이션
| 편 | 제목 | 상태 |
|---|---|---|
| 1편 | Claude Code란? AI 코딩의 새 시대 | ✅ |
| 2편 | 설치와 초기 설정 | ✅ |
| 3편 | 기본 사용법 마스터 | ✅ |
| 4편 | 슬래시 커맨드 완전정리 | ✅ |
| 5편 | CLAUDE.md 작성법 | ✅ |
| 6편 | 메모리 시스템 심화 | ✅ |
| 7편 | 권한 시스템 완전정리 | ✅ |
| 8편 | 모델 선택과 컨텍스트 | ✅ |
| 9편 | 요금제 완전 가이드 | ✅ |
| 10편 | Git 연동 완전정리 | ✅ |
| 11편 | Hook 시스템 | 📖 |
| 12편 | MCP 서버 연동 | 🔜 |
| 13편 | 헤드리스 모드와 CI/CD | 🔜 |
면책 조항: 이 글은 정보 제공 목적으로 작성되었습니다. Claude Code의 기능과 요금은 Anthropic의 정책에 따라 변경될 수 있으며, 최신 정보는 공식 문서를 확인해 주세요.
'IT' 카테고리의 다른 글
| Claude Code 헤드리스 모드와 CI/CD 완전정리: 자동화 파이프라인에 AI를 넣는 법 (0) | 2026.03.10 |
|---|---|
| Claude Code MCP 서버 연동 완전정리: AI에 외부 도구를 연결하는 법 (0) | 2026.03.10 |
| Claude Code Git 연동 완전정리: 커밋, PR, 브랜치를 AI로 자동화하는 법 (0) | 2026.03.10 |
| Claude Code 요금제 완전 가이드: Free, Pro, Max, API 비교 (1) | 2026.03.10 |
| Claude Code 모델 선택과 컨텍스트 최적화: 비용 대비 최고 성능 뽑기 (0) | 2026.03.09 |
댓글