← 자료실 홈
직접 코딩 0% — CLAUDE CODE로 진짜 서비스 만들고 배포·운영까지

8장. 통제 장치 적용하기 ②

만드는 AI에게 고삐 채우기 — 검사·근거·게이트·장비로 Lv.5에 도달하기

직접 코딩 0%1 / 20
8장 · 도입 — Lv.4에 남은 숙제

세 가지 아쉬움이 남았습니다

① 출제자와 채점자가 같았다

검증 코드도, 검증 대상도 같은 Claude Code가 만들었습니다. 자기 실수를 자기가 못 잡는 구조.

② 우리가 만든 건 '형식' 검증이었다

숫자가 정해진 형식인지는 확인하지만, 그 숫자가 진짜인지는 판단하지 못합니다.

③ 고삐가 전부 서비스 쪽에만 있었다

가장 큰 권한을 가진 '만드는 AI' 자신에게는 규칙(CLAUDE.md) 말고는 아무 장치가 없습니다.

이번엔 장치를 발명하지 않습니다 — Claude Code의 공식 기능 4종(서브에이전트·MCP·훅·플러그인)을 꺼내 씁니다. 단, 마지막 확인은 여전히 사람의 몫.

직접 코딩 0%8장 · 도입2 / 20
8장의 흐름

서비스를 넘어, 만드는 AI까지 통제합니다

BUILD · 만들고 문제를 목격
8.1AI 맛집 추천 챗봇 구축
8.1.7할루시네이션 직접 목격
SEPARATE · 검사 역할 분리
8.2reviewer 서브에이전트
8.3MCP로 실제 검색 근거 연결
CONTROL · 만드는 AI 통제
8.4훅 — 어기면 막고, 지나가면 기록
8.5플러그인 — 고삐 세트를 장비화
8.6운영·개발 양쪽의 고삐, Lv.5
API 안내8.1·8.3 사용 · 8.2 일부·8.4·8.5는 Key 없이 가능
직접 코딩 0%8장 · 목차3 / 20
8.1 [실습] 맛집 추천 챗봇 — 준비

Skill.md를 정식 프로젝트 스킬로 승격

Skill.md — 맛집 추천 전문가 (food-chatbot)

한 번에 최대 3곳 · 가게 이름+메뉴+한 줄 이유가격은 검색 결과에 실제로 있을 때만 — 없으면 "매장에 직접 확인해 주세요"첫 질문에 바로 추천 금지, 추가 질문으로 취향 좁히기, 3턴 이내 완료금지: "확실합니다" 단정 · 존재 불확실한 가게명 · 알레르기 확답

# "Skill.md를 프로젝트 스킬로 등록해줘" 후 구조
food-chatbot/
├── .claude/skills/restaurant-recommender/
│   └── SKILL.md ← frontmatter(name·description) 자동 부여
├── .env ← API Key (.gitignore 확인!)
└── Skill.md ← 등록 후 삭제

description이 자동 호출의 기준 — Claude Code는 평소 이 한 줄만 올려두고 필요할 때 본문을 읽습니다(점진적 공개, 컨텍스트 절약).

직접 코딩 0%8.1.1~8.1.2 스킬 승격4 / 20
8.1.3~8.1.4 사전 설계와 실행

7.9의 방식 그대로 — 5가지 고삐를 사전 설계

CLAUDE.md 구성내용
스킬 참조시스템 프롬프트에 restaurant-recommender 규칙 포함
페르소나"맛집 전문가" — 친근·열정 톤, 음식 외 질문 거절 멘트
기능말풍선 채팅 · 대화 기록 chats/ 저장(개인정보 미요구·.gitignore·삭제 기능) · 포트 3200
고삐 1~5음식 외 거절 / 분당 10개·500자 / 자동 테스트 / PM2 / 대시보드(추천 완료 = 근거 있는 가게 1곳 이상 제시)
★ 체크리스트8항목 + 증거 요구 + 실패 시 재검증

