Notice
Recent Posts
Recent Comments
반응형
오늘도 공부
Claude Code 훅(Hook) 완벽 가이드: 개발 워크플로우를 자동화하는 11가지 방법 본문
반응형
Claude Code는 AI 기반 코딩 어시스턴트로, 다양한 훅(Hook) 이벤트를 통해 개발 프로세스를 세밀하게 제어할 수 있습니다. 이 글에서는 각 훅의 용도와 실제 활용 예제를 상세히 살펴보겠습니다.
훅(Hook)이란?
훅은 Claude Code의 실행 흐름에서 특정 시점에 발생하는 이벤트입니다. 각 훅에서 커스텀 로직을 실행하여 프롬프트 강화, 권한 관리, 보안 정책 적용 등을 자동화할 수 있습니다.
1. SessionStart - 세션 초기화
핵심 질문: 초기 컨텍스트나 환경 설정이 필요한가?
용도:
- 프로젝트 컨텍스트 로드
- 환경 변수 설정
- 시작 스크립트 실행
실제 예제:
# .claude/hooks/session_start.py
def on_session_start():
"""세션 시작 시 프로젝트 환경 설정"""
# 1. 프로젝트 README 자동 로드
with open('README.md', 'r') as f:
context = f.read()
# 2. 코딩 스타일 가이드 주입
style_guide = """
이 프로젝트의 코딩 규칙:
- Flutter Clean Architecture 패턴 사용
- Riverpod 2.0+ 상태관리
- 한국어 주석 필수
- 테스트 커버리지 80% 이상 유지
"""
# 3. 현재 브랜치 정보
import subprocess
branch = subprocess.check_output(['git', 'branch', '--show-current']).decode().strip()
return {
'project_context': context,
'style_guide': style_guide,
'current_branch': branch
}
2. UserPromptSubmit - 프롬프트 전처리
핵심 질문: 사용자 프롬프트에 컨텍스트를 추가하거나 검증이 필요한가?
용도:
- 프롬프트에 추가 정보 자동 삽입
- 부적절한 요청 차단
- 프롬프트 로깅
실제 예제:
# .claude/hooks/user_prompt_submit.py
def on_user_prompt_submit(prompt):
"""프롬프트 제출 전 검증 및 강화"""
# 1. 금지된 키워드 체크
forbidden_keywords = ['production_api_key', 'delete_database']
if any(keyword in prompt.lower() for keyword in forbidden_keywords):
return {
'block': True,
'reason': '위험한 작업이 감지되었습니다.'
}
# 2. 컨텍스트 자동 추가
enhanced_prompt = f"""
{prompt}
[추가 컨텍스트]
- 현재 작업 중인 기능: 블록체인 지갑 연동
- 기술 스택: Flutter 3.24 + Riverpod + Web3dart
- 테스트 필수: 모든 public 메서드에 단위 테스트 작성
"""
# 3. 프롬프트 로깅
log_prompt(prompt, enhanced_prompt)
return {'enhanced_prompt': enhanced_prompt}
3. PermissionRequest - 권한 자동화
핵심 질문: 이 권한 요청을 자동으로 승인/거부해야 하나?
용도:
- 파일 접근 권한 자동 관리
- API 호출 승인
- 감사 로그 작성
실제 예제:
# .claude/hooks/permission_request.py
def on_permission_request(request):
"""권한 요청 자동 처리"""
# 1. 읽기 전용 파일은 자동 승인
if request['type'] == 'file_read':
safe_extensions = ['.dart', '.json', '.yaml', '.md']
if any(request['path'].endswith(ext) for ext in safe_extensions):
return {'approve': True, 'log': True}
# 2. 민감한 파일 접근은 자동 거부
sensitive_paths = ['.env', 'secrets/', 'private_keys/']
if any(path in request['path'] for path in sensitive_paths):
return {
'deny': True,
'reason': '민감한 파일 접근이 차단되었습니다.',
'notify_user': True
}
# 3. 파일 쓰기는 백업 후 승인
if request['type'] == 'file_write':
backup_file(request['path'])
return {'approve': True, 'backup_created': True}
# 4. 그 외는 사용자에게 확인 요청
return {'require_user_confirmation': True}
4. PreToolUse - 도구 실행 전 제어
핵심 질문: 도구 실행을 허용, 수정 또는 차단해야 하나?
용도:
- 위험한 명령어 차단
- 파라미터 자동 수정
- 보안 정책 적용
실제 예제:
# .claude/hooks/pre_tool_use.py
def on_pre_tool_use(tool_name, parameters):
"""도구 사용 전 보안 검증"""
# 1. 위험한 쉘 명령어 차단
if tool_name == 'bash':
dangerous_commands = ['rm -rf', 'sudo', 'chmod 777', 'dd if=']
if any(cmd in parameters['command'] for cmd in dangerous_commands):
return {
'block': True,
'reason': '위험한 명령어가 감지되었습니다.',
'alternative': '안전한 대안을 제안합니다.'
}
# 2. API 호출 시 rate limit 체크
if tool_name == 'api_call':
if not check_rate_limit(parameters['endpoint']):
return {
'block': True,
'reason': 'API rate limit 초과',
'retry_after': 60
}
# 3. 파일 경로 자동 수정
if tool_name == 'file_write':
if not parameters['path'].startswith('safe_directory/'):
parameters['path'] = f"safe_directory/{parameters['path']}"
return {
'modify': True,
'modified_parameters': parameters,
'reason': '안전한 디렉토리로 경로 수정'
}
return {'allow': True}
5. PostToolUse - 도구 실행 후 처리
핵심 질문: 결과를 검증하거나 후처리가 필요한가?
용도:
- 코드 포맷팅 자동 실행
- 린터 실행
- 실행 결과 피드백
실제 예제:
# .claude/hooks/post_tool_use.py
def on_post_tool_use(tool_name, result):
"""도구 실행 후 자동 처리"""
# 1. Dart 파일 생성 시 자동 포맷팅
if tool_name == 'create_file' and result['path'].endswith('.dart'):
import subprocess
subprocess.run(['dart', 'format', result['path']])
# 린트 체크
lint_result = subprocess.run(
['dart', 'analyze', result['path']],
capture_output=True
)
if lint_result.returncode != 0:
return {
'warning': '린트 오류가 발견되었습니다.',
'lint_output': lint_result.stderr.decode(),
'suggest_fix': True
}
# 2. 테스트 파일 생성 시 자동 실행
if tool_name == 'create_file' and '_test.dart' in result['path']:
test_result = subprocess.run(
['flutter', 'test', result['path']],
capture_output=True
)
return {
'test_passed': test_result.returncode == 0,
'test_output': test_result.stdout.decode()
}
# 3. Git 커밋 자동 생성
if tool_name == 'file_write':
subprocess.run(['git', 'add', result['path']])
return {'git_staged': True}
6. Notification - 알림 커스터마이징
핵심 질문: 사용자에게 어떤 방식으로 알림을 보낼까?
용도:
- 데스크톱 알림
- 로그 기록
- Slack/Discord 메시지 전송
실제 예제:
# .claude/hooks/notification.py
def on_notification(notification_type, message):
"""커스텀 알림 처리"""
# 1. 중요 이벤트는 Slack으로 전송
if notification_type in ['error', 'security_alert']:
send_slack_message(
channel='#dev-alerts',
message=f"🚨 Claude Code Alert: {message}",
priority='high'
)
# 2. 작업 완료 시 데스크톱 알림
if notification_type == 'task_complete':
from plyer import notification
notification.notify(
title='Claude Code',
message=message,
app_name='Claude Code',
timeout=10
)
# 3. 모든 알림 로깅
with open('.claude/logs/notifications.log', 'a') as f:
timestamp = datetime.now().isoformat()
f.write(f"[{timestamp}] {notification_type}: {message}\n")
7. Stop - 작업 완료 검증
핵심 질문: Claude가 작업을 완료했나, 아니면 계속해야 하나?
용도:
- 작업 완료 검증
- 에러 체크
- 추가 작업 강제
실제 예제:
# .claude/hooks/stop.py
def on_stop(task_context):
"""작업 완료 검증 및 후처리"""
# 1. 필수 파일 생성 체크
required_files = ['main.dart', 'test/main_test.dart', 'README.md']
missing_files = [f for f in required_files if not os.path.exists(f)]
if missing_files:
return {
'continue': True,
'reason': f'필수 파일이 누락되었습니다: {", ".join(missing_files)}',
'additional_prompt': f'다음 파일들을 생성해주세요: {", ".join(missing_files)}'
}
# 2. 테스트 통과 확인
test_result = subprocess.run(['flutter', 'test'], capture_output=True)
if test_result.returncode != 0:
return {
'continue': True,
'reason': '테스트가 실패했습니다.',
'error_output': test_result.stderr.decode()
}
# 3. 코드 품질 체크
analyze_result = subprocess.run(['dart', 'analyze'], capture_output=True)
if 'error' in analyze_result.stdout.decode().lower():
return {
'continue': True,
'reason': '코드 분석에서 오류가 발견되었습니다.'
}
# 4. 모든 검증 통과
return {
'complete': True,
'summary': generate_task_summary(task_context),
'metrics': {
'files_created': len(task_context['created_files']),
'test_coverage': calculate_coverage(),
'duration': task_context['duration']
}
}
8. SubagentStop - 서브에이전트 검증
핵심 질문: 서브에이전트가 작업을 완료했나?
용도:
- 병렬 작업 검증
- 서브태스크 완료 확인
- 의존성 체크
실제 예제:
# .claude/hooks/subagent_stop.py
def on_subagent_stop(subagent_id, task_result):
"""서브에이전트 작업 검증"""
# 1. UI 컴포넌트 서브에이전트
if subagent_id == 'ui_builder':
if not os.path.exists('lib/presentation/screens/'):
return {
'continue': True,
'reason': 'UI 화면 파일이 생성되지 않았습니다.'
}
# 2. API 연동 서브에이전트
if subagent_id == 'api_integrator':
# API 테스트 실행
api_test_passed = run_api_tests()
if not api_test_passed:
return {
'continue': True,
'reason': 'API 연동 테스트 실패',
'retry_count': task_result.get('retry_count', 0) + 1
}
# 3. 의존성 체크
if not validate_dependencies(subagent_id, task_result):
return {
'continue': True,
'reason': '다른 서브에이전트 작업이 완료되지 않았습니다.'
}
return {'complete': True}
9. PreCompact - 컨텍스트 압축 전 저장
핵심 질문: 컨텍스트 압축 전에 저장할 정보가 있나?
용도:
- 중요 컨텍스트 보존
- 대화 히스토리 백업
- 상태 정보 저장
실제 예제:
# .claude/hooks/pre_compact.py
def on_pre_compact(context):
"""컨텍스트 압축 전 중요 정보 보존"""
# 1. 중요 결정사항 저장
important_decisions = extract_decisions(context['conversation'])
save_to_file('.claude/decisions.json', important_decisions)
# 2. 생성된 파일 목록 보존
created_files = context.get('created_files', [])
save_to_file('.claude/file_history.json', {
'timestamp': datetime.now().isoformat(),
'files': created_files
})
# 3. 프로젝트 상태 스냅샷
project_state = {
'current_task': context.get('current_task'),
'completed_features': context.get('completed_features'),
'pending_tasks': context.get('pending_tasks'),
'git_commit': get_current_commit_hash()
}
save_to_file('.claude/state_snapshot.json', project_state)
# 4. 압축 시 유지할 핵심 정보 반환
return {
'preserve': {
'project_context': context.get('project_readme'),
'coding_standards': context.get('style_guide'),
'current_task': context.get('current_task')
}
}
10. SessionEnd - 세션 종료 처리
핵심 질문: 세션 종료 시 정리 작업이나 통계 저장이 필요한가?
용도:
- 분석 리포트 생성
- 세션 데이터 저장
- 정리 작업 실행
실제 예제:
# .claude/hooks/session_end.py
def on_session_end(session_data):
"""세션 종료 시 정리 및 리포트 생성"""
# 1. 세션 통계 생성
statistics = {
'duration': session_data['end_time'] - session_data['start_time'],
'tasks_completed': len(session_data['completed_tasks']),
'files_created': len(session_data['created_files']),
'files_modified': len(session_data['modified_files']),
'api_calls': session_data['api_call_count'],
'tokens_used': session_data['token_usage']
}
# 2. 개발 리포트 생성
report = f"""
# Claude Code 세션 리포트
생성일: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
## 세션 통계
- 작업 시간: {statistics['duration']}
- 완료 작업: {statistics['tasks_completed']}개
- 생성 파일: {statistics['files_created']}개
- 수정 파일: {statistics['files_modified']}개
## 생성된 파일
{chr(10).join(f"- {f}" for f in session_data['created_files'])}
## 다음 작업 제안
{generate_next_tasks(session_data)}
"""
with open(f".claude/reports/session_{session_data['session_id']}.md", 'w') as f:
f.write(report)
# 3. Git 커밋 자동 생성 (옵션)
if session_data.get('auto_commit', False):
subprocess.run(['git', 'add', '.'])
subprocess.run([
'git', 'commit', '-m',
f"Claude Code 세션: {statistics['tasks_completed']}개 작업 완료"
])
# 4. 임시 파일 정리
cleanup_temp_files()
# 5. 백업 생성
create_backup(session_data)
return {
'report_path': f".claude/reports/session_{session_data['session_id']}.md",
'statistics': statistics
}
실전 활용: 모바일앱 프로젝트 설정 예시
모바일 앱 개발에 최적화된 훅 설정:
# .claude/config.yaml
hooks:
session_start:
- load_project_context
- set_flutter_environment
- load_blockchain_config
user_prompt_submit:
- enhance_with_korean_context
- validate_security_prompts
- add_testing_reminder
pre_tool_use:
- check_blockchain_operations
- validate_wallet_access
- enforce_security_policies
post_tool_use:
- auto_format_dart_files
- run_unit_tests
- update_documentation
session_end:
- generate_progress_report
- backup_code
- suggest_next_tasks
project_context:
name: "Flutter App"
tech_stack:
- Flutter 3.24
- Riverpod 2.5+
- Web3dart
- Drift Database
coding_standards:
- Clean Architecture
- 한국어 주석
- 80% 테스트 커버리지
- 린트 오류 0건
마무리
Claude Code의 훅 시스템을 활용하면 반복적인 작업을 자동화하고, 코드 품질을 일관되게 유지하며, 보안을 강화할 수 있습니다. 프로젝트의 특성에 맞게 훅을 설정하여 생산성을 극대화하세요.
반응형
'AI > Claude code' 카테고리의 다른 글
| Claude Code 훅(Hook) 완벽 가이드: 개발 워크플로우 자동화 마스터하기 (0) | 2025.11.25 |
|---|---|
| 클로드 코드를 단계별로 배워보자!! (0) | 2025.11.06 |
| Claude Code 실전 활용법 (초급자용) (0) | 2025.11.06 |
| Context-Aware Claude Code: AI 코딩의 숨겨진 슈퍼파워 🚀 (0) | 2025.11.05 |
| 바이브 코딩: 초보자를 위한 완벽 가이드 (0) | 2025.11.04 |
