필사 모드: 2026년 AI 코딩 워크플로 베스트 프랙티스 — CLAUDE.md, AGENTS.md, .cursorrules, Skills, 서브에이전트, MCP 깊게 보기
한국어> "에이전트는 당신이 만든 환경을 그대로 닮는다. 좋은 환경을 만드는 것이 곧 좋은 에이전트를 만드는 일이다."
프롤로그 — 코드보다 컨텍스트가 먼저다
2026년 5월, 시니어 개발자의 하루는 2022년과 많이 달라졌습니다. 아침에 자리에 앉아 가장 먼저 여는 것은 IDE가 아니라 에이전트 세션입니다. PR의 절반 이상이 사람이 직접 친 줄보다 에이전트가 친 줄을 더 많이 포함합니다. 그리고 그 PR의 품질을 결정하는 가장 큰 변수는 **에이전트의 모델 버전이 아니라 우리가 만들어 둔 컨텍스트**입니다.
이 글은 한 가지 단순한 명제에서 출발합니다.
> 에이전트는 코드와 함께 있는 **마크다운 파일들과 설정 파일들**을 컴파일러처럼 읽는다. 그 파일들이 곧 당신의 에이전트다.
지난 2년 동안 일어난 일은 도구 폭발이었습니다. Claude Code의 `CLAUDE.md`, Cursor의 `.cursorrules`와 `.cursor/rules`, GitHub Copilot의 `.github/copilot-instructions.md`, 그리고 OpenAI Codex가 밀고 있는 범도구 표준 `AGENTS.md` — 이름은 다 다르지만 본질은 같습니다. **"이 레포에서 일할 때 이렇게 행동해라"** 라는 공유된 지시문입니다.
그 위에 도구별 고급 기능이 얹혀 있습니다. Claude Code의 **Skills**(`.claude/skills/`)와 **서브에이전트**(`.claude/agents/`)와 **hooks**(`.claude/hooks/`), **MCP 서버 설정**(`.mcp.json`), Cursor의 **agent 정의**(`agents.json`)와 permission 시스템. 각각은 사소해 보이지만, 합쳐 놓으면 **개인 생산성의 10배 차이**를 만듭니다.
문제는 이것을 가르치는 글이 의외로 드물다는 것입니다. 도구별 공식 문서는 있지만, 그 도구들이 한 레포에서 어떻게 공존하는지를 다룬 글은 별로 없습니다. 이 글은 그 빈자리를 채우려는 시도입니다.
이 글에서 다룰 내용:
| 장 | 주제 |
| --- | --- |
| 1장 | 컨텍스트 파일 패밀리 — 무엇이 어디로 가는가 |
| 2장 | CLAUDE.md 잘 쓰기 — 길이, 구조, 계층 |
| 3장 | AGENTS.md — 범도구 표준의 등장 |
| 4장 | Cursor 규칙 — .cursorrules와 .cursor/rules |
| 5장 | GitHub Copilot, README.dev, CONTRIBUTING의 역할 |
| 6장 | Claude Code Skills — 재사용 가능한 워크플로 |
| 7장 | 서브에이전트와 hooks — 자동화의 두 축 |
| 8장 | MCP 서버 설정 — 에이전트의 도구 상자 |
| 9장 | Permission과 샌드박싱 — 안전한 자율성 |
| 10장 | 에이전트 친화 코드베이스란 무엇인가 |
| 11장 | 안티패턴 — 이렇게 하면 망한다 |
| 에필로그 | 체크리스트 + 다음 글 예고 |
1장 · 컨텍스트 파일 패밀리
2026년 현재, 잘 세팅된 레포에는 보통 다음 파일들이 있습니다. 이름은 도구별로 갈리지만 역할은 명확히 분담됩니다.
1.1 파일 지도
| 파일 | 누가 읽는가 | 용도 |
| --- | --- | --- |
| `CLAUDE.md` | Claude Code (세션 시작 시 자동) | 이 레포에서 Claude가 따라야 할 규칙 |
| `AGENTS.md` | OpenAI Codex, 그리고 점점 더 많은 도구 | 범도구 공통 지시문 |
| `.cursorrules` (구) / `.cursor/rules/*.mdc` (신) | Cursor IDE | Cursor 모드에서의 규칙 |
| `.github/copilot-instructions.md` | GitHub Copilot Chat | Copilot에 들어가는 시스템 프롬프트 보조 |
| `README.md` | 사람 (그리고 에이전트가 컨텍스트로 사용) | 프로젝트 진입점 |
| `CONTRIBUTING.md` | 사람 + 에이전트 | 개발/PR/리뷰 규칙 |
| `README.dev.md` | 시니어/온콜/에이전트 | 내부 개발 가이드 |
| `.mcp.json` | Claude Code | 이 레포가 쓰는 MCP 서버 목록 |
| `.claude/agents/*.md` | Claude Code | 서브에이전트 정의 |
| `.claude/skills/*/SKILL.md` | Claude Code | 재사용 가능한 절차 묶음 |
| `.claude/hooks/*.toml` | Claude Code | 세션 라이프사이클 훅 |
| `agents.json` | Cursor | Cursor 에이전트 정의 |
1.2 계층의 원칙
이 모든 파일이 한 레포에 다 있을 필요는 없습니다. 다만 어떤 것을 어디에 둘지를 결정할 때 다음 세 가지 축을 따라가면 충돌이 줄어듭니다.
1. **도구 범용성 축** — 한 도구에만 쓰이면 그 도구의 파일에, 여러 도구에서 공통이면 `AGENTS.md` 또는 `README.md`에.
2. **범위 축** — 레포 전역이면 루트에, 특정 폴더만이면 그 폴더에 `CLAUDE.md`나 `AGENTS.md`를 또 둡니다. Claude Code는 작업 중인 파일의 상위 디렉터리들을 거슬러 올라가며 모든 `CLAUDE.md`를 읽어 합칩니다.
3. **휘발성 축** — 자주 바뀌는 것(현재 진행 중인 마이그레이션 메모, 회의 결정)은 별도 파일이나 `CLAUDE.md`의 짧은 절에. 거의 안 바뀌는 규칙(코드 스타일, 보안 원칙)은 본문에.
> 한 줄 요약: **공통 규칙은 AGENTS.md, 도구별 디테일은 각자의 파일, 폴더별 디테일은 폴더에.**
2장 · CLAUDE.md 잘 쓰기
Claude Code는 세션이 시작되면 작업 디렉터리의 `CLAUDE.md`를 자동으로 읽어 시스템 프롬프트에 합칩니다. 또한 작업 중인 파일 경로의 상위들을 따라가며 `CLAUDE.md`를 더 찾고, 사용자 홈의 `~/.claude/CLAUDE.md`(전역)와 머지합니다. 이 파일이 잘 쓰여 있으면 같은 모델로도 결과 품질이 눈에 띄게 올라갑니다.
2.1 좋은 CLAUDE.md의 구조
Project: Acme Web
Stack
- Next.js 15 (App Router), TypeScript strict, Tailwind v4
- Drizzle ORM + Postgres 16
- Vitest + Playwright
Conventions
- All server actions live in `app/_actions/` and import zod schemas from `lib/schemas/`.
- Database access goes through `lib/db/repositories/`. Do NOT import drizzle directly in components.
- Error type: throw `AppError` (see `lib/errors.ts`); the global handler converts to JSON.
Verification (do this before reporting "done")
- `pnpm typecheck`
- `pnpm test --run`
- `pnpm lint`
Permissions
- You may run: pnpm scripts, git read commands, gh CLI for issues/PRs.
- You may NOT run: git push, gh pr merge, anything that mutates production.
핵심은 짧고 행동 지향적이라는 점입니다. "이 레포에서 다르게 행동해야 할 부분"만 적습니다.
2.2 길이 — 200줄 안에서 끝낸다
CLAUDE.md가 1000줄이 되면 두 가지 문제가 동시에 생깁니다. 첫째, 토큰 비용이 매 턴마다 발생합니다. 둘째, 모델이 그 모든 규칙을 균일하게 따르지 못합니다. 길이가 길어질수록 중간이 묽어집니다.
경험칙: **200줄을 넘으면 분리**합니다. 두 가지 분리 패턴이 있습니다.
- 폴더별 CLAUDE.md — 백엔드 규칙은 `apps/api/CLAUDE.md`에, 프런트 규칙은 `apps/web/CLAUDE.md`에. Claude Code가 자동으로 합칩니다.
- 별도 문서 — 길고 자주 참조하지 않는 정책(보안 운영, 데이터 보존)은 별도 마크다운으로 두고 CLAUDE.md에서는 "필요할 때 `docs/security.md`를 읽어라"라고만 적습니다.
2.3 무엇을 적고 무엇을 빼는가
적을 것:
- 이 레포의 비표준 컨벤션 (전역 규칙은 적지 않습니다 — "TypeScript는 strict 모드"는 거의 모든 레포에서 같으므로 굳이 안 적어도 됩니다)
- 자주 틀리는 함정 ("이 레포에서는 `dayjs`가 아니라 `date-fns`만 쓴다")
- 검증 절차 — 어떤 명령을 돌려야 "완료"인지
- 금지 사항 — `force push`, 마이그레이션 자동 적용 등
뺄 것:
- 모델의 기본 행동에 이미 포함된 일반론 ("코드는 깔끔하게 짜라" 같은 문장은 노이즈)
- 자주 바뀌는 임시 메모 (그것은 티켓이나 PR 설명에)
- 비밀 정보 (이 파일은 보통 커밋되므로 토큰이나 키를 절대 적지 않습니다)
2.4 폴더별 CLAUDE.md 예
`apps/api/CLAUDE.md`만 따로 두면 백엔드 작업 시에만 그 규칙이 합쳐집니다.
apps/api
Boundaries
- Controllers in `routes/` — only HTTP concerns.
- Business logic in `services/`.
- DB access in `repositories/` (Drizzle).
Tests
- Unit tests next to the file (`*.test.ts`).
- Integration tests in `tests/integration/` — they spin up testcontainers Postgres.
3장 · AGENTS.md — 범도구 표준
2025년 후반부터 OpenAI Codex가 밀기 시작한 `AGENTS.md`는 "한 레포에 둔 마크다운을 모든 코딩 에이전트가 읽도록 하자"는 운동입니다. 2026년 현재 Codex, 일부 Cursor 모드, 그리고 여러 OSS 에이전트들이 이 파일을 인식합니다. 작성 방식은 마크다운 자유 형식입니다.
3.1 전형적인 AGENTS.md
AGENTS.md
This file gives AI coding agents the context they need to work in this repository.
What this repo is
A pnpm monorepo with `apps/web` (Next.js), `apps/api` (Fastify), and `packages/*` shared libs.
Setup
- Node 20.18+, pnpm 9.
- `pnpm install` from root.
- `pnpm dev` runs all apps in parallel.
Test
- `pnpm test` — unit tests across the workspace.
- `pnpm test:e2e` — Playwright; requires Docker for testcontainers.
Coding rules
- TypeScript only. No JS files in `src/`.
- Public APIs go in `packages/*/src/index.ts` re-exports.
- New endpoints need a zod request schema and 1+ test.
Don't
- Don't commit secrets. `.env.local` is gitignored on purpose.
- Don't change `pnpm-lock.yaml` without running `pnpm install`.
3.2 CLAUDE.md와의 관계
도구 두 개가 같은 파일을 읽지 않을 때, 같은 내용을 두 번 적기는 싫을 것입니다. 두 가지 패턴이 흔합니다.
- **AGENTS.md 일원화** — 모든 공통 규칙을 `AGENTS.md`에 적고, `CLAUDE.md`에는 한 줄만 둡니다.
CLAUDE.md
Read AGENTS.md first. Anything below is Claude-specific addenda.
Claude-only
- When running shell commands, prefer pnpm over npm here.
- **CLAUDE.md 일원화** — Claude만 쓴다면 `AGENTS.md`를 두지 않거나 심볼릭 링크합니다. 단, 다른 에이전트가 들어왔을 때 작동을 보장하지 않습니다.
선택의 기준: 팀이 도구를 1개만 쓴다면 단일 파일, 2개 이상이면 `AGENTS.md`를 공통 진실의 원천으로 삼고 도구별 파일은 얇게 유지합니다.
3.3 실제 사례 둘러보기
공개된 잘 쓰인 사례들이 있습니다. Vercel 자체의 OSS 레포들(`vercel/next.js`, `vercel/ai`)은 비교적 짧고 직설적인 `AGENTS.md`를 두고, 빌드/테스트 커맨드와 "PR 전 체크리스트"를 중심으로 적습니다. Anthropic의 SDK 레포들(`anthropics/anthropic-sdk-python` 등)은 `CLAUDE.md`를 쓰며, 마이그레이션 시기에는 그 상단에 "이번 시즌 변경 사항" 절을 일시적으로 둡니다. 이런 패턴을 그대로 가져다 쓰면 됩니다.
4장 · Cursor 규칙
Cursor는 두 개의 규칙 파일 시스템을 갖고 있습니다. 옛 방식과 새 방식인데, 2026년 현재 둘 다 동작합니다.
4.1 옛 방식 — `.cursorrules`
레포 루트에 평문 마크다운으로 한 파일만 둡니다.
Cursor Rules
- Use TypeScript strict mode and avoid `any`.
- Prefer named exports.
- React components: function components with explicit prop types.
- All API handlers must validate input with zod.
When generating tests
- Use Vitest.
- Place test files adjacent to source as `*.test.ts`.
장점은 단순함, 단점은 분기 불가입니다. 모든 파일 작업에 같은 규칙이 들어갑니다.
4.2 새 방식 — `.cursor/rules/*.mdc`
`.cursor/rules/` 아래에 여러 개의 `*.mdc` 파일을 두고, 각 파일이 헤더로 자기가 적용될 조건을 선언합니다.
description: "Backend API rules — Fastify routes"
globs:
- "apps/api/src/routes/**/*.ts"
alwaysApply: false
Backend API rules
- Every route declares its zod schema via `schema:` option.
- Use `app.log` not `console.log`.
- Error handling: throw `AppError` (see lib/errors.ts).
조건은 보통 두 가지로 갈립니다. `globs`에 매치되는 파일을 열고 있을 때만 적용되거나, 사용자가 명시적으로 슬래시 명령으로 호출했을 때만 적용되거나. 이 모듈식 접근이 `.cursorrules`보다 깔끔하므로, 새 레포에서는 처음부터 `.cursor/rules/` 방식을 추천합니다.
4.3 Cursor agents — `agents.json`
Cursor의 "에이전트 모드"는 자체 에이전트 정의를 가질 수 있습니다. 레포 루트의 `agents.json`에 어떤 도구를 허용할지, 어떤 모드로 실행할지 등을 적습니다. 디테일은 Cursor 버전마다 빠르게 바뀌니 공식 문서 기준으로 가는 것이 좋고, 우리 글에서는 "이런 파일이 존재한다" 정도만 인지하면 충분합니다.
5장 · GitHub Copilot, README.dev, CONTRIBUTING
5.1 `.github/copilot-instructions.md`
GitHub Copilot Chat은 이 파일이 있으면 자동으로 자신의 시스템 프롬프트에 합칩니다. 사용 패턴은 `CLAUDE.md`와 비슷하지만 더 짧게 적는 것이 좋습니다. Copilot 모델은 보통 더 좁은 컨텍스트 윈도로 동작하기 때문입니다.
Copilot Instructions
- This repo uses pnpm, Next.js 15, Drizzle, Vitest.
- Always type API responses (no `any`).
- For React components, prefer server components unless interactivity is required.
- New endpoints must validate input with zod.
5.2 README.dev.md
README.md가 외부에 보여주는 얼굴이라면, `README.dev.md`(또는 `docs/dev.md`)는 내부 개발자와 에이전트에게 보여주는 얼굴입니다. 들어갈 내용은 보통 다음입니다.
- 로컬에서 처음 띄우는 절차 (의존성, env, DB 시드)
- 자주 쓰는 명령어 목록 (`pnpm dev`, `pnpm db:reset`, `pnpm e2e:headed`)
- 디렉터리 구조 한 그림
- "처음 보는 사람이 자주 막히는 곳" 모음
이 파일은 에이전트에게도 좋고 신입에게도 좋습니다. 그래서 가장 비용 대비 효과가 높은 글 중 하나입니다.
5.3 CONTRIBUTING.md
OSS 레포라면 외부 기여자용이지만, 사내 레포에서도 "PR을 어떻게 여는가, 어떻게 리뷰하는가"의 규칙을 적어두면 에이전트가 그것을 따라갑니다. AGENTS.md와 겹친다면 한쪽에 두고 다른 쪽은 링크만 두는 편이 깔끔합니다.
6장 · Claude Code Skills — 재사용 가능한 워크플로
Skill은 Claude Code의 강력한 기능입니다. **여러 번 반복하는 작업의 절차를 마크다운으로 묶어 둔 것**이고, 이름으로 호출할 수 있습니다. 위치는 `.claude/skills/<name>/SKILL.md`(레포 로컬) 또는 `~/.claude/skills/`(전역).
6.1 SKILL.md의 모양
name: release-blog-post
description: Write, validate, and commit a trilingual blog post under data/blog/
when_to_use: User says "write a blog post" with a topic.
Release Blog Post
1. Confirm filename slug: `data/blog/<category>/<YYYY-MM-DD>-<slug>.mdx`
2. Draft Korean version first.
3. Translate to en.mdx and ja.mdx, preserving structure.
4. Validate:
npx tsx val.ts data/blog/.../<slug>.mdx data/blog/.../<slug>.en.mdx data/blog/.../<slug>.ja.mdx
5. Fix any reported issues, re-run until clean.
6. Stage and commit with message: `post: <topic> (ko/en/ja)`.
6.2 Skill을 잘 만드는 법
- 트리거(`when_to_use`)를 분명히 — 모델이 언제 이 Skill을 부를지 결정합니다.
- 절차는 번호 매긴 짧은 단계로. 한 단계가 한 문장 = 한 행동.
- 검증 단계를 마지막에 둡니다. 그 단계가 실패하면 위로 돌아가 고치라고 명시.
- Skill끼리 호출하지 않습니다 — 의존성이 생기면 디버깅이 어려워집니다.
6.3 Skill vs CLAUDE.md vs 서브에이전트
| 자산 | 언제 호출되나 | 무엇을 담는가 |
| --- | --- | --- |
| CLAUDE.md | 세션 시작 시 항상 | "이 레포에서는 이렇게 행동해라" 정적인 규칙 |
| Skill | 모델이 트리거 조건을 보고 호출 | 반복되는 절차, 체크리스트 |
| 서브에이전트 | 메인 에이전트가 위임 | 분리된 컨텍스트가 필요한 큰 작업 |
세 개를 혼동하지 않아야 깔끔한 설계가 나옵니다.
7장 · 서브에이전트와 hooks
7.1 서브에이전트 (`.claude/agents/`)
서브에이전트는 "이 작업은 다른 컨텍스트에서 다른 도구셋으로 처리하라"고 위임할 때 씁니다. 예를 들어 코드 리뷰, 보안 스캔, 대용량 검색 같은 것들. 정의는 다음과 같이 마크다운입니다.
name: security-review
description: Reviews code for security issues — secrets, injection, auth bypass.
tools: [Read, Grep, Bash]
You are a security reviewer.
Process:
1. Search for hardcoded secrets (regex on common patterns).
2. Look for SQL/command injection in user-input paths.
3. Check authn/authz boundaries.
Output: a markdown report with severity tags (P0/P1/P2).
서브에이전트의 가장 큰 가치는 **컨텍스트 격리**입니다. 메인 세션에 100k 토큰의 검색 결과가 쏟아져 들어오지 않습니다.
7.2 hooks (`.claude/hooks/`)
hook은 세션 이벤트에 자동으로 끼어드는 작은 스크립트입니다. 흔한 패턴:
- `pre_tool_use` — 위험한 명령(예: `rm -rf`, `git push --force`)에 대해 알람을 띄움
- `post_tool_use` — 파일을 수정한 직후 자동으로 포맷터를 돌림
- `session_start` — 세션 시작 시 환경 정보를 출력해 모델에 컨텍스트 제공
- `notification` — 외부 시스템(슬랙, 알림)으로 상태 푸시
훅 정의 예시는 다음과 같습니다.
[[hooks]]
event = "post_tool_use"
matcher.tool = "Edit"
matcher.path = "*.ts"
command = "pnpm prettier --write"
hook은 사용자 환경을 건드리므로 "이 레포에서만" 동작하도록 설계하는 것이 안전합니다.
8장 · MCP 서버 설정 — 에이전트의 도구 상자
MCP(Model Context Protocol)는 모델에 도구를 붙이는 표준 프로토콜입니다. Claude Code는 `.mcp.json`을 보고 그 레포에서 어떤 MCP 서버를 띄울지 결정합니다.
8.1 `.mcp.json` 예시
{
"mcpServers": {
"postgres": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-postgres"],
"env": {
"POSTGRES_URL": "postgres://app:app@localhost:5432/app"
}
},
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_TOKEN": "${env:GITHUB_TOKEN}"
}
}
}
}
이 파일이 있으면 모델에 `postgres` MCP의 쿼리 도구, `github` MCP의 이슈/PR 도구가 노출됩니다. 즉, 모델이 직접 SQL을 짜서 돌리거나, 깃허브 이슈를 열고 닫을 수 있습니다.
8.2 어떤 MCP를 둘 것인가
원칙은 "**팀이 자주 하는 외부 호출을 도구화**"입니다. 후보들:
- 데이터베이스(Postgres, MySQL) — 디버깅 시 임시 쿼리에 무한히 유용
- GitHub/GitLab — 이슈, PR, 코멘트
- 관측 도구(Sentry, Datadog, Grafana) — 에러 컨텍스트를 자동으로 가져오게
- 사내 API의 슬림 MCP — 위키, 디자인 시스템, RBAC 조회
너무 많이 붙이면 컨텍스트가 무거워지니, **세션당 5개 안쪽**을 권장합니다. 자주 안 쓰는 것은 켰다 껐다 하는 것이 낫습니다.
8.3 시크릿 다루기
`.mcp.json`은 보통 커밋되지만, env 변수는 절대 그 안에 적지 않습니다. `${env:VAR}` 문법을 쓰거나, 시크릿이 필요한 항목은 `.mcp.local.json`(gitignore된)에 별도로 둡니다. Claude Code는 두 파일을 자동으로 머지합니다.
9장 · Permission과 샌드박싱
자율성 있는 에이전트의 큰 위험은 "예상하지 못한 행동"입니다. 2026년의 도구들은 이를 막기 위해 두 가지 메커니즘을 제공합니다.
9.1 Claude Code의 permission 모드
Claude Code는 다음 모드들을 지원합니다 (이름은 버전마다 약간 다르지만 의미는 비슷).
- **default** — 위험 명령마다 사용자에게 확인을 받습니다.
- **acceptEdits** — 파일 편집은 자동 승인, 외부 명령(쉘, 네트워크)은 확인.
- **plan** — 읽기 전용. 계획만 세우고 변경은 하지 않습니다.
- **bypassPermissions** — 모든 확인을 건너뜁니다. 격리된 환경에서만 권장.
레포 단위로 권한 모드를 고정하려면 `.claude/settings.json`에 다음을 둘 수 있습니다.
{
"permissions": {
"allow": [
"Bash(pnpm test*)",
"Bash(pnpm typecheck)",
"Bash(git status)",
"Bash(git diff*)"
],
"deny": [
"Bash(git push*)",
"Bash(gh pr merge*)"
]
}
}
핵심 아이디어: **읽기와 빌드/테스트는 자동 허용, 외부에 변경을 일으키는 행동은 항상 명시적 승인**. 이 규칙 하나만으로도 사고가 크게 줄어듭니다.
9.2 Cursor의 agent 허용 목록
Cursor 에이전트도 비슷하게 명령 허용/거부 목록을 갖습니다. 흔한 권장은 "테스트와 lint와 typecheck는 무제한 허용, 패키지 설치는 확인, 깃 푸시는 차단"입니다.
9.3 샌드박스 — 워크트리, 컨테이너, dev container
권한과 별개로, 작업 자체를 격리된 환경에 가두는 패턴이 빠르게 표준이 되고 있습니다.
- **git worktree** — 한 레포의 여러 브랜치를 동시에, 별도 디렉터리에 체크아웃해 두는 기능. 에이전트가 그 워크트리 안에서만 일하게 하면 메인 작업과 충돌이 안 일어납니다.
- **dev container / Docker** — 의존성과 네트워크가 통제된 컨테이너 안에서 에이전트가 동작합니다. Claude Code Docker 이미지가 공식으로 있고, 이걸 쓰면 호스트 OS와 분리됩니다.
- **클라우드 샌드박스** — OpenAI Codex 등의 일부 모드는 클라우드 VM에서 동작합니다. 호스트는 절대 건드려지지 않습니다.
> 자율성을 늘리고 싶을수록 샌드박스를 강하게. 두 다이얼은 같은 축이 아니라 직교합니다.
10장 · 에이전트 친화 코드베이스란
설정 파일이 아무리 좋아도 코드가 따라주지 않으면 한계가 있습니다. "에이전트가 일하기 좋은 코드"라는 것이 따로 있습니다.
10.1 다섯 가지 특성
1. **강한 타입** — TypeScript strict, Python typing 풀가동, Rust. 모델이 시그니처만 보고 의도를 짐작할 수 있어야 합니다.
2. **명확한 경계** — 모듈 사이에 import 그래프가 단순하고, 한 모듈의 책임이 한 문장으로 설명됩니다.
3. **빠른 테스트** — 단위 테스트가 10초 안에 끝나야 에이전트가 매 단계 검증할 수 있습니다. 분단위 테스트만 있으면 에이전트는 검증을 건너뜁니다.
4. **좋은 에러 메시지** — `Error: invalid input` 같은 메시지는 모델에게 정보를 주지 않습니다. `Error: 'email' must be a valid RFC 5322 address (got "foo@")` 같은 에러가 에이전트에게는 디버깅 단서입니다.
5. **명명 규칙의 일관성** — 비슷한 것이 비슷하게 이름지어져 있어야 모델의 일반화가 잘 작동합니다. `userService.findById`와 `OrderRepository.get`이 섞여 있으면 모델이 헷갈립니다.
10.2 "테스트를 에이전트의 검증자로"
가장 강력한 패턴은 "에이전트가 자신의 변경을 검증하는 방식을 미리 정해두는 것"입니다. CLAUDE.md/AGENTS.md의 "Verification" 절이 그 역할을 합니다. 모델이 코드를 바꾸고 — 테스트를 돌리고 — 실패하면 — 다시 고치는 루프를 자기 안에서 닫게 됩니다. 이 루프가 닫혀 있을수록 사람의 개입이 줄어듭니다.
10.3 작은 단위 = 작은 PR = 좋은 에이전트 출력
에이전트는 한 번에 너무 많은 것을 바꾸지 않을 때 가장 잘 동작합니다. 그래서 코드베이스 자체가 "작은 PR이 자연스럽게 나오게" 설계되어야 합니다. 모듈이 너무 크면, 에이전트의 한 작업이 자동으로 거대해집니다. 이건 그냥 좋은 엔지니어링 원칙인데, 에이전트 시대에 보상이 두 배입니다.
11장 · 안티패턴 — 이렇게 하면 망한다
11.1 너무 긴 컨텍스트 파일
가장 흔한 실수입니다. CLAUDE.md가 2000줄이 되면 매 턴 그만큼의 토큰을 태우면서 모델이 중간 규칙은 잊어버립니다. 200줄에서 잘리는 자기 절제가 필요합니다.
11.2 서로 충돌하는 지시문
`CLAUDE.md`에는 "pnpm 써라", `AGENTS.md`에는 "npm 써라"가 있는 경우. 모델은 무작위로 하나를 고릅니다. 단일 진실의 원천을 정하고 다른 파일은 그쪽을 참조만 하게 만들어야 합니다.
11.3 빈 placeholder, 옛 명령어
`"This file is a stub — fill in your project details"`가 그대로 남아 있는 CLAUDE.md를 본 적이 있을 것입니다. 모델은 그것을 진지하게 받아들입니다. 그리고 6개월 전의 명령어가 그대로 적혀 있으면 그 명령어를 실행하다 실패합니다. 컨텍스트 파일도 **CI에서 lint**할 수 있다면 가장 좋습니다(빈 placeholder 검출).
11.4 시크릿 누출
MCP 설정에 API 키를 직접 적거나, hook 스크립트에 토큰을 박아 둔 채로 커밋하는 사고. 절대 일어나서는 안 됩니다. env 변수, OS 키체인, 시크릿 매니저를 통해 주입합니다.
11.5 "에이전트가 알아서 하겠지" 권한
`bypassPermissions`를 디폴트로 두고 `git push`까지 자동 허용. 한 번의 사고로 메인 브랜치가 망가집니다. 디폴트는 항상 보수적으로, 풀 자율은 격리된 워크트리/컨테이너 안에서만.
11.6 Skill을 너무 잘게 자르거나 너무 크게 만들기
Skill이 5줄이면 그냥 시스템 프롬프트로 옮기는 게 낫고, 200줄이면 그건 더 이상 Skill이 아니라 별도 문서입니다. 한 Skill은 한 화면(50~80줄)이 적당합니다.
11.7 컨텍스트 파일을 사람만 보고 갱신하기
배포 절차, CI 명령어가 바뀌었는데 CLAUDE.md가 옛 명령어를 들고 있으면 에이전트는 헛수고를 합니다. 인프라 변경 PR에 "관련 컨텍스트 파일 갱신" 체크박스를 PR 템플릿에 박아두는 것이 가장 싸게 막는 방법입니다.
에필로그 — 환경에 투자한 시간은 복리로 돌아온다
좋은 에이전트 세팅의 본질은 **단 한 가지**입니다. 사람과 도구가 한 페이지를 보고 일하게 만드는 것. 사람에게 좋은 가이드는 에이전트에게도 좋고, 에이전트에게 좋은 절차는 신입에게도 좋습니다. 둘 사이에 다른 표준은 거의 없습니다.
매 시간을 컨텍스트 파일에 투자하는 것이 부담스러울 수 있습니다. 하지만 이건 한 번의 PR에 들어가는 시간이 아닙니다. **앞으로의 모든 세션에 누적되는 시간**입니다. 잘 쓴 200줄짜리 CLAUDE.md는 1년 동안 수백 번 읽힙니다. 그 200줄에 한 시간을 더 쓰는 것은, 그 한 시간을 1000번 곱한 가치로 돌아옵니다.
베스트 프랙티스 체크리스트
1. **AGENTS.md** — 도구 공통 규칙의 진실의 원천이 있다
2. **CLAUDE.md** — 200줄 안, 비표준 컨벤션과 검증 절차 중심
3. **폴더별 CLAUDE.md** — 모노레포라면 앱·패키지별로 분리
4. **.cursor/rules/** — 글로브로 분기되는 모듈식 규칙
5. **.github/copilot-instructions.md** — Copilot용 짧은 요약
6. **README.dev.md** — 로컬 세팅과 자주 쓰는 명령
7. **.claude/skills/** — 반복되는 워크플로 묶음 (이름 트리거)
8. **.claude/agents/** — 컨텍스트 격리가 필요한 위임 작업
9. **.claude/hooks/** — 포맷터, 알람 등 자동화
10. **.mcp.json** — 자주 호출하는 외부 시스템 도구화 (커밋), 시크릿은 `.mcp.local.json`
11. **permissions** — 읽기/빌드/테스트 자동, 외부 변경 행동은 확인
12. **샌드박스** — 자율 모드는 워크트리 또는 컨테이너 안에서만
13. **CI에서 컨텍스트 파일 lint** — 빈 placeholder, 옛 명령어 검출
14. **PR 템플릿** — "관련 컨텍스트 파일 갱신" 체크박스
15. **분기마다 리뷰** — 컨텍스트 파일도 코드처럼 살아 있다
피해야 할 안티패턴 요약
- **2000줄 CLAUDE.md** — 모델은 중간을 잊어버린다. 200줄에서 자른다
- **충돌하는 지시문** — 단일 진실의 원천을 정한다
- **시크릿 직접 기입** — env 변수와 `.mcp.local.json`을 쓴다
- **풀 자율 디폴트** — 항상 보수적 디폴트 + 명시적 옵트인
- **빈 placeholder** — CI에서 검출, PR에서 차단
- **인프라 변경 시 컨텍스트 미갱신** — 템플릿 체크박스로 강제
- **너무 많은 MCP** — 세션당 5개 이내, 사용 안 하는 것은 끈다
- **너무 잘게 자른 Skill** — 5줄짜리는 시스템 프롬프트로 옮긴다
다음 글 예고
다음 글은 **"AI 코드 리뷰 워크플로 — 사람 리뷰어와 에이전트 리뷰어를 함께 쓰는 법"**입니다. 좋은 컨텍스트 파일이 작성을 돕는다면, 좋은 리뷰 프로세스는 출력의 품질을 보장합니다. 사람 리뷰어가 봐야 하는 것, 에이전트 리뷰어가 잘 잡는 것, 둘을 PR 템플릿과 CI에 어떻게 엮을지 — 그리고 어떻게 하면 "에이전트가 단 PR을 사람이 리뷰만 하는 시스템"이 만들어지는지를 정리합니다.
> 도구는 매년 바뀐다. 표준은 더 천천히 바뀐다. 환경은 한 번 잘 짜두면 한 해를 간다. 당신의 다음 한 시간을 가장 비싼 코드에 쓰지 말고, 그 코드를 만드는 환경에 쓰라.
참고 / References
- [Anthropic Claude Code 공식 문서](https://docs.claude.com/en/docs/claude-code/overview)
- [Claude Code — Memory & CLAUDE.md](https://docs.claude.com/en/docs/claude-code/memory)
- [Claude Code — Skills](https://docs.claude.com/en/docs/claude-code/skills)
- [Claude Code — Subagents](https://docs.claude.com/en/docs/claude-code/sub-agents)
- [Claude Code — Hooks](https://docs.claude.com/en/docs/claude-code/hooks)
- [Claude Code — Settings & Permissions](https://docs.claude.com/en/docs/claude-code/settings)
- [Claude Code — MCP servers](https://docs.claude.com/en/docs/claude-code/mcp)
- [AGENTS.md 공식 사이트](https://agents.md/)
- [OpenAI Codex CLI — GitHub](https://github.com/openai/codex)
- [Cursor — Rules for AI](https://docs.cursor.com/context/rules-for-ai)
- [Cursor — `.cursor/rules` 형식](https://docs.cursor.com/context/rules)
- [GitHub Copilot — Repository custom instructions](https://docs.github.com/en/copilot/customizing-copilot/adding-repository-custom-instructions-for-github-copilot)
- [Model Context Protocol 공식](https://modelcontextprotocol.io/)
- [MCP 서버 카탈로그](https://github.com/modelcontextprotocol/servers)
- [Vercel Next.js — 레포](https://github.com/vercel/next.js)
- [Vercel AI SDK — 레포](https://github.com/vercel/ai)
- [Anthropic SDK Python](https://github.com/anthropics/anthropic-sdk-python)
- [Anthropic Engineering — Building agents](https://www.anthropic.com/engineering)
- [Devin / Cognition — Agent design lessons](https://www.cognition-labs.com/)
- [git worktree 공식 문서](https://git-scm.com/docs/git-worktree)
- [GitHub Actions — copilot-instructions](https://github.com/github/copilot-instructions-examples)
현재 단락 (1/282)
2026년 5월, 시니어 개발자의 하루는 2022년과 많이 달라졌습니다. 아침에 자리에 앉아 가장 먼저 여는 것은 IDE가 아니라 에이전트 세션입니다. PR의 절반 이상이 사람이 ...