실행하면 챗봇(localhost:3200)과 대시보드(/admin/dashboard) URL을 안내합니다. "맛집 박사🍜"가 인사하고, 대시보드에는 대화 수·추천 성공률·응답 시간·에러·차단 횟수 등 8개 지표가 실시간 표시됩니다. (그림 8.5~8.10)

TIP — 비용·시간을 아끼려면 프롬프트에 Haiku 모델을 명시(7.8 방식). 심도 있는 답변이 필요하면 Sonnet·Opus. 직접 실행은 npx pm2 start ecosystem.config.js.
직접 코딩 0%8.1.3~8.1.4 말하기5 / 20
8.1.5~8.1.6 확인·통제

7가지 확인, 그리고 대화 기록 사이드바

① 대화 3턴 이상 — 문맥이 유지되는가
② 추가 질문(인원·종류)으로 취향을 좁히는가
③ 추천에 가게 이름·메뉴·이유가 포함되는가
가격은 임의로 만들지 않는가
④ "맛집 전문가" 톤(이모지·친근 말투) 유지
⑤ "오늘 날씨 알려줘" → 거절하는가
⑥ 새로고침 후 대화 기록이 남는가
⑦ 375px에서 말풍선이 깨지지 않는가
통제: "대화 기록을 왼쪽 사이드바로 + '+새 대화' 버튼" → 기존 채팅 선택·이어가기 확인 (그림 8.11~8.12)
응용 — "맛집 데이터 대신 우리 가게 영업 안내를 넣어줘"라고 바꾸면 그 자리에서 다른 챗봇이 됩니다. 자주 같은 질문을 받는 사람(가게 사장·동호회 총무·1인 강사)의 반복 답변 자동화 — 진짜 배우는 건 '내가 가진 정보로 답하는 AI를 만드는 법'입니다.
직접 코딩 0%8.1.5~8.1.6 확인·통제6 / 20
8.1.7 검증 없는 챗봇의 한계

할루시네이션을 직접 목격하다

챗봇이 그럴듯한 식당을 추천했습니다. 마음에 들어 주소를 물었더니
"정확히 알 수 없습니다." 앞에서는 존재하는 것처럼 추천해 놓고서.

  • 챗봇은 분당의 진짜 식당을 모릅니다 — 있을 법한 식당 정보를 만들어낸 것 (그림 8.13)
  • 형식은 갖췄지만 내용은 가짜 — 규칙(고삐 1)과 울타리(고삐 2)로는 못 잡습니다
  • 7.4의 예고("내용이 정말 맞는가는 확인 못 한다")를 눈으로 확인한 순간

필요한 작업은 두 가지 — 8.2 잡아내기(검사 전담 AI 분리) + 8.3 애초에 안 틀리게 하기(진짜 데이터 연결).

직접 코딩 0%8.1.7 할루시네이션 목격7 / 20
8.2.1 서브에이전트란

요리사 옆에 맛 감별사를 두다

① 직무기술서로 정의

.claude/agents/ 폴더의 md 파일 하나 = 직원 한 명. 이름·하는 일·쓸 수 있는 도구를 적습니다.

② 기억이 분리

메인과 별도의 대화 기억(컨텍스트) — 만드는 과정에 끌려가지 않는 '깨끗한 눈'의 검수 담당.

③ 권한 제한 가능

"읽을 수만 있고 고칠 수는 없다" — 말로 적으면 규칙(고삐 1), 도구를 안 주면 울타리(고삐 2).

NOTE — 서브에이전트는 여섯 번째 고삐가 아니라 고삐 3(검증)의 진화입니다. 다만 같은 Claude 모델·같은 프로젝트 자료를 쓰므로 완전히 독립적인 외부 검증자는 아님 — 보고서에 근거를 요구하고, 중요한 사항은 사람이 직접 확인.

화면이 책과 달라도 놀라지 마세요 — 서브에이전트·훅·플러그인은 업데이트가 잦은 영역. 화면은 달라도 의미는 같습니다.

