Recent Posts
Recent Comments
반응형
«   2025/11   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30
Archives
Today
Total
관리 메뉴

오늘도 공부

Claude Code — Hooks를 활용한 턴 종료 시점 품질 검증 본문

AI/Claude code

Claude Code — Hooks를 활용한 턴 종료 시점 품질 검증

행복한 수지아빠 2025. 11. 3. 10:47
반응형

 

 

CodeDeck - 개발자를 위한 코드 학습 카드 뉴스

프로그래밍 언어와 프레임워크를 카드 뉴스 형태로 쉽게 배우는 개발자 학습 플랫폼

www.codedeck.kr

 

Claude Code의 잘 알려지지 않은 hooks 기능을 활용하여 각 턴이 끝날 때마다 자동으로 품질 검사를 실행하고 귀중한 시간을 절약하는 방법을 알아봅니다.

핵심 요약

  • Stop hook을 사용하여 각 턴 종료 시점에 결정론적이고 자동화된 품질 검사를 실행합니다
  • 가벼운 PostToolUse hook과 after-write.sh를 조합하여 편집 후 즉각적인 포맷팅이나 빠른 검증을 수행합니다
  • .claude/settings.json에서 after-write.sh를 PostToolUse에, 강력한 end-of-turn-check.sh를 Stop에 연결하여 설치, 코드 품질 검사(Biome), 조건부 E2E 테스트(Playwright)를 실행합니다
  • matcher를 사용하여 hook을 안전하고 빠르게, 범위를 제한적으로 유지하며, 중요한 실패 시 exit code 2를 사용하여 계속 진행을 차단합니다

왜 중요한가?

매번 AI 어시스턴트가 코드를 편집한 후 수동으로 검사를 실행하는 것은 느리고 오류가 발생하기 쉽습니다. Claude Code hooks를 사용하면 모델이 체크리스트를 기억하도록 의존하지 않고도 "항상 실행" 품질 게이트를 강제할 수 있습니다.

Stop 이벤트는 턴 종료 시점의 검증에 이상적입니다:

  • 린팅
  • 타입 체크
  • 테스트
  • 리포지토리별 가드레일

이를 통해 턴 사이에 작업 트리가 더 안전하게 유지되고 피드백이 즉각적으로 이루어집니다.

사전 준비사항

이 튜토리얼에서는 이미 hooks가 활성화된 리포지토리를 가정합니다:

.claude/settings.json          # 이벤트를 스크립트에 연결
.claude/hooks/after-write.sh   # write/edit 도구 호출 직후 실행
.claude/hooks/end-of-turn-check.sh  # 턴 종료 시(Stop) 실행

핵심 개념 및 아키텍처

Hook 이벤트 종류

  • PreToolUse: 도구 실행 전 게이트
  • PostToolUse: 도구 실행 후
  • Stop: 턴 종료 시점
  • SessionStart/End: 세션 시작/종료
  • UserPromptSubmit: 사용자 프롬프트 제출 시
  • SubagentStop: 서브에이전트 중지 시
  • PreCompact: 컴팩트 전

Matchers

특정 도구나 이벤트에만 hook을 적용하도록 범위를 지정합니다.

예: "Write|Edit" - 파일 쓰기/편집 시에만 실행

Hook 스크립트

환경 변수와 함께 실행되는 간단한 셸 명령입니다. 가능한 한 멱등성을 유지하고 빠르게 유지하세요.

실행 결과

  • 일반 종료 코드 사용
  • exit code 2: 차단 오류로 처리됨
  • stderr 내용은 Claude에게 전달되어 자동 후속 조치가 가능합니다

단계별 가이드

1. .claude/settings.json에서 hooks 연결

{
  "hooks": {
    "PostToolUse": [
      { 
        "matcher": "Write|Edit", 
        "hooks": [
          { 
            "type": "command", 
            "command": ".claude/hooks/after-write.sh" 
          }
        ]
      }
    ],
    "Stop": [
      { 
        "matcher": "*", 
        "hooks": [
          { 
            "type": "command", 
            "command": ".claude/hooks/end-of-turn-check.sh" 
          }
        ]
      }
    ]
  }
}

