이 글에서는 실제 프로젝트에 Claude Code의 Hooks 기능을 도입·적용하는 구체적인 방법을 안내합니다.
설정 구조, 주요 예시, 실습 팁을 참고하여 여러분만의 AI 기반 자동화·품질관리 워크플로우를 직접 만들어볼 수 있을 것입니다.
Hooks
Hooks의 기본 개념
Hooks(훅)은 Claude Code가 도구를 사용하기 전 또는 후에 자동으로 실행시킬 명령어(스크립트, 커맨드)를 설정하는 기능입니다.
- PreToolUse: 도구(예: 파일 읽기, 코드 수정 등) 실행 ‘직전’ 필요한 작업이나 검증을 수행
- PostToolUse: 도구 실행 ‘직후’ 후처리, 테스트, 스타일링 등을 실행
이러한 Hooks은 개발 및 협업 공정의 반복적 품질관리, 자동화, 보안 등에 사용될 수 있는 강력한 기능입니다.
Claude Code에서 Hooks 적용 영역
| 구분 | 파일 위치 | 적용 범위 | 특화 용도 |
| Global (전역 설정) | ~/.claude/settings.json | 내 모든 프로젝트 | 개인 전체 워크플로우, 코딩 스타일 등 |
| Project (공통, 팀 설정) | .claude/settings.json | 해당 프로젝트(팀공유) | 팀 규칙, 프로젝트별 검증 등 |
| Project (개인, 미커밋) | .claude/settings.local.json | 해당 프로젝트(내로컬) | 나만의 디버그, 환경별 차이 관리 |
우선순위: 개인 > 프로젝트 > 전역
Hooks 작성 방법과 구조
settings.local.json 예시
json"hooks": {
"PreToolUse": [
{
"matcher": "Read|Grep",
"hooks": [
{
"type": "command",
"command": "node ./hooks/read_hook.js"
}
]
}
],
"PostToolUse": [
{
"matcher": "Write|Edit|MultiEdit",
"hooks": [
{
"type": "command",
"command": "npm run lint && npm run test"
}
]
}
]
}
- matcher: 어떤 도구 이벤트에 hook을 적용할지(도구 이름 또는 | 로 여러 개)
- command: 실제 실행될 스크립트(커맨드, Node, Bash 등)
실제 차단용 스크립트 read_hook.js
async function main() {
const chunks = [];
for await (const chunk of process.stdin) chunks.push(chunk);
const toolArgs = JSON.parse(Buffer.concat(chunks).toString());
const readPath = toolArgs.tool_input?.file_path || toolArgs.tool_input?.path || "";
if (readPath.includes('.env')) {
console.error("You cannot read the .env file");
process.exit(2); // 2 이상
}
}
main();
작동 원리: Read/Grep 도구 실행 전, .env 파일이면 강제로 차단 및 에러 메시지 전달 (Claude가 접근을 포기)
실제 Hooks 활용 시나리오
예제 1
Claude Code가 민감한 정보가 들어있는 .env에 접근하지 못하도록 막으려고 한다.
- 민감 파일 접근을 차단하려면 작업 전 사전 차단이 필요하므로 PreToolUse hook를 사용해야 한다.
- 감시하고 싶은 도구의 호출 유형은 파일 읽기(Read)다. Claude Code가 파일을 읽으려고 할 때 Hook이 동적하도록 설정해야 한다.
- Hook 스크립트로 ".env 파일 읽기 시도를 할 경우 에러를 리턴"하게 만든다.
- Claude Code를 종료했다가 다시 실행시킨다.
- 추가로 에러 메시지를 반영하여 Claude Code가 파일 읽기를 중단하고 사용자에게 "접근이 차단되었습니다." 같은 메시지를 보여주게 한다.
위의 Hooks 작성 방법과 구조에 해당 예시 시나리오의 코드를 작성했습니다.

