클로드 코드(Claude Code)에게 코드를 작성하게 하면 작동은 하지만, 포맷이 미묘하게 깨져 있는 경우가 자주 있습니다. 들여쓰기나 줄 바꿈 위치가 프로젝트의 관례와 달라 결국 나중에 수동으로 다시 정리해야 합니다. 이러한 왕복 작업이 은근히 시간을 많이 소모합니다.
이는 모델 성능의 문제가 아니라, Hooks를 통해 해결할 수 있습니다. 본문에서는 Claude Code가 파일을 편집할 때마다 Prettier로 자동 포맷하는 설정을 설정 파일과 스크립트 전문을 포함하여 공개합니다. 복사만 하면 바로 작동합니다.
Hooks란 무엇인가 (30초 만에)
Hooks는 Claude Code의 처리 과정 중 특정 지점에 사용자의 셸 커맨드를 자동으로 실행시키는 메커니즘입니다. 설정은 settings.json 파일의 hooks 섹션에 작성합니다.
- 이벤트(Event): 언제 작동할지. 여기서는 '도구가 사용된 후'인
PostToolUse를 사용합니다.
- 매처(matcher): 어떤 도구를 대상으로 할지. 여기서는
Edit|Write를 사용합니다.
- 핸들러(handler): 실행할 커맨드입니다. 표준 입력으로 JSON이 전달됩니다.
Hooks의 역할은 AI의 판단에 맡기는 것이 아니라, 정해진 규칙을 확실하게 실행시키는 것입니다. 포맷팅처럼 '매번・반드시・동일한 절차로' 수행해야 하는 작업과 궁합이 좋습니다.
완성된 형태: 설정 및 스크립트
설정 (settings.json에 추가할 조각)
프로젝트의 .claude/settings.json (또는 모든 프로젝트 공통의 ~/.claude/settings.json)의 hooks 섹션에 다음 내용을 병합합니다.
{
"hooks": {
"PostToolUse": [
...
도입 절차
- 위 설정 조각을 자신의
settings.json에 병합합니다 (이미 hooks가 있는 경우, PostToolUse 배열에 추가). - 스크립트를 프로젝트의 .claude/hooks/format-file.sh에 저장합니다. - 실행 권한을 부여합니다.
chmod +x .claude/hooks/format-file.sh
- Claude Code에서
/hooks를 실행하여 등록된 후크 목록에 표시되는지 확인합니다. - 테스트: Claude에게 JS 파일을 1줄 편집하게 한 뒤, 저장된 파일이 포맷되었는지 육안으로 확인합니다.
전제 조건은 jq와 Node.js (npx)입니다. 스크립트 내의 경로는 $CLAUDE_PROJECT_DIR (프로젝트 루트를 가리키는 환경 변수로, 후크 실행 시 Claude Code가 준비해 줍니다)을 전제로 작성되었으므로, 스크립트를 다른 위치에 둘 경우 경로를 수정해야 합니다.
작동 원리 해설
포인트는 세 가지뿐입니다.
1. 편집된 파일의 경로는 표준 입력 JSON에서 가져옵니다
후크에는 tool_input을 포함하는 JSON이 표준 입력으로 전달됩니다. 스크립트는 그 안의 tool_input.file_path를 jq로 추출하여 대상 파일에 적용합니다. 경로가 비어 있거나 파일이 존재하지 않으면 아무것도 하지 않고 종료됩니다.
2. 대상 확장자를 제한합니다
Prettier가 처리하는 확장자(js / ts / json / css / md 등)만 case 문으로 대상을 지정했습니다. 무엇이든 포맷하려 하면 의도하지 않은 파일까지 건드릴 수 있으므로, 대상을 명시적으로 제한하는 것이 안전합니다.
3. 항상 종료 코드 0으로 끝냅니다
이것이 가장 중요한 설계 판단입니다. 포맷팅은 PostToolUse (실행 후)의 후처리 과정이므로, 실패하더라도 편집 자체를 막을 이유가 없습니다. jq가 없는 환경에서는 조용히 정상 종료하고, Prettier 실행 오류도 무시합니다. '가능하면 하는' 처리와 '멈춰야 할' 처리를 혼동하지 않는 것이 후크 설계의 기본입니다.
참고로, 먼저 npx --no-install을 시도하는 이유는 프로젝트에 이미 도입된 Prettier를 우선적으로 사용하기 위함입니다. 프로젝트 측의 .prettierrc 등의 설정이 그대로 적용됩니다.
커스터마이징
대상 확장자나 포맷터는 스크립트의 case 부분을 편집하여 교체할 수 있습니다.
- Python의 경우, 대상을
*.py로 설정하고 실행 줄을 ruff format "$file_path" 또는 black "$file_path"로 지정합니다. Go의 경우, *.go를 대상으로 gofmt -w "$file_path"를 사용합니다.
자신의 프로젝트 표준 포맷터에 맞게 설정해 주세요.
문제 발생 지점 (Troubleshooting Points)
훅이 작동하지 않을 때는 보통 다음 중 하나가 원인입니다.
- 스크립트에 실행 권한(
chmod +x)을 부여하는 것을 잊음.
jq가 설치되어 있지 않음 (이 스크립트는 jq 없이는 아무것도 하지 않고 끝납니다).
- 설정 측의 스크립트 경로와 실제 배치가 일치하지 않음.
- Prettier가 프로젝트에 설치되어 있지 않음.
먼저 /hooks에서 등록되었는지 확인하는 것이 문제 해결의 지름길입니다.
참고 사항 (Hooks 전반에 대하여)
훅은 사용자의 권한으로 임의의 셸 명령을 실행하는 메커니즘입니다. 편리하지만, 내용을 이해할 수 없는 훅은 도입하지 않는 것이 좋습니다. 타인의 리포지토리를 클론했을 때는 그 .claude/settings.json에 모르는 훅이 포함되어 있는지 확인하는 습관을 가지세요. 이번 설정 역시 사용하기 전에 스크립트 내부를 한 번 읽어보시길 바랍니다.
요약
- "편집할 때마다 수동으로 정리하는 작업"은 Hooks로 제거 가능
- 후처리 계열 훅은 "항상 exit 0"이 설계의 핵심입니다
- 대상은 확장자로 명시적으로 제한합니다.
이 설정에 흥미를 느낀 분들은 Hooks의 다른 사용법(위험한 명령어 차단, 보호 파일 편집 차단, 입력 대기 알림)이나 외부 도구와 연결하는 MCP 설정도 분명 도움이 될 것입니다.
※ 본 기사는 AI를 활용하여 작성되었으며, 인간이 내용 확인 및 수정을 진행했습니다. 설정 사양은 Claude Code 공식 문서를 기반으로 하지만, 버전에 따라 변경될 수 있으므로 도입 시에는 공식 문서의 최신 정보도 확인해 주세요.
Discussion