DaleSchool

Hooks로 워크플로우 자동화

중급20분

학습 목표

  • Hooks의 주요 이벤트 타입을 이해한다
  • PreToolUse Hook으로 위험한 작업을 차단할 수 있다
  • PostToolUse Hook으로 자동 후처리를 구성할 수 있다

동작하는 코드

프로젝트의 .claude/settings.json에 Hook을 추가해봅시다. main 브랜치에서 파일 수정을 차단하는 Hook입니다:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "[ \"$(git branch --show-current)\" != \"main\" ] || { echo '{\"block\":true,\"message\":\"main 브랜치에서는 직접 수정할 수 없습니다. feature 브랜치를 만드세요.\"}' >&2; exit 2; }",
            "timeout": 5
          }
        ]
      }
    ]
  }
}

이제 main 브랜치에서 Claude에게 파일 수정을 요청해보세요:

> README.md에 한 줄 추가해줘

Hook이 작동하여 수정이 차단됩니다. 다른 브랜치로 전환하면 정상적으로 수정됩니다:

> git checkout -b feature/test로 브랜치를 만들고, README.md를 수정해줘

직접 수정하기

이번에는 PostToolUse Hook으로 파일 저장 후 자동 린트를 실행해봅시다:

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "npx eslint --fix $CLAUDE_FILE_PATHS 2>/dev/null || true",
            "timeout": 10
          }
        ]
      }
    ]
  }
}

Claude가 파일을 수정할 때마다 ESLint가 자동으로 실행되어 스타일을 교정합니다.

"왜?" — 반복되는 규칙을 코드로 강제하기

CLAUDE.md에 "main 브랜치에서 작업하지 마세요"라고 적어도 Claude가 무시할 수 있습니다. Hook은 이런 규칙을 코드로 강제합니다. 요청이 아니라 차단입니다.

주요 Hook 이벤트

이벤트시점용도
PreToolUse도구 실행 전위험 작업 차단, 조건부 승인
PostToolUse도구 실행 후자동 포매팅, 린트, 로깅
Notification알림 발생 시커스텀 알림 (Slack, 데스크톱 등)
Stop응답 완료 시결과 검증, 정리 작업
UserPromptSubmit사용자 입력 시입력 전처리
SubagentStop서브에이전트 완료 시서브에이전트 결과 후처리
PreCompact컨텍스트 압축 전압축 전 데이터 보존
SessionStart세션 시작 시환경 검증, 의존성 체크
SessionEnd세션 종료 시정리, 로깅

이 중 가장 자주 쓰이는 건 PreToolUse, PostToolUse, Notification입니다.

Hook 설정 구조

{
  "hooks": {
    "이벤트이름": [
      {
        "matcher": "도구이름 패턴 (정규식)",
        "hooks": [
          {
            "type": "command",
            "command": "실행할 셸 명령어",
            "timeout": 5
          }
        ]
      }
    ]
  }
}

matcher 패턴

matcher는 어떤 도구에 Hook을 적용할지 필터링합니다:

패턴매칭 대상
Edit|Write파일 수정/생성 도구
Bash셸 명령어 실행
Read파일 읽기
.*모든 도구 (주의해서 사용)

종료 코드로 동작 결정

Hook의 종료 코드가 동작을 결정합니다:

종료 코드동작
0성공 — 작업 계속 진행
2차단 — 도구 실행을 막음
그 외오류로 처리

PreToolUse에서 exit 2를 반환하면 작업이 차단됩니다:

exit 2

stderr로 메시지를 전달하면 Claude에게 차단 이유를 알려줄 수 있습니다:

echo "main 브랜치에서는 수정할 수 없습니다." >&2
exit 2

심화 학습

Hook에서 사용할 수 있는 환경 변수는?

Hook 명령어 안에서 다음 환경 변수를 사용할 수 있습니다:

  • $CLAUDE_FILE_PATHS — 현재 도구 호출에 관련된 파일 경로들 (공백 구분)
  • $CLAUDE_PROJECT_DIR — 프로젝트 루트 디렉토리의 절대 경로

더 상세한 정보가 필요하면 stdin으로 전달되는 JSON을 jq로 파싱할 수 있습니다:

jq -r '.tool_input.command' >> ~/.claude/bash-log.txt
  1. .claude/settings.json에 main 브랜치 보호 Hook을 추가하고 테스트해보세요.
  2. PostToolUse Hook으로 파일 수정 후 자동으로 prettier --write를 실행하는 Hook을 만들어보세요.
  3. SessionStart Hook으로 세션 시작 시 "현재 브랜치: {브랜치명}" 메시지를 출력하는 Hook을 만들어보세요.

Claude Code가 파일을 수정하기 전에 실행되는 Hook 이벤트는?

참고 자료