Claude Code에 운영 서버 작업을 맡기고 있습니다. 매우 편리하지만, AI가 '이전에 사고를 쳤던 작업'을 또다시 선의로 수행하는 경우가 발생합니다.
메모리나 지시문에 '하지 마세요'라고 적어도 이를 준수할 것이라는 보장은 없습니다. 반드시 막고 싶다면, hooks를 사용해 실행 전에 기계적으로 차단해야 합니다.
이 글에서는 실제로 운영하며 사용하고 있는 3가지 hooks를 익명화하여 소개합니다. 저는 혼자 EC 사이트를 운영하면서 PHP/MySQL 관리 시스템을 Claude Code와 함께 유지보수하는 환경에 있습니다.
전제: hooks란 무엇인가요?
Claude Code가 도구를 실행하기 전후(또는 세션 시작 시)에, 사용자가 작성한 스크립트를 자동으로 실행하는 메커니즘입니다.
- 이 스크립트에는 실행하려는 명령어 등이 JSON 형태로 표준 입력으로 전달됩니다.
- 종료 코드 2로 끝나면 해당 실행은 중단되고, 표준 에러(stderr)에 작성된 내용이 Claude에게 반환됩니다. '왜 막았는지'를 설명하면 AI가 그 이유를 읽고 다른 방법을 모색합니다.
설정은 .claude/settings.json 파일에 작성합니다.
이것이 가장 효과적입니다. 과거에 실제로 사고를 일으킨 작업들만 정규 표현식(regex)을 사용해 막고 있습니다.
차단하는 항목은 다음 3가지입니다.
- 연동 인증 정보가 포함된 설정 파일을 서버에 덮어쓰는 작업 (재인증이 필요한 사고가 있었습니다)
- 손상된 CSV를 출력하는 구식 스크립트 실행
- main 브랜치로의 강제 푸시 (여러 PC에서 작업하기 때문에 최신 커밋이 사라지는 것을 방지합니다)
#!/usr/bin/env python3
import json, re, sys
sys.stderr.reconfigure(encoding='utf-8')
...
핵심 포인트는 3가지입니다.
- '모두 금지'가 아니라 '전과가 있는 것만'. 너무 광범위하게 차단하면 작업 자체가 진행되지 않습니다. - 조회만 하는 명령어는 통과시킵니다.
⚠️ Windows에서는 문자 인코딩에 주의하세요. 표준 입력은 sys.stdin.buffer.read().decode('utf-8')로 읽고, 표준 에러는 reconfigure(encoding='utf-8')를 합니다. 일본어 이유가 깨져서 AI에게 전달되지 않을 수 있습니다. - 정규 표현식 (regex)의 hook은 보안 경계가 아닙니다. 명령어 작성 방식을 바꾸면 우회할 수 있습니다. 반대로, 위에서 쓴 것처럼 문자열로 포함되는 것만으로 오탐지(誤検知)도 합니다. 어디까지나 '실수 사고'를 막는 안전 울타리입니다. - 막았다면, 회피하지 못하게 한다. 차단되었을 때 AI가 다른 방식으로 같은 작업을 시도하지 않도록 메시지에 '회피하지 말고, 이 절차로'라고 명시합니다. - hook은 너무 많이 늘리지 않는다. 사고가 발생할 때마다 하나씩 추가하는 정도가 유지보수 가능한 양입니다. 지금은 3개로 충분합니다.
요약
- '하지 마세요'라고 쓰는 것보다,
hooks를 이용해 기계적으로 막는 것이 더 확실합니다. - 막을 것은 '이전에 발생한 기록(前科のある操作)'만 합니다. 이유와 대체 절차를 AI에게 반환합니다.
- 배포 직후의 구문 검사와 시작 시의
git pull은,
별것 아니지만 효과가 있습니다. - 정규 표현식 hook은 오탐지도 하므로, '안전 울타리'로 생각하는 것이 좋습니다.
다음 시간에는 매번 설명이 없어지게 하는 '스킬과 메모리'를 만드는 방법을 작성하겠습니다.
토론 (Discussion)