본문으로 건너뛰기

© 2026 Molayo

Zenn헤드라인2026. 05. 23. 22:55

당신은 「Fact-Forcing Gate」를 알고 있는가 — Claude Code에서 AI에게 사실을 신고하게 만드는 Hook

요약

Claude Code 사용 시 AI가 사실 관계를 확인하지 않고 코드를 수정하여 발생하는 오류를 방지하기 위한 'Fact-Forcing Gate' Hook을 소개합니다. ECC 플러그인을 통해 파일 수정 전 AI가 영향 범위를 스스로 신고하도록 강제하여 작업의 정확도를 높이는 방법을 다룹니다.

핵심 포인트

  • Claude Code의 PreToolUse Hook을 활용한 작업 차단 메커니즘
  • AI가 파일 수정 전 영향 범위와 근거를 먼저 제시하도록 강제
  • 에이전트의 '짐작 기반 작업'을 방지하고 코드 안정성 확보
  • ECC(everything-claude-code) 플러그인을 통한 구현 사례

서론: AI가 「알고 있다고 착각하며」 파일을 망가뜨리기 전에

Claude Code로 코드를 작성하게 하면서, 이런 경험을 한 적이 없으신가요?

  • 「이 함수를 수정해줘」라고 부탁했더니,
    그 함수를 import 하고 있는 다른 파일을 보지 않고 새로 작성하여 빌드가 깨졌다
  • 데이터 파일의 필드명을
    기존 스키마와 일치하지 않는 형태로 멋대로 바꿔버렸다
  • 지시 사항의 절반밖에 반영하지 않고도, **자신만만하게 「완료했습니다」**라고 보고했다

이는 Claude Code에 국한되지 않고, 코딩 에이전트(Coding Agent) 전반에 공통되는 「짐작만으로 작업을 진행하는」 문제입니다.

이에 대해, 커뮤니티 플러그인인 everything-claude-code (ECC)가 준비한 GateGuard Fact-Forcing Gate라는 Hook이 흥미로운 접근 방식을 취하고 있습니다.

한마디로 말하자면, 「파일을 편집하기 직전에, AI에게 『너는 지금 무엇을, 왜 건드리려고 하는가』를 사실로서 강제적으로 신고하게 만드는」 게이트입니다.

본 기사에서는 이 Hook의 구조, 효과, 활용법을 Mermaid 다이어그램과 함께 해설합니다.

Claude Code Hooks 복습

본론에 들어가기에 앞서, Claude Code의 Hooks 기능에 대해 1분만 시간을 내어 봅시다.

Claude Code에는 도구 호출(Tool Call: 파일 읽기/쓰기, Bash 실행 등)의 전후에 사용자 정의 스크립트를 삽입할 수 있는 Hook 시스템이 있습니다. 대표적인 이벤트는 다음과 같습니다:

  • PreToolUse — 도구 실행 . 스크립트가 non-zero를 반환하면 **해당 도구 호출을 차단(Block)**할 수 있음
  • PostToolUse — 도구 실행 . 로그 기록, 포맷팅, 추가 체크 등
  • Stop — Claude가 응답을 마쳤을 때

PreToolUse의 「차단할 수 있다」는 점이 핵심입니다. AI가 무엇을 하려고 하는지를 스크립트로 검사하고, 조건을 만족하지 않으면 멈추게 한다. 이것이 Fact-Forcing Gate의 토대입니다.

Fact-Forcing Gate란 무엇인가

ECC 플러그인의 hooks/hooks.json을 살펴보면, 다음과 같은 Hook이 등록되어 있습니다 (요점 발췌).