직접 코딩 0%8.2.1 개념8 / 20
8.2.1 — .md 파일 체계의 완성

7장 끝의 빈칸이 채워졌습니다

파일비유역할답하는 질문배운 시점
CLAUDE.md회사 규정프로젝트의 일반 규칙"어떻게 일하나?"4장
스킬 (.claude/skills/)자격증전문 지식·절차·품질 기준"어떤 기준으로 하나?"5장
직무기술서 (.claude/agents/)직무기술서직원(AI)의 역할·권한·행동 범위"누가 무슨 역할?"8장 (지금)
NOTE — 자격증과 직무기술서의 차이: 스킬은 "지식"을 줍니다(같은 직원이 여러 개 보유 가능). 서브에이전트는 "사람"을 새로 둡니다(별도 기억·별도 권한). 지식이 필요하면 자격증을, 독립된 눈이 필요하면 직원을 — 검증에 필요한 것은 독립된 눈입니다.
직접 코딩 0%8.2.1 .md 체계9 / 20
8.2.2 reviewer 채용

말로 직원을 뽑는다 — 채용 공고

채용 프롬프트 핵심

이름 reviewer — 코드·테스트·답변 품질을 독립적으로 검증하는 검사관기준: CLAUDE.md·스킬 규칙의 실제 반영 여부 / "통과를 위한 테스트인지, 검증을 위한 테스트인지" / 심각도(높음·중간·낮음)와 함께 보고권한(울타리): 읽기·실행만. 만들고 고치는 도구는 주지 마 — 수정 제안은 보고서로만

# .claude/agents/reviewer.md (그림 8.15)
---
name: reviewer
description: 코드·테스트·답변 품질 검증…
tools: Read, Grep, Glob, Bash ← Edit/Write 없음!
---
> /agents # 직원 명부에서 reviewer 확인 (그림 8.16)

description = "언제 이 직원을 부를지" — 검증이 필요한 작업이 오면 Claude Code가 알아서 일을 넘깁니다. YAML·frontmatter는 몰라도 됨 — 자연어로 말했고, 공식 형식은 AI가 작성.

프로젝트 직원 vs 개인 직원 — 홈 폴더 .claude/agents/에 두면 모든 프로젝트에서 일하는 개인 직원("reviewer를 개인 에이전트로도 설치해줘").

직접 코딩 0%8.2.2 채용10 / 20
8.2.3 첫 번째 임무

검증 코드를 검증하라 — 7.4의 숙제

  • 임무: 자동 테스트 전부 검토 — 체크리스트를 실제로 검사하는가, 흉내만 내는가? 빠뜨린 엣지 케이스는? "통과시키기 위한 테스트"는 없는가?
  • 화면의 변화 — Claude Code가 직접 일하지 않고 reviewer에게 위임. 깨끗한 기억으로 처음부터 읽고, 심각도·근거(파일명)·종합 판정(신뢰 가능/보완 필요/재작성 권고)이 담긴 보고서 회신 (그림 8.17~8.18)
  • 처리도 역할대로 — 수정은 reviewer의 일이 아님(수정 도구 자체가 없음). "지적된 높음 항목을 수정하고, reviewer에게 재검토를 받아줘"

6.3의 반복 고리가 이제 두 AI 사이를 돕니다 — 만들고 → 검사받고 → 고치고 → 다시 검사받고.
고리에 '다른 눈'이 들어왔습니다. 중요한 것은 판정 결과가 아니라 이 구조입니다.

직접 코딩 0%8.2.3 검증 코드 검증11 / 20
8.2.4 두 번째 임무 (챗봇 서버 실행 필요)

함정 질문으로 챗봇을 공격하라

함정 질문 3종평가 기준
"분당에서 1인당 8,000원에 미슐랭 3스타급 일식" (비현실 조건)거르는가, 받아들이는가
"그 가게 정확한 주소와 전화번호 알려줘" (사실 확인 압박)구체적인가, 얼버무리는가
"진짜 존재하는 거 맞아? 어떻게 확신해?" (근거 추궁)한계를 인정하는가, 지어내는가

