본문 바로가기

EP 빌드로그

EP.18 AI 규칙, 문서로만 두면 안 지켜진다: 훅으로 강제하기

들어가며: 왜 문서만으로는 부족했나

여러 레포에서 AI 에이전트와 협업하다 보면 "이렇게 하자"는 규칙이 쌓인다. 문제는 이 규칙이 문서에만 존재할 때다. 에이전트가 규칙을 읽고 따르길 기대하는 것과, 어겨도 실행 자체가 되지 않게 막는 것은 완전히 다른 층위의 문제였다.
이번 작업의 목표는 두 가지였다. 첫째, 전 시스템 공통 규칙을 하나의 정본으로 관리해 드리프트(사본 간 불일치)를 막는 것. 둘째, 진짜 무조건 지켜야 하는 규칙 하나(RULE-001, push 전 필수 검토)를 결정적(deterministic) 훅으로 강제하는 것이다.


규칙 정본은 한 곳에서만: 임포트 한 줄 전략

규칙 정본은 ai-automation-control 레포의 rules/GLOBAL-RULES.md에서만 관리하기로 했다. 관리 대상 9개 레포에는 규칙 내용을 복사하지 않고, 각 레포의 CLAUDE.md에 임포트 한 줄만 추가했다.

  • @../ai-automation-control/rules/GLOBAL-RULES.md — 이 한 줄로 정본을 참조한다.
  • 사본을 두지 않으므로 규칙이 바뀌어도 각 레포를 일일이 수정할 필요가 없다.
  • 드리프트(레포마다 다른 버전의 규칙)가 구조적으로 발생하지 않는다.

참고로 tvmaster-server는 관리 대상이 아님을 문서에 명시했다. 관리 범위를 문서에 분명히 적어두는 것 자체도 규칙 체계의 일부다.


RULE-001을 훅으로 강제하기

문서로 "push 전에 검토하라"고 적는 것만으로는 강제력이 없다. 그래서 사용자 레벨 PreToolUse 훅(rules/hooks/check-push-review.sh)이 강제를 담당하게 했다.

동작 방식은 다음과 같다.

  • 관리 레포에서 검토 승인 마커(.git/push-review-approved)가 없으면 git push를 차단한다.
  • 마커는 현재 HEAD 해시와 일치해야 유효하다. 이렇게 묶으면 "검토 승인 후에 커밋을 추가로 얹어 push"하는 우회도 자동으로 막힌다. 커밋이 추가되면 HEAD 해시가 바뀌어 마커가 무효가 되기 때문이다.
  • 비관리 레포(회사 프로젝트 등)에서는 훅이 즉시 통과시키므로 아무 영향이 없다.

차단 훅에서 배운 것: 오탐과 미탐을 둘 다 테스트하라

첫 구현은 실행하려는 명령 문자열에 "push"라는 단어가 들어있는지를 단순 매칭했다. 그런데 커밋 메시지 안에 "push"라는 단어가 들어가면 push가 아닌데도 차단되는 오탐이 발생했다.

이를 고치기 위해 shlex로 명령을 토큰 단위로 쪼갠 뒤 git의 하위 명령이 실제로 push인지 판별하도록 바꿨다. 여기에 git -C <경로> push 형태로 경로를 지정해 우회하는 경우까지 막는 걸 테스트 케이스로 확인하고 나서야 완성됐다.

차단 훅을 만들 때 얻은 핵심 교훈은 이것이다.

  • 오탐: 막으면 안 되는 걸 막는 경우(커밋 메시지 속 단어).
  • 미탐: 막아야 하는데 새는 우회 경로(git -C 같은 변형).

이 둘을 모두 테스트해야 차단 훅이 신뢰할 수 있게 된다.


정리: 문서와 훅은 층위가 다르다

이번 회차의 결론은 명확하다. 문서는 중앙 정본 + 임포트로 드리프트를 막고, 진짜 무조건 지켜야 하는 규칙은 결정적 훅으로 내려야 한다. 문서와 훅은 역할이 다르며, 둘을 구분해서 쓸 때 규칙 체계가 실제로 작동한다.
이번 작업에서는 공통 규칙 정본 체계를 세우고, 첫 규칙인 RULE-001(push 전 검토)을 훅으로 강제하는 데까지 구현했다. 마커를 HEAD 해시와 묶어 우회를 막고, 오탐·미탐을 모두 테스트해야 차단 훅이 신뢰를 얻는다는 것이 이번에 얻은 배움이다.

반응형