훅(Hooks)으로 동작 강제하기
Hooks는 Claude Code 라이프사이클의 특정 시점에 자동으로 실행되는 처리입니다. CLAUDE.md의 '부탁'과 달리 모델 판단과 무관하게 항상 동작하는 '규칙'을 만드는 방법과 대표 이벤트 10종을 정리합니다.
Hooks는 Claude Code 라이프사이클의 특정 시점에 자동으로 실행되는 처리입니다. 지침 파일에 "이건 하지 마세요"라고 적는 것은 부탁이지만, 훅은 규칙입니다. 하네스가 직접 실행하므로 모델의 판단과 무관하게 항상 동작합니다.
파일을 편집할 때마다 포매터를 손으로 돌리는 것은 번거롭고, Claude에게 부탁해도 가끔 잊습니다. 훅을 쓰면 LLM의 판단에 기대지 않고 처리를 결정론적으로 실행할 수 있습니다.
핵심 요약
- Hooks는 "~가 일어나면 ~를 실행한다"는 트리거 방식의 자동 처리입니다. 셸 명령 외에 HTTP 엔드포인트, MCP 도구, LLM 판정(prompt), 서브에이전트 판정(agent)으로도 정의할 수 있습니다.
- 최대 특징은 LLM의 판단에 의존하지 않는 결정론적 실행입니다.
- 이벤트 타입은 30종 전후이며, 실무에서는 PreToolUse·PostToolUse·Stop·SessionStart 네 가지를 가장 많이 씁니다.
- 설정은
.claude/settings.json,.claude/settings.local.json,~/.claude/settings.json세 곳 중 하나에 적습니다. - 코드 포맷, 테스트 실행, 위험 명령 차단, 완료 알림 자동화에 씁니다.
언제 훅이 필요한가
- "매번 X한 다음에 Y해줘" 같은 반복 요구가 있을 때
- 절대 일어나면 안 되는 명령이 있을 때 (
rm -rf, 강제 푸시) - 수정 후 항상 포매터나 린터를 돌려야 할 때
- 세션 시작마다 특정 정보를 주입하고 싶을 때
일반 프로그래밍의 훅(Git pre-commit 훅, React의 useEffect)과 같은 개념입니다. Claude Code에서는 도구 실행 전후, 세션 시작·종료 같은 시점에 원하는 처리를 끼워 넣습니다.
CLAUDE.md와 무엇이 다른가
CLAUDE.md에 "파일 편집 후에는 npm run format을 실행해줘"라고 썼다고 합시다. Claude는 이 문장을 읽고 확률론적으로 판단하므로, 문맥에 따라 실행해 줄 때와 안 해줄 때가 생깁니다.
반면 PostToolUse 훅에 npm run format을 걸어 두면 파일 편집 때마다 포매터가 반드시 돌아갑니다. 확실성이 요구되는 처리에는 CLAUDE.md가 아니라 훅을 쓰는 것이 맞습니다.
| 수단 | 성격 | 맡길 것 |
|---|---|---|
| CLAUDE.md | 확률론적 — 모델이 읽고 판단 | 지시, 문맥 정보, 취향 |
| Hooks | 결정론적 — 하네스가 실행 | 매번 확실히 실행해야 하는 처리 |
훅은 "AI를 못 믿어서" 쓰는 장치가 아니라, 자율 실행 범위를 넓히기 위해 쓰는 장치입니다. 사고 가능성을 구조적으로 막아 두면 훨씬 과감하게 맡길 수 있습니다.
대표적인 훅 이벤트 10종
이벤트 타입은 전부 30종 전후 있지만, 자주 쓰는 10종의 발화 시점은 다음과 같습니다.
| 이벤트 | 발화 시점 | 대표 용도 |
|---|---|---|
PreToolUse | 도구 실행 직전 (차단 가능) | 위험 명령 차단 |
PostToolUse | 도구 실행 완료 후 | 자동 포맷, 린트 |
PermissionRequest | 권한 다이얼로그 표시 시 | 권한 요청 기록 |
Notification | 알림 전송 시 | 외부 알림 연동 |
UserPromptSubmit | 사용자 프롬프트 전송 시 | 프롬프트 검사, 정보 주입 |
Stop | 메인 에이전트 완료 시 | 완료 알림, 로그 기록 |
SubagentStop | 서브에이전트 완료 시 | 서브에이전트 결과 후처리 |
SessionStart | 세션 시작·재개 시 | 브랜치·환경 정보 주입, 초기화 |
SessionEnd | 세션 종료 시 | 정리, 로그 저장 |
PreCompact | 컴팩트 실행 전 | 컨텍스트 백업 |
도구 실행을 차단할 수 있는 시점은 PreToolUse뿐입니다. 나머지는 관찰과 후처리용입니다. 실무에서 가장 많이 쓰는 것은 PreToolUse(사전 체크), PostToolUse(자동 포맷), Stop(완료 알림), SessionStart(환경 초기화) 네 가지입니다.
훅은 어디에 설정하나
훅 설정은 세 곳에 쓸 수 있습니다. 스코프와 Git 관리 여부가 다르므로 용도에 맞게 고릅니다.
| 설정 파일 | 스코프 | Git 관리 |
|---|---|---|
.claude/settings.json | 프로젝트 | 커밋 대상 (추천) |
.claude/settings.local.json | 프로젝트 (로컬) | .gitignore 권장 |
~/.claude/settings.json | 사용자 전체 | 해당 없음 |
팀에서 공유하고 싶은 훅(자동 포맷 등)은 .claude/settings.json에 적습니다. 개인 환경에 의존하는 설정(알림 등)은 .claude/settings.local.json에 적어 Git 관리에서 뺍니다. 설정 파일 구조 전반은 settings.json 설정을 참고하세요.
예시 1 — 위험 명령 차단
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{ "type": "command", "command": "~/.claude/hooks/guard.sh" }
]
}
]
}
}guard.sh는 표준 입력으로 실행하려는 명령을 받고, 종료 코드로 판정합니다.
#!/usr/bin/env bash
input=$(cat)
if echo "$input" | grep -qE 'rm -rf /|git push --force'; then
echo "차단됨: 되돌릴 수 없는 명령입니다." >&2
exit 2 # 0이 아닌 값 → 실행 차단
fi
exit 0종료 코드별 동작의 차이는 종료 코드로 제어에서 자세히 다룹니다.
예시 2 — 저장 후 자동 포맷
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{ "type": "command", "command": "npx prettier --write $CLAUDE_FILE_PATHS" }
]
}
]
}
}이렇게 두면 "포맷 맞춰줘"라고 매번 말할 필요가 없습니다. 규칙이 되었기 때문입니다. $CLAUDE_FILE_PATHS 같은 변수는 Hooks 환경 변수에, Edit|Write 같은 패턴은 Hooks 매처에 정리돼 있습니다.
훅 설계 원칙 4가지
1. 빠르게 끝나야 한다. 훅은 매 도구 호출마다 실행됩니다. 수 초씩 걸리면 전체 작업이 체감상 느려집니다. 오래 걸리는 처리는 비동기 실행으로 뺍니다.
2. 조용해야 한다. 정상 경로에서는 아무것도 출력하지 마세요. 출력은 곧 컨텍스트 소비입니다.
3. 실패해도 안전해야 한다. 훅 스크립트 자체에 버그가 있으면 모든 작업이 막힙니다. 차단 조건은 좁고 명확하게 씁니다.
4. 차단 이유를 알려준다. stderr에 남긴 메시지는 모델에게 전달됩니다. "왜 막혔는지"를 알려주면 다른 방법을 찾아 진행합니다.
보안상 주의할 점
훅은 자동으로 실행되므로 잘못된 설정이 프로젝트 전체에 영향을 줄 수 있습니다.
- 신뢰할 수 있는 스크립트만 씁니다. 외부에서 가져온 훅 설정은 쓰기 전에 내용을 리뷰합니다.
- 최소 권한 원칙을 지킵니다. 명령 실행 권한은 필요한 만큼만 줍니다.
- 프로젝트 훅은 Git에 커밋하기 전에 팀원과 설정 내용을 확인합니다.
- 설정을 바꾼 뒤에는 의도한 대로 동작하는지 한 번 실제로 돌려 봅니다.
훅이 동작하지 않을 때 점검 순서
- 스크립트에 실행 권한이 있는가 (
chmod +x) - 경로가 절대 경로인가 (
~는 셸에 따라 확장되지 않을 수 있음) matcher패턴이 실제 도구 이름과 맞는가- 스크립트를 터미널에서 직접 실행하면 어떻게 되는가
Hooks 코스 — 이어서 읽을 글 10편
이 글은 개요와 레퍼런스입니다. 설정 방법부터 이벤트별 실전 예까지는 아래 순서대로 읽으면 됩니다.
| 순서 | 글 | 내용 |
|---|---|---|
| 1 | Hooks 설정 방법 | /hooks 커맨드, sh 파일화, 테스트 방법 |
| 2 | SessionStart 훅 | npm install 자동 실행, 환경 초기화 |
| 3 | Stop 훅 | 완료 알림, 로그 기록 |
| 4 | PreToolUse·PostToolUse 훅 | 자동 포맷, 사전 체크 |
| 5 | 종료 코드로 제어 | 도구 실행 차단, 경고 표시 |
| 6 | Hooks 환경 변수 | 프로젝트 정보, 파일 경로 취득 |
| 7 | Hooks 매처 | 와일드카드, 패턴 지정 |
| 8 | 비동기 실행 async:true | 오래 걸리는 처리를 기다리지 않기 |
| 9 | SubagentStop 훅 | 서브에이전트 완료 시 처리 |
| 10 | UserPromptSubmit 훅 | 프롬프트 전송 시 검사·정보 주입 |
정리
- Hooks는 라이프사이클 이벤트에 따라 자동 실행되는 처리이며, 셸 명령 외에 HTTP·MCP 도구·prompt·agent 형식으로도 정의할 수 있습니다.
- CLAUDE.md의 확률론적 지시와 달리 결정론적으로 실행되므로, 확실성이 필요한 처리는 훅에 맡깁니다.
- 도구 실행을 차단할 수 있는 것은 PreToolUse뿐이고, 종료 코드와 stderr 메시지로 모델에게 이유를 알립니다.
- 빠르게, 조용하게, 좁은 조건으로 — 이 세 가지를 지키면 훅이 작업을 느리게 하거나 막는 일이 없습니다.
- 설정은 팀 공유용은
.claude/settings.json, 개인용은.claude/settings.local.json에 둡니다.
자주 묻는 질문
팀에 Claude Code를 도입하려면 실제 코드베이스에 맞춘 설계가 필요합니다.
무료 상담 신청