
문제: AI가 규칙을 '읽었다'고 지킨 게 아니다

AI 코딩 에이전트에게 "push 전에는 반드시 검토해"라고 문서로 적어두면, 대부분의 경우 잘 지킨다. 그런데 '대부분'이 문제다. 컨텍스트가 길어지거나, 급한 작업이 끼거나, 프롬프트가 살짝 달라지면 같은 규칙도 건너뛴다. 문서는 부탁이지 강제가 아니기 때문이다.
필자는 여러 레포를 한 AI 에이전트로 관리하면서 이 경계를 마주했다. 전 시스템 공통 규칙 체계를 만들고, 그 첫 규칙 RULE-001(push 전 필수 검토)을 '문서로 부탁할지, 훅으로 막을지' 판단해야 했다. 결론부터 말하면 두 방식은 서로 다른 층위이며, 섞어 쓰되 역할을 나눠야 한다.
왜 문서만으로는 위험한가

문서 기반 규칙의 약점은 두 가지다. 첫째, 확률적이다. LLM은 지시를 따를 확률을 높일 뿐 100%를 보장하지 않는다. 둘째, 드리프트가 생긴다. 레포마다 규칙 파일을 복사해두면 시간이 지나며 내용이 조금씩 어긋난다.
드리프트 문제는 정본(source of truth)을 한 곳에 두는 방식으로 줄였다. 규칙 원본은 컨트롤 레포의 rules/GLOBAL-RULES.md 한 곳에만 두고, 관리 대상 9개 레포의 CLAUDE.md에는 임포트 한 줄만 넣는다.
@../ai-automation-control/rules/GLOBAL-RULES.md이 한 줄은 각 레포의 CLAUDE.md가 공통 규칙 파일을 그대로 끌어오게 한다. 규칙을 고칠 때 원본 한 파일만 수정하면 되므로, 레포마다 사본이 달라지는 드리프트가 원천적으로 사라진다.
하지만 임포트로 드리프트를 막아도, '읽고 따를 확률'은 여전히 100%가 아니다. 진짜 어기면 안 되는 규칙은 실행 자체를 막는 편이 안전하다.
문서로 둘 규칙과 훅으로 내릴 규칙 구분
모든 규칙을 훅으로 만들면 유지보수가 무거워지고, 반대로 전부 문서에 맡기면 강제력을 보장하지 못한다. 독자가 자기 규칙을 나눌 때 참고할 만한 기준을 정리하면 다음과 같다.
| 스타일·컨벤션 (변수명, 커밋 메시지 형식) | 낮음, 되돌리기 쉬움 | 문서(정본+임포트) |
| 권장 절차 (PR 설명 작성 등) | 중간, 사람이 보완 가능 | 문서 + 리뷰 |
| 비가역·위험 동작 (push, 배포, 삭제) | 높음, 되돌리기 어려움 | 훅으로 결정적 차단 |
실제로 첫 규칙 RULE-001(push 전 필수 검토)은 세 번째 칸에 해당한다고 판단해, 문서만이 아니라 Claude Code의 PreToolUse 훅으로 강제했다.
어떻게 훅으로 강제했는가
강제 로직은 사용자 레벨 PreToolUse 훅 rules/hooks/check-push-review.sh가 담당한다. 동작 절차는 다음과 같다.
- 에이전트가 실행하려는 명령을 훅이 가로챈다(
git push실행 직전). - 대상 레포가 관리 대상인지 판별한다. 비관리 레포(회사 프로젝트 등)는 즉시 통과시켜 영향이 전혀 없게 한다.
- 관리 레포라면 검토 승인 마커
.git/push-review-approved가 있는지, 그리고 그 마커가 현재 HEAD 해시와 일치하는지 확인한다. - 마커가 없거나 해시가 다르면 push를 차단한다.
여기서 핵심은 마커를 HEAD 해시와 묶은 점이다. 단순히 '검토했다는 파일이 있으면 통과'로 두면, 검토 후 커밋을 하나 더 얹고 push하는 우회가 가능하다. 해시를 묶으면 커밋이 바뀐 순간 마커가 무효가 되어 이 우회가 자동으로 막힌다.
실패 사례: 오탐과 미탐을 둘 다 테스트해야 한다
첫 구현은 실행할 명령 문자열에 "push"라는 단어가 들어있는지 단순 매칭했다. 이게 바로 사고 났다. 커밋 메시지에 "push" 단어가 들어간 경우까지 push 명령으로 오인해 막으면 안 되는 걸 막는 오탐이 발생한 것이다.
그래서 명령 문자열을 shlex로 토큰 단위 분해하고, git의 하위 명령이 실제로 push인지 판별하도록 고쳤다. 여기에 더해 git -C <경로> push처럼 작업 디렉터리를 바꿔 우회하는 미탐(막아야 할 걸 놓침) 경로까지 테스트 케이스로 확인하고 나서야 완성됐다.
차단 훅을 만들 때 얻은 교훈은 명확하다. 차단기는 오탐(false positive)과 미탐(false negative)을 둘 다 테스트해야 한다. 하나만 보면, 너무 헐거워 뚫리거나 너무 빡빡해 정상 작업을 막는다.
| 증상 | 원인 | 확인 방법 |
|---|---|---|
| 정상 커밋인데 push가 막힘 | 커밋 메시지의 push 단어를 명령으로 오인(오탐) | 메시지에 push 넣은 커밋으로 push 시도 |
| 검토 안 했는데 push 성공 | git -C 등 우회 경로(미탐) |
디렉터리 지정 push를 직접 실행 |
| 검토 후 커밋 추가로 우회 | 마커가 HEAD와 무관 | 승인 후 새 커밋 얹고 push 시도 |
적용 체크리스트
- 규칙을 '어기면 되돌리기 어려운가'로 분류했는가? 그렇다면 문서가 아니라 훅 후보다.
- 규칙 정본을 한 곳에만 두고, 나머지는 임포트/링크로 참조해 드리프트를 막았는가?
- 차단 조건을 문자열 포함이 아니라 토큰/명령 단위로 판별하는가?
- 승인 마커를 커밋 해시 등 '내용'과 묶어 우회를 막았는가?
- 오탐 테스트(정상 작업이 막히지 않는지)와 미탐 테스트(우회 경로가 뚫리지 않는지)를 둘 다 돌렸는가?
- 관리 대상이 아닌 곳에는 훅이 영향을 주지 않도록 예외를 명시했는가?
한계와 주의사항
이 사례는 Claude Code의 PreToolUse 훅과 git 레포 환경 기준이다. 다른 에이전트나 CI 환경에서는 훅을 거는 지점(pre-commit, 서버 사이드 pre-receive, CI 파이프라인)이 달라지므로 그대로 옮길 수는 없다. 여기서 가져갈 것은 스크립트가 아니라 원칙이다.
또한 사용자 레벨 훅은 그 사용자 환경에서만 작동한다. 조직 차원에서 규칙을 강제하려면 서버 측 훅(pre-receive 등)이나 브랜치 보호 규칙처럼 개인 환경 밖의 지점에 거는 방안을 함께 검토하는 편이 좋다. 다만 그런 수단도 권한 설정과 운영 정책에 따라 우회 여지가 달라질 수 있으므로, '거는 것'만으로 안전이 완성되지는 않는다. 훅이 있다고 사람이 검토를 대충 해도 된다는 뜻도 아니다 — 훅은 '검토를 안 하면 못 나가게' 막을 뿐, 검토의 질까지 보장하지는 못한다.
'실전 원칙' 카테고리의 다른 글
| AI 티 안 나는 글은 문체가 아니라 소재 관리에서 나온다 (0) | 2026.08.09 |
|---|---|
| 여러 시스템에 흩어진 같은 문제를 빠짐없이 닫는 법 (0) | 2026.08.09 |
| 예측 기능을 만들었다면 연결보다 적중률 집계가 먼저다 (0) | 2026.08.09 |
| 테스트 자동화가 실제 계정 잔고를 참조하면 안 되는 이유 (0) | 2026.08.07 |
| AI 자동화에 사람 검수 단계를 반드시 넣어야 하는 이유 (0) | 2026.08.04 |