이렇게 .env 파일을 읽으려고 하면 hook에 의해 차단되는 것을 확인할 수 있습니다.
예제 2
함수의 정의를 수정해서 다른 코드에서 타입오류가 난 상황, tsc --noEmit를 통해서 에러가 나는 곳을 찾아서 자동으로 Claude에게 피드백을 할 수 있게 한다.
- 전역에 PostToolUse Hook을 설정 한다.
- Claude Code에서 일어나는 모든 편집(Write/Edit/MultiEdit) 후마다 tsc --noEmit 명령어를 자동으로 실행시킨다.
- 타입 에러가 있다면 Claude에게 즉시 피드백을 해주도록 한다.
- Claude가 피드백을 받아서 타입 오류 해결을 해준다.
tsc --noEmit 는 타입스크립트 타입 에러 오류를 검증하는 커맨드인데, 다른 언어들도 이와 같이 훅을 구성할 수 있을 것입니다. 예를 들어 Python은 mypy, Go는 go vet, Rust는 cargo check, Java는 javac -Xlint 같은 명령어를 활용해 PostToolUse Hook을 구성할 수 있습니다.
예제 3
Claude가 코드를 작성할 때, 이미 구현된 함수나 쿼리가 있어도 기존 것을 재사용하지 않고 중복된 기능을 새롭게 만드는 일이 종종 발생한다. 이를 방지하기 위해 코드 자동 리뷰 프로세스 Hook을 도입하여 중복 쿼리 생성을 차단할 수 있다.
- 추가 생성을 막고 싶은 디렉터리에 Write/Edit/MultiEdit 작업 발생 시 PreToolUse Hook을 추가한다.
- Hook 스크립트에서는 생성되거나 변경된 파일의 내용을, 리뷰 목적으로 별도의 Claude Code 인스턴스에 전달하여, 기존 디렉터리 내 다른 함수와의 중복 또는 유사성을 분석하도록 지시한다.
- Claude 리뷰 결과에서 중복 혹은 유사 여부를 파악한다.
- 중복 시 Claude 메인 인스턴스에게 피드백을 전달하여 적절히 기존 함수 사용을 지시하거나 코드 수정을 진행할 수 있도록 한다.
settings.local.json 에는 파일이 쓰여지거나 수정될 때, query_hook.js를 실행하도록 아래 코드와 같이 Hook을 설정해줍니다.
"PreToolUse": [
{
"matcher": "Write|Edit|MultiEdit",
"hooks": [
{
"type": "command",
"command": "node /home/dkms6/claude/queries/hooks/query_hook.js",
"timeout": 300
}
]
},
]
query_hook.js에는 이미 프로젝트 내에 유사(중복) 쿼리가 있는데 또 생성하려고 하면 “지금 이거 추가/수정 막아야 함!” 이런식으로 메인 Claude Code 인스턴스에게 알려야 하는 별도의 Claude Code 인스턴스를 활용해서 분석해야 합니다.
아래와 같은 코드로 메인 Claude Code 인스턴스를 중지하지 않고,별도의 프롬프트 세션(서브 인스턴스)을 실시간으로 생성해 Claude Code가 코드 리뷰(중복 검사 등) 역할을 하도록 할 수 있습니다.
const messages = [];
for await (const message of query({
prompt,
abortController: new AbortController(),
})) {
messages.push(message);
}
이러한 방식은 상대적으로 리소스를 많이 소비할 수 있지만, 중복 코드 생성 예방 기능과 유지보수성이 향상됩니다. 따라서 모든 디렉터리를 감시하는 것이 아닌, query_hook.js 내에서 핵심 디렉터리만 Hook으로 감시할 수 있도록 설정하는 것도 중요합니다.
권장사항
- 훅에 사용되는 스크립트는 절대 경로를 사용하는 것이 권장된다고 합니다. 하지만 이러면 협업에서 불편이 생길 수 있습니다. (나의 절대경로와 팀원의 절대경로는 다를 것이기 때문이다.)
- 따라서 템플릿 설정 파일(팀원 공유 파일)을 미리 준비하여 command 경로 지정에 $PWD(현재 디렉터리 변수)를 사용해서 settings.local.json 파일을 생성하도록 합니다.
- 이 PWD 변수는 init-claude.js 과정에서 저장되도록 하고, npm run setup 명령어로 본인 PC의 경로에 맞는 settings,local.json을 만들게 할 수 있습니다.
Claude Code의 다양한 Hooks 활용
PreToolUse와 PostToolUse 말고도 다양한 Hook의 종류가 있습니다.
| Hook 이름 | 실행 시점/의미 | 주요 용도 설명 |
| PreToolUse | 도구 실행 "직전" | 실행 전 검사·차단·로깅 |
| PostToolUse | 도구 실행 "직후" | 실행 후 자동화(포매팅, 테스트 등), 로그, 피드백 |
| Notification | 권한 필요, 60초 유휴 등 알림 이벤트 발생 시 | 알림과 관련된 자동화/로깅 |
| Stop | (한) 응답이 마무리된 직후 | 대화/세션 종료 후 후처리, 최종 저장, 클린업 등 |
| SubagentStop | 서브 에이전트(작업 단위) 실행 완료 시 | 개별 작업 단위별 후처리, 리포트 등 |
| PreCompact | 대화 압축(요약) 작업이 있기 "직전" | 대화 로그 저장, 스냅샷 등 |
또한 같은 "후크"라도(PreToolUse, PostToolUse 등) 어떤 도구(TodoWrite, Read, Write, ...), 어떤 이벤트(Stop, Notification 등)에 따라 stdin으로 넘어오는 JSON 입력의 구조가 완전히 달라집니다.
따라서 Hook을 처음 작성하거나 새로운 matcher(도구/이벤트)에 Hook을 붙인 경우, stdin으로 어떤 JSON 구조가 들어오는지 파악하려면
"PostToolUse": [
{
"matcher": "*",
"hooks": [
{
"type": "command",
"command": "jq . > post-log.json"
}
]
}
],
위와 같이 Hook이 실행될 때마다 stdin으로 전달된 전체 JSON 입력을 post-log.json 에 저장하여, 어떤 구조인지 확인할 수 있습니다.
Claude Code SDK
Claude Code SDK는 특정 프로그램이나 스크립트에서 Claude Code를 코드로 직접 제어할 수 있도록 해 주는 개발자 도구입니다. JavaScript, Python, CLI 등 다양한 환경에서 터미널에서 쓰는 것과 거의 똑같이 Claude Code의 기능을 사용할 수 있습니다.
기본 사용 예시(TypeScript)
import { query } from "@anthropic-ai/claude-code";
const prompt = "";
for await (const message of query({
prompt,
})) {
console.log(JSON.stringify(message, null, 2));
}
하지만 SDK는 기본적으로 읽기 권한만 있는데, 쓰기 권한을 부여하는 등 도구에 대한 권한을 부여하고 싶다면, allowedTools에 사용이 필요한 도구 이름("Edit", "Write", "MultiEdit", "Read", "Grep", "Search" 등)을 배열로 지정합니다.
for await (const message of query({
prompt,
options: {
allowedTools: ["Edit"]
},
})) {
console.log(JSON.stringify(message, null, 2));
}
이렇게 하면 Claude Code는 쓰기 권한이 생겨서 파일을 직접 수정할 수도 있게 됩니다.
'AI > Claude' 카테고리의 다른 글
| Claude Code 실전 활용법 1 (3) | 2025.08.05 |
|---|---|
| 최고의 AI 파트너, Claude Code (4) | 2025.08.04 |