본문 바로가기
IT

Claude Code Hook 시스템 완전정리: AI 코딩을 자동화하는 확실한 방법

by 샤나엘 2026. 3. 10.
반응형

Claude Code Hook 시스템 완전정리: AI 코딩을 자동화하는 확실한 방법

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

Hook 시스템 완전정리


1. Hook이란? — 확정적 자동화

AI의 확률적 행동에 확정적 규칙을

Claude Code는 LLM 기반이라 항상 똑같이 행동한다는 보장이 없습니다. "파일 수정 후 Prettier 돌려줘"라고 CLAUDE.md에 써놓아도, 가끔 빼먹을 수 있죠. Hook은 이 문제를 해결합니다.

비교 CLAUDE.md 지시 Hook
실행 보장 확률적 (LLM이 판단) 확정적 (무조건 실행)
동작 방식 "~해주세요" 요청 이벤트 발생 시 자동 실행
커스텀 자연어 지시 쉘 스크립트, HTTP, 프롬프트
차단 가능 불가 (권고만 가능) 가능 (exit 2로 차단)

핵심 원리: "확률적 시스템에 확정적 제어를 부여한다."

Hook의 기본 구조

이벤트 발생 → 매처 패턴 확인 → 매칭되면 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 알림 발생 데스크톱 알림

14가지 이벤트 타입


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 비활성화

 

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 멀티턴 에이전트 불가 가능 복합 검증, 테스트

4가지 Hook 타입


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로 커밋 차단

Hook vs MCP 서버


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의 정책에 따라 변경될 수 있으며, 최신 정보는 공식 문서를 확인해 주세요.

반응형

댓글