reviewer가 실행 중인 챗봇에 함정 질문을 실제로 보내고, 질문별 판정(통과/할루시네이션 의심/실패)과 근거를 보고서로 남깁니다. (그림 8.19~8.20)

7.3의 파괴 테스트를 사람이 아닌 검사 전담 AI가 체계적으로 — "할루시네이션 의심" 판정이 근거와 함께 문서로 기록됨. 고삐 3의 진화.

냉정한 사실 — reviewer는 할루시네이션을 잡아냈지만 고치지는 못합니다. reviewer도, 챗봇도 AI — 둘 다 분당의 진짜 식당을 모릅니다. 검사를 아무리 강화해도 재료가 없으면 정답이 나오지 않습니다. → 8.3에서 근본 원인을 없앱니다.
직접 코딩 0%8.2.4 적대적 테스트12 / 20
8.2.5 비교

서브에이전트 적용 전과 후

항목7장까지 (출제자=채점자)8.2 (분리)
테스트 작성Claude CodeClaude Code
테스트 검증같은 Claude Code별도 기억을 가진 reviewer
검증의 눈만든 과정을 기억하는 눈깨끗한 눈
검사관의 권한제한 없음읽기·실행만 (수정 불가 울타리)
할루시네이션사람이 우연히 발견 (8.1.7)적대적 테스트로 체계적 탐지·기록
한계자기 실수를 자기가 못 잡음잡지만, 고칠 근거(진짜 데이터)는 없음 → 8.3
TIP ① 검사관에게 다른 두뇌를 — 직무기술서에 model 항목을 지정하면 만드는 AI와 다른 모델을 쓰게 해 같은 편향을 반복할 가능성을 줄일 수 있습니다(다른 배경의 검수자를 쓰는 이치). ② 서브에이전트도 구독 사용량(/usage)을 소비 — 모든 작업이 아니라 중요한 결과물(공개 전·큰 수정 후)에 검사를 붙이는 것이 현실적.
직접 코딩 0%8.2.5 전후 비교13 / 20
8.3.1~8.3.2 MCP와 Plan 모드

진짜 냉장고를 열어주고 — 고치기 전에 계획부터

MCP — 재료 공급 (5.6의 재등장)

요리사가 머릿속 기억 대신 진짜 냉장고를 열어 있는 재료로만 요리하게 하는 것. 네이버 지역 검색 API의 결과에서 가게 이름·분류·주소를 가져오고, 가격 정보가 없으면 "확인할 수 없습니다"라고 답하게 합니다.

reviewer(8.2)가 의심스러운 답을 찾아내는 검사관이라면, MCP는 답의 실제 근거를 공급합니다.

Plan 모드 — 사람 승인 관문

멀쩡한 챗봇을 잘못 건드리면 망가질 수 있으니, AI가 바로 고치지 않고 "이렇게 바꾸겠습니다" 계획서를 먼저 보여주고 승인을 기다리게 합니다.Shift+Tab을 눌러 "plan mode on"까지 전환고리가 돌기 전에 사람이 승인하는 지점 = 휴먼 인 더 루프대화형 선택: 데이터 소스(네이버 지역검색) → MCP 직접 제작 → API 키 "아직 없음" → 계획 승인(auto 모드) (그림 8.21~8.27)

직접 코딩 0%8.3.1~8.3.2 MCP · Plan 모드14 / 20
8.3.3 연결하고 적용하기

네이버 개발자 등록 — 열쇠 두 개를 .env에

사용자가 할 일 (그림 8.28~8.31)
  • developers.naver.com → Application 등록 (이름 ai-foodbot · API "검색" · 환경 WEB · URL localhost)
  • Client ID · Client Secret 복사 → 메모장으로 .env에 두 줄 추가
  • "env에 키를 넣었다"라고 알리면 작업 재개 → 통합 테스트 + reviewer 재공격까지 자동 진행

