CPN 한국어 자습서 · Claude Code in Action
3 · 훅과 SDK
Another useful hook
PreToolUse·PostToolUse 말고도 훅 이벤트는 더 있습니다. 그런데 훅마다 들어오는 입력(stdin)의 구조가 달라 훅을 짜기 까다롭습니다. 이번엔 그 입력을 파일로 그대로 찍어 들여다보는 디버깅 도우미 훅을 봅니다.
Stephen Grider · Anthropic 기술 스태프
이 코스에서 다룬 PreToolUse·PostToolUse 말고도 훅은 더 있습니다. Notification은 Claude Code가 알림을 보낼 때 — 즉 도구를 쓸 권한이 필요하거나, Claude Code가 60초간 멈춰 있을 때 — 실행됩니다. Stop은 Claude Code가 응답을 마쳤을 때 실행됩니다. SubagentStop은 서브에이전트(UI에서 Task로 표시됩니다)가 끝났을 때 실행됩니다. PreCompact는 수동이든 자동이든 압축(compact) 작업 직전에 실행됩니다. UserPromptSubmit은 사용자가 프롬프트를 제출했을 때, Claude가 처리하기 전에 실행됩니다. SessionStart는 세션을 시작하거나 재개할 때, SessionEnd는 세션이 끝날 때 실행됩니다.
그런데 여기서 헷갈리는 부분이 있습니다. 첫째, 여러분 명령으로 들어오는 stdin 입력은 실행되는 훅의 종류(PreToolUse·PostToolUse·Notification 등)에 따라 달라집니다. 둘째, 그 안에 든 tool_input은 호출된 도구에 따라 또 달라집니다(PreToolUse·PostToolUse 훅의 경우).
예를 들어, TodoWrite 도구 사용을 지켜보던 PostToolUse 훅에 들어오는 stdin은 session_id·transcript_path·hook_event_name·tool_name(TodoWrite)·tool_input(todos 배열)·tool_response(oldTodos·newTodos)를 담습니다. 참고로 TodoWrite는 Claude가 할 일 목록을 관리할 때 쓰는 도구입니다.
비교를 위해 Stop 훅에 들어오는 입력을 보면 session_id·transcript_path·hook_event_name(Stop)·stop_hook_active 정도로 훨씬 단출합니다.
보다시피 명령으로 들어오는 stdin 입력은 훅(PreToolUse·PostToolUse·Stop 등)에 따라, 그리고 매처(PreToolUse·PostToolUse의 경우)에 따라 크게 달라집니다. 그래서 입력의 정확한 구조를 모르면 훅을 짜기가 까다롭습니다.
이 문제를 다루려면 이런 도우미 훅을 하나 만들어 두면 좋습니다. 매처를 *(전부)로 두고, 명령으로 jq . > post-log.json을 줍니다. 이 명령은 훅에 들어온 입력을 post-log.json 파일에 그대로 써 줍니다. 그러면 내 명령에 정확히 무엇이 들어올지 직접 확인할 수 있습니다. 내 명령이 어떤 데이터를 들여다봐야 하는지 파악하기가 훨씬 쉬워집니다.
이 장에서 배우는 것What you'll learn
약 6분PreToolUse·PostToolUse 외에 여러 훅 이벤트가 더 있다
Notification · Stop · SubagentStop · PreCompact
UserPromptSubmit · SessionStart · SessionEnd
헷갈리는 점: stdin 입력 구조가 훅마다 다르다
그 안의 tool_input은 호출된 도구에 따라 또 다르다
도우미 훅 jq . > post-log.json으로 입력을 그대로 찍어 본다
이 코스에서 다룬 PreToolUse·PostToolUse는 일부일 뿐입니다. 훅이 발동하는 시점은 더 많습니다. 각 이벤트는 워크플로의 다른 길목을 잡아 줍니다.
Notification(권한 필요·60초 유휴) · Stop(응답 종료) · SubagentStop(Task 종료) · PreCompact(압축 직전) · UserPromptSubmit(프롬프트 제출 직후, 처리 전) · SessionStart/SessionEnd(세션 시작·재개·종료).
훅을 짜기 까다로운 이유가 둘 있습니다. (1) 명령으로 들어오는 stdin 입력은 훅 종류에 따라 달라집니다. (2) 그 안의 tool_input은 호출된 도구에 따라 또 달라집니다(PreToolUse·PostToolUse의 경우).
같은 일을 하는 훅이라도 이벤트가 다르면 입력도 다릅니다. PostToolUse엔 tool_input·tool_response가 있지만 Stop엔 없습니다 — 그래서 실제 입력을 한 번 찍어 보는 게 확실합니다.
정확한 입력 구조를 모를 때 가장 확실한 방법은 직접 찍어 보는 것입니다. 매처를 *로 두고 명령에 jq . > post-log.json을 주면, 훅에 들어온 입력이 파일에 그대로 저장됩니다.
// .claude/settings.json — 들어오는 입력을 그대로 파일에 찍는 도우미 훅 { "hooks": { "PostToolUse": [ // 또는 "PreToolUse", "Stop" 등 { "matcher": "*", // 전부 "hooks": [ { "type": "command", "command": "jq . > post-log.json" } ] } ] } }
훅이 한 번 돌면 post-log.json에 입력이 그대로 들어 있습니다. 이걸 열어 내 명령이 무엇을 받게 될지 확인합니다.
# 훅이 한 번 돌고 나면 post-log.json에 입력이 그대로 들어 있다. # 이걸 열어 보면 내 명령이 무엇을 받게 될지 정확히 알 수 있다: { "session_id": "9ec122fa-...", "transcript_path": "<path_to_transcript>", "hook_event_name": "PostToolUse", "tool_name": "TodoWrite", "tool_input": { "todos": [ ... ] }, # 도구마다 모양이 다름 "tool_response": { "newTodos": [ ... ] } }
한 번 찍어 구조를 파악한 뒤, 그 모양에 맞춰 진짜 처리 로직을 작성하면 됩니다. PreToolUse·Stop 등 다른 이벤트도 같은 방식으로 들여다볼 수 있습니다.
PreToolUse·PostToolUse 말고도 여러 가지가 있다.tool_input은 도구마다 다르다.jq . > post-log.json 같은 도우미 훅으로 입력을 찍어 본다.Q1훅을 짜기 까다로운 이유로 맞는 것은?
stdin은 훅 종류(PreToolUse·Stop 등)에 따라, 그 안의 tool_input은 호출된 도구에 따라 달라집니다.
Q2jq . > post-log.json 도우미 훅은 무엇을 하나요?
들어온 입력을 post-log.json에 써 두면, 내 명령이 무엇을 받게 될지 정확히 확인할 수 있습니다.
Q3Stop 훅이 발동하는 시점은?
Stop은 응답이 끝난 시점, UserPromptSubmit은 제출 직후(처리 전)입니다.
중복 쿼리 훅이 띄웠던 "또 다른 Claude" — 그 정체가 바로 SDK입니다. 다음 레슨에서 Claude Code를 프로그램에서 호출해 봅니다. → Claude Code SDK
전 코스는 계속 무료입니다. 등록하면 이 코스의 남은 16개 레슨을 끝까지 읽을 수 있습니다.
이미 등록하셨다면 그때 쓰신 이메일을 넣어 주세요.