{
"matcher": "Edit|Write|MultiEdit",
"hooks": [
...

포인트를 풀어서 설명하면 다음과 같습니다:

  • 대상 도구: Edit / Write / MultiEdit (즉, 파일을 새로 쓰거나 수정하는 모든 작업)
  • 타이밍: PreToolUse (실행 전)
  • 동작: 파일마다 최초 1회, 편집을 강제적으로 차단하고 「사실(Fact)」의 제시를 요구함
  • 요구되는 사실:
    • 이 파일을 import / require 하고 있는 파일
    • 변경으로 인해 영향을 받는 public 함수 / 클래스
    • 데이터 파일이라면 필드명과 구조
    • 사용자 지시 사항의 축자 인용 (Verbatim Quote)

요컨대, **「수정하기 전에, 너는 정말로 이 파일의 책임과 영향 범위를 파악하고 있는가? 증거를 대라」**라는 추궁을 인간 대신 Hook이 수행해 주는 것입니다.

이것이 왜 효과적인가 — AI 에이전트의 「훑어 읽기」를 교정하기

LLM 기반의 에이전트에게는 「지시를 읽은 것만으로 만족하고, 확인해야 할 곳을 확인하지 않은 채 작업을 진행하는」 강한 경향이 있습니다. 이유는 간단합니다. 확인 작업(grep 수행, import 경로 추적, 스키마 읽기 등)은 토큰을 소비하는 것에 비해, 그 즉시 결과물이 나오지 않기 때문입니다.

인간 리뷰어가 에이전트에게 「잠깐만, 이거 호출하는 곳이 어디지?」라고 되묻지 않는 한, AI는 최단 경로로 「완료」라고 말하고 싶어 합니다.

Fact-Forcing Gate는 이 「되묻기」를 기계적으로 강제합니다.

특히 효과적인 상황:

  • 공유 모듈 (Shared Modules) — utils나 common의 함수를 수정하면, 자신도 모르는 사이에 다른 곳에서 사용되고 있는 경우가 많음 -
    데이터 스키마 (Data Schema) — JSON / YAML / DB 마이그레이션에서 필드명의 표기 불일치는 치명적인 결과를 초래함 -
    public API — export하고 있는 함수의 시그니처 (Signature) 변경은 파괴적 변경 (Breaking Change)이 되기 쉬움 -
    긴 지시 사항 — 사용자 요구사항의 전반부만 파악하고 후반부를 무시하는 사고를, 축자 인용 (Verbatim Quotation) 강제를 통해 방지

실제로 일어나는 일 — 이 글을 작성하던 중의 실례

웃지 못할 이야기지만, 이 글을 쓰기 위해 Zenn의 articles/ 디렉토리를 ls 하려 했더니, Bash용 Fact-Forcing Gate에 가로막혔습니다. 돌아온 메시지는 다음과 같았습니다.

[Fact-Forcing Gate]
Before the first Bash command this session, present these facts:
1. The current user request in one sentence
...

세션의 첫 Bash 호출에 대해,

사용자 요구사항을 한 문장으로 말할 것
이 명령어로 무엇을 검증/생성할 것인지 말할 것

을 요구합니다. Edit|Write|MultiEdit 버전과는 요구 항목이 다르지만, 사상은 동일합니다 — "첫 발을 내딛기 전에, 목적을 언어화하게 만든다" 입니다.

게다가 본 기사의 파일 자체를 Write 하려 했을 때도, 이 역시 첫 번째 Write로서 차단되었으며, importer의 유무·기존 파일의 중복·스키마·사용자 지시사항의 축자 인용을 신고하게 만들었습니다. Hook을 설명하는 글을 쓰려는 행위 자체가 Hook의 동작 데모가 되어버린 셈입니다.

이를 통과하면 그 이후의 Bash나 동일 파일 편집은 매끄럽게 진행됩니다. 매번 확인하는 것이 아니라, "위험한 첫 번째 한 번"만 차단하는 것이 핵심입니다.

활용법 — 어떤 프로젝트에 적합한가

적합한 프로젝트:

  • 의존 관계가 깊은 코드베이스 — 모듈 간 참조가 많아, 특정 함수를 수정하면 10군데 이상에 영향을 미치는 환경
  • 데이터 스키마의 정합성이 중요한 경우 — 마이그레이션, API 응답 규약 (Contract), ETL 파이프라인
  • 긴 요구사항 지시가 일상적인 경우 — 사양서나 issue 본문을 붙여넣어 작업을 시키는 케이스
  • 여러 AI를 협업시키는 환경 — 사양 판단 AI와 구현 AI를 분리했을 때, 구현 AI가 폭주하지 않도록 하는 문지기(Gatekeeper)로서 기능

반대로 오버킬 (Overkill)이 되기 쉬운 케이스:

  • 일회성으로 작성하고 버리는 스크립트
  • README나 문서만을 다루는 태스크
  • 개인 프로토타입이나 PoC 단계에서 "망가지면 다시 쓰면 된다"는 전제

v2 제안 — 조금 더 똑똑해질 예정

현재 버전은 "모든 파일에 일률적으로 게이트를 설치하는" 거친 설계로, 문서의 오타 수정에도 코어 비즈니스 로직 변경에도 동일한 체크가 실행됩니다. 이것이 오버헤드의 근원입니다.

이를 개선하기 위한 v2 제안 (Issue #1499) 에서는 다음과 같은 방향성이 제시되었습니다.

  • 리스크 기반의 계층화 — 코어 비즈니스 / 유틸리티 / 테스트 / 문서에 따라 개입 수준을 변경
  • 변경 내용 기반의 게이트 — 파일 단위가 아니라 "실제 차이점 (Diff)"을 보고 판단
  • 투명한 검증 — 평소에는 백그라운드에서 조용히 체크하다가, 정말 문제가 있을 법할 때만 개입
  • 오개입률 감소 — "의미 없는 차단율"을 75%에서 10% 이하로 낮춤
  • 컨텍스트별 요구사항 — 시그니처 변경 시에는 importer 확인, 함수 추가 시에는 필수 항목을 압축하는 등

"쓸 수 있는 것에서 사용하기 쉬운 것으로, 최종적으로는 보이지 않는 존재가 되는 것"이 v2의 철학이라고 합니다.

알려진 과제

공정성을 기하기 위해, 현재 버전의 문제점도 언급해 두겠습니다 (Issue #1427 등).

  • auto mode와의 상성이 나쁨 — 무인으로 실행하는 모드에서는 차단된 상태로 무한 루프에 빠질 수 있음
  • 비활성화 플래그가 없음 — 플러그인을 활성화하면 Hook도 자동으로 실행됨. GateGuard만 끌 수 있는 공식적인 수단이 없음
  • 입도가 거침 — 주석 수정이든 본문 로직 변경이든 동일한 무게의 체크가 실행됨

무효화하고 싶은 경우에는, ECC 플러그인의 hooks/hooks.json에서 해당 엔트리를 제거하거나, ~/.claude/settings.json에서 덮어쓰는 방식으로 운영해야 합니다.

요약

Fact-Forcing Gate는 **"AI에게 사실을 신고하게 한 뒤에 움직이게 만든다"**라는, 단순하지만 강력한 가드 메커니즘 (Guard mechanism)입니다.

  • 편집 전에 **importer / 영향 범위 / 스키마 / 지시 사항의 축자 인용 (Verbatim citation)**을 요구
  • 세션별·파일별로 처음 한 번만 블록 (Block)
  • AI 에이전트의 "훑어 읽기 문제"를 구조적으로 교정 가능 - v2에서는 리스크 기반 (Risk-based)으로 진화할 예정

"AI에게 일을 맡기고 싶지만, 멋대로 망가뜨리는 것이 두렵다"라는 니즈에 대해, Hook이라는 Claude Code의 범용 메커니즘이 철학 있는 운용 방식으로 변모한 좋은 사례라고 생각합니다. 같은 발상으로, 자신의 프로젝트에서 "빼놓을 수 없는 체크"를 Hook화 해보는 것도 재미있을 것입니다.

참고 링크

Discussion

AI 자동 생성 콘텐츠

본 콘텐츠는 Zenn AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0