2. after-write hook을 빠르게 유지

#!/usr/bin/env bash
set -euo pipefail

# 필요시 언어별 빠른 포맷터 추가
echo "After-write: file changes applied." >&2

# 예: Prettier 실행 (선택사항)
# prettier -w "**/*.{ts,tsx,js,jsx,json,md}" || true

용도:

  • 포맷팅
  • import 정렬
  • 빠른 린팅

주의사항:

  • 무거운 I/O 작업 피하기
  • 더 깊은 검사는 Stop hook으로 연기

3. 강력한 Stop hook 구현

실용적인 Stop 스크립트는 리포지토리별 검사를 안정적으로 실행하고 문제 발생 시 명확하게 실패합니다.

#!/bin/bash
set -e

kill_port() { 
  local p=$1
  local pid=$(lsof -ti:$p 2>/dev/null || true)
  [ -n "$pid" ] && kill -9 "$pid" || true
}

# TSX 파일이 변경되었으면 Playwright E2E 실행
if git diff --name-only HEAD 2>/dev/null | grep -q '\\.tsx$' || \
   git ls-files --others --exclude-standard | grep -q '\\.tsx$'; then
  kill_port 3000
  kill_port 1080
  kill_port 1025
  pnpm test:e2e
  kill_port 3000
  kill_port 1080
  kill_port 1025
fi

# 항상 의존성 및 타입 체크 실행
pnpm install
pnpm check

이 예제의 핵심:

  • maildev(가짜 메일박스 서비스)가 사용하는 포트를 정리
  • .tsx 파일 변경 시에만 E2E 테스트 실행 (조건부)
  • 항상 의존성 설치 및 코드 품질 검사 실행

4. 스크립트를 실행 가능하게 만들기

chmod +x .claude/hooks/after-write.sh .claude/hooks/end-of-turn-check.sh

5. 동작 확인

  • 파일 편집 트리거: after-write 메시지 확인
  • 턴 종료: 설치/검사가 실행되는지 확인
  • 의도적 실패: 즉시 표면화되는지 확인

6. 중요한 실패 시 차단 (선택사항)

if ! pnpm check; then
  echo "타입 체크 실패. 다음 단계 전에 수정 중..." >&2
  exit 2
fi

exit code 2를 반환하면:

  • 계속 진행 차단
  • 에러를 Claude에게 피드백
  • Claude가 자동으로 복구 시도

실제 예제

기본 예제

# .claude/hooks/after-write.sh
prettier -w "**/*.{ts,tsx,js,jsx,json,md}" || true

# .claude/hooks/end-of-turn-check.sh
set -e
pnpm install
pnpm check || { echo "check failed" >&2; exit 2; }

Next.js 프로젝트 예제

.tsx 파일 변경 시에만 Playwright를 조건부로 실행하고 충돌하는 포트를 먼저 정리합니다:

kill_port 3000; kill_port 1080; kill_port 1025
pnpm test:e2e || { echo "e2e failed" >&2; exit 2; }
kill_port 3000; kill_port 1080; kill_port 1025

: UI E2E는 Stop으로 연기하고 PostToolUse는 즉각적으로 유지하세요. 피드백 속도와 커버리지 간의 균형을 맞춥니다.

pnpm check의 역할

이 리포지토리에서 pnpm check가 하는 일:

// package.json (scripts)
{
  "check": "biome check --write .",
  "check:ci": "biome ci app components config emails lib scripts styles tests .github package.json biome.json tsconfig.json"
}

기능:

  • Biome의 포맷터, 린터, import 정렬을 지원되는 파일 전체에 실행
  • --write 옵션으로 안전한 문제를 디스크에서 자동 수정
  • 간격 및 따옴표 수정, import 정렬, 사용하지 않는 변수 및 일반적인 정확성/스타일 문제 플래그
  • 차단 실패 시 0이 아닌 종료 코드 반환