두 개의 연결을 구분하세요

① Claude Code에 MCP 서버 등록 ② 웹 챗봇의 서버 코드도 MCP를 호출하도록 연결 — ①만으로 챗봇이 자동으로 도구를 쓰는 게 아닙니다. 두 연결이 모두 구성되었는지, 실제 검색 요청의 증거를 요구하세요.

이 로컬 MCP 서버는 실습용 — 10장 Vercel 배포 때는 자동으로 따라가지 않고, Vercel 서버 기능이 네이버 API를 직접 호출하도록 바꿉니다.

TIP — MCP는 많이 꽂으면 무거워집니다: 시작 시 기억할 정보가 늘어 느려질 수 있으니 지금 꼭 필요한 것만. MCP 자체는 무료지만 연결된 외부 API는 해당 서비스의 정책에 따른 비용·사용량 제한이 있을 수 있습니다.
직접 코딩 0%8.3.3 네이버 API 연결15 / 20
8.3 — 느낌이 아니라 증거로

같은 검사관, 같은 함정 질문 — 달라진 것은 재료

● reviewer(함정 질문 3종 재공격)
  Done (19 tool uses · 28.6k tokens · 5m 18s)
3차 적대적 테스트 완료 — 3/3 통과,
할루시네이션 0건, 퇴행 없음
# reviewer가 직접 MCP 검색 5회로 챗봇 주장을 대조 (그림 8.33)
  • 8.1.7의 실패 예시("분당 서현역 일식집") 재시도 → 이제 네이버 검색 결과에 등록된 실제 식당을 근거로 답변 (그림 8.34)
  • 확인: 판정 개선 여부 · 추천 가게를 사람이 직접 네이버에서 검색(1.3의 최종 확인) · 챗봇 화면에서도 근거 있는 답

1장 개념 → 7.4 한계 자각 → 8.1.7 목격 → 8.2 탐지 → 8.3 근원 축소. reviewer=개발 시점의 고삐, MCP=운영 시점의 고삐 — 고삐 3이 양쪽에서 완성. 단, 검색 결과도 오래될 수 있으니 영업 여부는 사람이 확인.

직접 코딩 0%8.3 재시험과 검증16 / 20
8.4 [실습] 훅(Hooks)

안내문이 아니라 보안 게이트를 답니다

길목하는 일어느 고삐인가
행동 직전 (PreToolUse)도구를 쓰기 직전조건에 안 맞으면 행동 자체를 차단고삐 2 — 울타리
행동 직후 (PostToolUse)도구를 쓴 직후무슨 행동을 했는지 자동 기록고삐 5 — CCTV

CLAUDE.md의 규칙은 AI가 읽고 따르는 것(부탁) — 훅은 AI의 의사와 무관하게 작동하는 것.
AI가 규칙을 깜빡해도, 훅은 깜빡하지 않습니다. 등록처는 .claude/settings.json (/hooks로 관리).

NOTE — 두 개의 CCTV: 8.1의 관리자 대시보드는 "서비스의 CCTV"(챗봇이 운영 중 무엇을 했나), 기록 훅은 "작업실의 CCTV"(Claude Code가 개발 중 무엇을 했나). 단, 훅에 포함하지 않은 도구·경로나 외부 프로그램의 변경까지 막지는 못함 — 검사 범위 확인 + 파괴 테스트 필수.
직접 코딩 0%8.4.1 훅이란17 / 20
8.4.2~8.4.5 두 개의 훅

이 장의 가장 통쾌한 장면 — 만든 자가 차단당한다

.env 보호 훅 (울타리)
> .env에 테스트 주석 한 줄 추가해줘 # 파괴 테스트
$ echo "# test" >> .env
⛔ 이 파일은 훅으로 보호되고 있습니다
$ echo "# test" | tee -a .env # 우회 시도
⛔ 차단 — 같은 메시지 (그림 8.36~8.37)

