유대선

관측할 수 없으면 강제할 수 없다

AI 코딩 어시스턴트에게 '중요한 결정은 이유를 적어라'는 규칙을 걸었다. 며칠 뒤 보니 그 규칙은 강제되고 있지 않았다 — 강제될 수가 없었다. AI 엔지니어링 배경이 없어도 따라올 수 있게, 백엔드 개념(DB 제약·미들웨어·IAM)에 빗대 처음부터 끝까지 풀었다.

·13 분 소요·English version →

AI 코딩 어시스턴트에게 규칙을 하나 걸었다. "중요한 결정을 내리면 그 이유를 반드시 기록해라." 나는 이게 강제되고 있다고 믿었다. 며칠 뒤 확인해보니 강제되고 있지 않았다 — 그리고 강제될 수가 없는 종류였다. 관측할 수 없는 것은 강제할 수 없기 때문이다.

이 글은 AI 엔지니어링 배경이 없어도 따라올 수 있게 썼다. 필요한 개념은 그때그때 백엔드 비유로 깔고 간다. 순서대로 읽으면 된다.

0. 먼저, AI 에이전트가 실제로 뭔지 (백엔드식으로)

용어 네 개만 깔고 시작한다.

큰 그림 하나만 더. 에이전트를 통제하는 방법은 딱 두 종류다:

  1. harness (하네스) — 훅·권한 체크 같은 코드. 항상 실행되고, 진짜로 막을 수 있다(hard-block).
  2. prompt (프롬프트)CLAUDE.md 같은 텍스트. 따라주길 바랄 뿐, 강제력은 없다.

이 둘을 헷갈리면 안 된다. 내가 헷갈렸고, 그게 이 글의 시작이다.

1. 내가 만든 것

결정의 이유가 항상 남도록 두 개를 깔았다.

내 믿음: 중요한 결정은 항상 그 이유가 기록되도록 강제돼 있다.

2. 점검해보니 (audit)

며칠 뒤 최근 commit들과 hook 코드를 직접 뜯어봤다. 버그 몇 개가 먼저 눈에 띄었다 — 미리 말해두면 이건 핵심이 아니다. 다 고쳐도 진짜 문제는 그대로 남는다. 그러니 빠르게 훑고 넘어가자:

여기까지는 버그다. 버그는 고치면 된다. 그런데 점검에서 진짜 문제는 따로 있었다 — 버그가 아니라, hook이 애초에 닿을 수 없는 영역이 있다는 것.

hook은 git commit에만 작동한다. 그런데 내가 대화 안에서만 어떤 결정을 내리고 commit을 안 하면? hook은 그걸 볼 수가 없다. 그리고 "결정에 이유를 달아라"는 그 규칙 — 그건 hook이 아니라 CLAUDE.md에 적힌 텍스트였다. 나를 막는 게 아니라, 내가 따라주길 바라는 것. 나는 '부탁'을 '강제'로 착각하고 있었다. 네가 이유 붙은 옵션을 봤다면, 그건 코드가 날 잡아서가 아니라 내가 그냥 따라준 것이다.

3. 핵심 — 왜 "관측 못 하면 강제 못 하나" (DB로)

여기가 전부다. 네가 매일 쓰는 걸로 설명한다.

DB의 NOT NULL 제약. 누가 빈 값을 넣으려 하면 DB가 그 쓰기(write)를 보고 거부한다. 왜 가능할까? 모든 쓰기가 DB를 반드시 거쳐 가니까. DB는 그 길목에 앉은 검문소다.

반대로 "사용자끼리 비밀번호 공유하지 마"는 DB로 못 막는다. DB는 비번 공유를 볼 일이 없다. 할 수 있는 건 정책 문서에 적고 지키길 바라는 것뿐. → 검문소(관측 지점)가 없으면 강제도 없다. 글 제목 그대로다.

미들웨어도 같다. API validation 미들웨어는 모든 요청이 거기를 지나가니까 거른다. 근데 어떤 코드가 미들웨어를 안 거치고 DB에 직접 쓰면? 못 잡는다. 검문소를 지나가는 것만 강제된다.

이제 AI에 그대로 대입:

여기서 헷갈릴 수 있다 — 대화 텍스트도 어쨌든 모델 밖으로 나오지 않나? 맞다. 하지만 hook이라는 검문소는 오직 git commit만 들여다본다. 대화는 그 검문소를 지나가지 않는다. 그러니 강제의 관점에선, 대화로만 내린 결정은 머릿속 생각과 똑같이 '안 보이는' 것이다 — 검문소를 안 지나가니까.

압축하면: 강제할 수 있는 것의 집합 = 검문소를 지나가는(= 관측 가능한) 것의 집합. 검문소(hook)는 commit만 본다. 그 외 전부 — 머릿속 생각이든 대화 텍스트든 — 는 그 검문소를 안 지나가니 강제 대상이 아니다. 그래서 가장 중요한 판단이 하필 가장 강제하기 어려운 자리에 있다.

4. 곁다리 한 방 — 자기 자신은 못 고친다

이 hook을 더 낫게 고치려고, 내 턴을 통제하는 그 파일 자체를 다시 쓰려고 했다. 그랬더니 막혔다 — 내 hook이 아니라, 하네스의 권한 승인 단계(어떤 행동에 사람 승인이 필요한지 판단하는 층, §0에서 말한 harness의 또 다른 검문소)가 "제어 파일 수정은 사람의 명시적 승인을 받아와"라며 멈춰 세웠다. 나는 내 통제 파일을 내 판단만으로 못 고친다.

백엔드에 이미 있는 원리다: 서비스가 자기 IAM 권한을 자기한테 못 부여한다. 자기 PR을 자기가 머지 못 한다(four-eyes). 검사당하는 쪽이 검사하는 쪽을 겸할 수 없다. 그래서 바깥에 있는 사람(너)의 승인이 필요하다. (그래서 이 fix는 글 쓰는 지금도 아직 적용 안 됐다 — 승인 대기 중.)

5. 어디에 또 나오나

같은 구조가 여기저기 반복된다. 강제 가능 = 관측 가능. 네 세계부터:

더 가고 싶으면 (없어도 글은 완성된다):

6. 결론과 한계

새 강제력을 원하면 길은 둘뿐이다:

  1. 검문소를 새로 만든다 — 그 행위가 관측 가능한 산출물(commit, 파일, 툴 콜)을 남기도록 강제한다. 예: 결정을 반드시 commit으로 남기게 한다.
  2. 강제를 포기하고 '영향'으로 만족한다 — 텍스트로 부탁하고 따라주길 바란다.

한계도 분명하다. 대화 속 판단을 완전히 강제하는 방법은 없다. 모든 결정을 억지로 commit으로 돌리면 마찰이 늘고, 사람은 결국 건너뛴다. 그래서 정직한 상태는 "보장"이 아니라 **"부분적 검문소 + 부탁"**이다 — 내 hook이 commit은 막아도 대화는 못 막는 것처럼.