참고:

  • biome ci는 읽기 전용이며 파이프라인에 적합
  • 로컬에서는 check로 자동 수정 사용
  • CI에서는 check:ci를 엄격하게 유지하여 회귀 방지

Biome 설정 (biome.json)

기본 설정으로도 합리적인 결과가 나옵니다. 포맷팅, 린트 규칙, 무시할 경로를 조정하려면 추가하세요:

{
  "$schema": "./node_modules/@biomejs/biome/configuration_schema.json",
  "formatter": {
    "enabled": true,
    "indentStyle": "space",
    "indentWidth": 2,
    "lineWidth": 100
  },
  "linter": {
    "enabled": true,
    "rules": {
      "correctness": {
        "noUnusedVariables": "error"
      },
      "style": {
        "useConst": "warn",
        "noVar": "error"
      }
    }
  },
  "files": {
    "ignore": ["node_modules", ".next", "coverage", "dist", "build"]
  }
}

주요 사항:

  • Formatter: 줄 너비 및 들여쓰기 설정; Biome은 TS/JS/JSON/MD 등에 일관된 포맷팅 적용
  • Linter: 핵심 규칙 활성화; 기준에 따라 심각도 조정
  • Files: 일반적인 빌드 아티팩트 무시; Biome은 기본적으로 node_modules 무시
  • Import 정렬: biome check는 import 정렬도 수행

성능, 확장성 및 보안

성능

  • PostToolUse는 빠르게 유지
  • 더 무거운 검사는 Stop으로 예약
  • matcher로 범위 지정하여 불필요한 실행 방지
  • 안전한 경우 캐싱 사용

보안

  • Hook은 사용자 자격 증명으로 실행 — CI 스크립트처럼 취급
  • 검토, 버전 관리, 부작용 제한
  • 중요한 문제에는 명시적 실패 선호: Stop이 exit 2를 반환하여 어시스턴트가 자동 복구

일반적인 함정 및 디버깅 팁

  1. 실행 불가능: 항상 chmod +x 수행
  2. 잘못된 경로: 명령은 워크스페이스 기준으로 실행 — 리포지토리 상대 경로 사용
  3. 과도한 검사: 파일 타입 휴리스틱(예: .tsx만) 사용하여 Stop 빠르게 유지
  4. 포트 충돌: E2E 실행 전후로 서버를 사전에 종료

대안 및 트레이드오프

Hook 타입 용도 장점

PreToolUse 도구 실행 전 엄격한 게이팅 권한 부여나 비용이 많이 드는 작업 방지에 최적
PostToolUse 도구 호출 후 즉각적인 피드백 포맷터 및 빠른 검증에 적합
Stop 턴 종료 시점 품질 게이트 설치, 코드 품질 검사, 테스트, 상태 요약에 최적
Git hooks/CI Claude hooks 보완 비대화형 안전을 위해 CI에서 중요한 검사 복제 유지

결론 및 다음 단계

턴 종료 시점 hook은 "X를 실행하는 것을 기억하세요"를 자동화된 반복 가능한 정책으로 전환합니다.

시작하기

  1. 가벼운 after-write hook으로 시작
  2. Stop 스크립트를 확장하여 설치, 검사, 타겟 E2E 커버
  3. 빠르고, 범위가 지정되고, 안전하게 유지
  4. 실패가 중요한 경우 exit 2 사용하여 Claude가 즉시 문제 수정

핵심 포인트

  • 자동화: 수동 검사 불필요
  • 일관성: 항상 같은 품질 기준 적용
  • 피드백 루프: 즉각적인 오류 감지 및 수정
  • 생산성: AI와 협업 시 안심하고 작업

참고 자료


작성 일자: 2025년 11월 3일
원문: Claude Code — Use Hooks to Enforce End-of-Turn Quality Gates

반응형