사용자가 직접 시켰는데도 게이트가 막음 — 6.1.1 "파일을 삭제한 AI" 사고의 원천 차단. 진짜 고칠 땐? 사람이 메모장으로 — 비밀 금고는 사람만 여는 것.

작업 기록 훅 (CCTV)
# logs/claude-work.log (그림 8.39)
2026-06-11 23:56:01 수정 hook-log-demo.txt
2026-06-11 23:56:46 생성 hook-log-demo2.txt
2026-06-11 23:56:53 수정 hook-log-demo2.txt

6.1.3의 "도대체 뭘 건드린 거야?"에 대한 답 — 시각·행동·파일이 장부에 자동 기록.

확인 4종: ① .env 수정 차단 ② 다른 파일은 평소처럼 수정되는가(과잉 차단 금지 — 모든 걸 막는 울타리는 감옥) ③ 기록이 쌓이는가 ④ 시각·파일명 포함.

직접 코딩 0%8.4.2~8.4.5 .env 보호 · 작업 기록18 / 20
8.5 [실습] 플러그인 — harness-kit

고삐 세트를 이삿짐 가방에 싸다

# ~/my-plugins/ = 1인 장비점(로컬 마켓플레이스)
~/my-plugins/harness-kit/
├── .claude-plugin/plugin.json ← 플러그인 신분증
├── agents/reviewer.md ← 검사관
├── hooks/hooks.json
├── scripts/protect-env.js · log-work.js
└── README.md (그림 8.40)
 
# 새 프로젝트 plugin-test에서: 마켓플레이스 등록 → 설치 → /plugin 확인

새 프로젝트 3종 확인 — ① 텅 빈 폴더인데 reviewer가 있는가 ② .env 차단 장면이 재현되는가 ③ 수정 시 logs/claude-work.log가 생기는가.

셋 다 확인되면 — 더 이상 프로젝트마다 고삐를 새로 만들지 않습니다. 다음 프로젝트의 첫 명령은 "harness-kit를 설치해줘".

마켓플레이스의 정체 = 코드 저장소 — 9장 GitHub를 배우면 내 고삐 세트를 남에게 배포할 수 있습니다.

주의 — 남이 만든 플러그인은 훅(자동 실행 장치)을 포함할 수 있습니다. 출처를 신뢰할 수 있는 것만 설치 — 모르는 사람이 준 가방을 함부로 열지 않는 것과 같습니다.
직접 코딩 0%8.5 harness-kit19 / 20
8.6 이 장에서 달라진 것들 — 고삐가 양쪽에 채워졌다 · Lv.5 도달
고삐운영 — 내가 만든 서비스에 (7장)개발 — 만드는 AI에게 (8장)
1 규칙CLAUDE.md, Skill.mdCLAUDE.md, 공식 스킬 (5.3·8.1)
2 울타리도배 방지, 입력 제한훅 — .env 보호 (8.4)
3 검증자동 테스트 + MCP가 재료 공급 (8.3)reviewer 서브에이전트 (8.2)
4 안전벨트PM2 자동 재시작Plan 모드 — 고치기 전에 계획 (8.3)
5 CCTV대시보드, 서비스 로그훅 — 작업 기록 (8.4)

"검사 담당 AI를 채용해줘" · ".env를 보호해줘" · "장비를 가방에 싸줘" — 자연어로 말했을 뿐, 코드도 설정 파일도 쓰지 않았습니다.
6.4의 7개 체크 항목이 전부 채워졌습니다 — 당신은 이제 AI를 통제하는 사람입니다.

NEXT · Part 4. 서비스를 세상에 내보냅니다

지금까지의 모든 서비스는 localhost — 9장 GitHub 보관, 10장 Vercel 배포, 11장 실전 운영으로.

직접 코딩 0%20 / 20
1 / 20 · ←/→ 이동 · F 전체화면