Dev Tools8 min

CLAUDE.md 제대로 쓰는 법 — 1인 인디 개발자가 16개 앱 운영하며 정리한 작성 가이드

16개 iOS 앱과 SaaS를 1인 운영하며 1년간 굴려본 CLAUDE.md 작성 5패턴 정리. Karpathy·HumanLayer 권장 길이 상한, 스코프 분리, '금지 + 대체' 형식까지.

On this page (18)

새 세션을 열 때마다 본인은 똑같은 말을 반복하고 있었다. "한국어로 답해라", "Pages Router 말고 App Router를 써라", "코드 던지기 전에 한 줄 설명해라". 16개 앱을 1인이 굴리는데, 매 세션이 신입 면접 같았다.

본인은 이걸 한 달 참다가 결론을 냈다. 세션 안에서 가르치지 말고 세션 밖에 박제해야 한다. 그게 CLAUDE.md 파일이 하는 일이다. AI한테 주는 사내 위키 같은 것이다.

이 글은 본인이 16개 iOS 앱과 SaaS를 1인 운영하면서 1년간 굴려본 CLAUDE.md 작성 가이드다. 결론부터 말한다. 잘 쓰면 매 세션 30분짜리 문맥 설명이 사라진다. 못 쓰면 그냥 무시당한다. 차이를 만든 패턴을 정리한다.

> TL;DR
> - CLAUDE.mdClaude Code가 세션 시작할 때 자동 주입하는 마크다운이다. 글로벌과 프로젝트 두 곳에서 읽힌다.
> - 잘 쓴 80줄 한 장이 매 세션 30분짜리 문맥 설명을 없앤다.
> - 핵심 5패턴: 정체성/말투/금지/작업 방식/위험. 다섯 영역으로 쪼개라.
> - "App Router 사용"보다 "Pages Router 금지 → App Router 사용"이 더 강하다. 금지 + 대체를 한 줄에 박는다.
> - 길이 상한은 60–300줄. Karpathy 공개 CLAUDE.md가 65줄이다. 그 이상은 우선순위가 무너진다.
> - 스코프가 다른 룰(Web vs iOS)은 한 글로벌 파일에 섞지 마라. 프로젝트로 분리하든 명시 표기하라.
> - @import로 길어진 룰을 쪼개라. 한 파일 200줄 넘으면 모델이 우선순위를 못 잡는다.

CLAUDE.md가 뭔지부터

CLAUDE.md는 Anthropic의 Claude Code가 작업 시작 시 자동 주입하는 마크다운 파일이다. 두 군데에서 읽힌다.

~/.claude/CLAUDE.md는 글로벌 룰이다. 모든 프로젝트에 공통 적용된다. 본인 정체성, 말투, 안전 룰을 박는다. 프로젝트루트/CLAUDE.md는 프로젝트 룰이다. 그 폴더 안에서 작업할 때만 적용된다. 코드베이스 구조, 컨벤션, 도메인 지식을 박는다.

본인은 두 개를 다 쓴다. 글로벌엔 정체성과 말투. 프로젝트엔 그 코드베이스만의 구조와 위험. 둘이 합쳐 매 세션이 본인을 이미 아는 상태로 시작한다.

비유하면 새 직원한테 매번 회사 소개를 다시 하는 게 아니라, 사내 위키 링크 하나를 던지는 셈이다. 위키가 잘 쓰여 있으면 첫날부터 일한다. 안 쓰여 있으면 매번 사장 책상 옆에 와서 묻는다.

다른 설정 파일과 무엇이 다른가

비슷한 파일이 여럿 있다. Cursor의 .cursorrules, Cursor 신형의 .cursor/rules/*.mdc, Google Gemini CLI의 GEMINI.md, OpenAI Codex 계열의 AGENTS.md. 다 마크다운인데 동작 방식이 미묘하게 다르다.

| 파일 | 도구 | 위치 | 적용 방식 |
|------|------|------|-----------|
| CLAUDE.md | Claude Code | 글로벌 + 프로젝트 | 세션 시작 시 자동 주입 |
| .cursorrules | Cursor (구) | 프로젝트 루트 | 매 채팅에 시스템 프롬프트로 주입 |
| .cursor/rules/*.mdc | Cursor (신) | 프로젝트 안 폴더 | globs 매칭, 조건부 주입 |
| AGENTS.md | Codex CLI 등 | 프로젝트 루트 | 세션 시작 시 주입 |
| GEMINI.md | Gemini CLI | 글로벌 + 프로젝트 | CLAUDE.md와 거의 동일 |

본인 입장에서 가장 자주 쓰는 건 CLAUDE.md.cursor/rules/*.mdc 두 개다. Cursor에서 inline 편집하고 Claude Code에서 큰 작업을 굴리니 두 파일에 같은 내용이 분산된다. 이 분산을 어떻게 정리하는지는 Cursor Rules vs CLAUDE.md 비교 글에 따로 정리해뒀다.

핵심만 짚자면 CLAUDE.md는 항상 박힌다. .cursor/rules/*.mdc는 globs로 조건부 주입이 가능하다. 그래서 토큰 비용은 CLAUDE.md가 더 든다. 대신 단순하다. 한 장만 보면 된다.

글로벌과 프로젝트를 나누는 기준

본인 룰은 단순하다. 사람이 안 변하는 건 글로벌, 코드베이스마다 다른 건 프로젝트.

글로벌엔 본인이 1인 개발자라는 사실, 한국어로 답하라는 말투, .env 절대 만지지 말라는 안전 룰을 박는다. 이건 SaaS 짤 때나 iOS 앱 짤 때나 같다. 프로젝트엔 그 코드베이스의 폴더 구조, 컨벤션, 도메인 용어를 박는다. SwiftUI 프로젝트의 MVVM 구조와 Next.js 프로젝트의 App Router 구조는 같은 파일에 들어갈 이유가 없다.

| 박제 영역 | 글로벌 | 프로젝트 |
|----------|--------|----------|
| 본인 정체성 | O | X |
| 답변 언어/말투 | O | X |
| 안전/금지 룰 | O | 보강 |
| 스택 큰 그림 | O | X |
| 폴더 구조 | X | O |
| 도메인 용어 | X | O |
| 자주 쓰는 npm 스크립트 | X | O |

이 분리가 안 되면 글로벌이 비대해진다. 본인 글로벌은 80줄이고 그 이상은 안 넘긴다. 200줄 부풀었던 시절이 있었는데 어느 순간 모델이 우선순위를 못 잡았다. 80줄로 줄이고 나서 룰 적중률이 다시 올라갔다.

참고로 Andrej Karpathy가 공개한 본인 CLAUDE.md가 65줄이다. HumanLayer 같은 운영 회사도 글로벌 60줄 이내, 길어지면 agent_docs/로 분할하라고 권장한다. 80–300줄을 상한선으로 잡으면 안전하다.

한 가지 더. 스코프가 다른 룰을 한 글로벌 파일에 섞지 마라. 본인은 글로벌엔 언어와 1인 인디라는 정체성만 박는다. Web 코드 컨벤션과 iOS 코드 컨벤션은 각 프로젝트 CLAUDE.md로 옮겼다. 글로벌에 두 스택 룰이 섞여 있으면 Web 작업 중에도 iOS 룰이 같이 컨텍스트에 박혀서 모델이 헷갈린다. 정 글로벌에 둬야 한다면 "Web에 한해" 같은 스코프 표기를 명시해라.

패턴 1 — 정체성과 스택을 첫 줄에 박는다

가장 위에 본인이 누구고 뭘 쓰는지 적어야 한다. AI가 가장 자주 묻는 게 "어떤 스택을 쓰시나요?"다. 미리 답해두면 안 묻는다.

본인 첫 줄은 "1인 인디 개발자 (iOS + Web SaaS)". 이 한 줄이 많은 가정을 깐다. "회원가입 만들어줘" 한 마디에 Claude가 자동으로 1인 운영 가정을 한다. Auth0 같은 비싼 서비스 추천을 안 한다. iOS도 한다니까 모바일 앱 토큰까지 같이 떠올린다.

스택은 명사 나열이 좋다. "Supabase, Vercel, Tailwind". 그러면 PostgreSQL 가정, edge function 가정, App Router 가정을 알아서 한다. 매번 "Firebase인가요?"를 안 묻는다.

여기서 한 가지. 버전을 명시하지 마라. "Next.js 16"이라고 박으면 17이 나왔을 때 본인이 까먹고 안 고친다. 그냥 "Next.js"라고 적고, 모델이 알아서 최신 가정을 하게 둔다.

패턴 2 — 말투 규칙을 디테일하게 박제한다

본인이 가장 효과를 본 부분이다. "한국어로 답해라"는 다들 적는데, 그 다음이 중요하다.

다만 한 가지 짚자면, 말투 박제와 코드 스타일 박제는 다르다. 들여쓰기·세미콜론·따옴표 같은 코드 형식은 ESLint와 Prettier가 할 일이지 CLAUDE.md에 박을 일이 아니다. linter 룰을 LLM에 시키면 토큰만 먹고 효과도 약하다. 박제할 말투는 답변 언어, 1인칭, 인사 패턴, 금지 단어 같은 사람 톤에 한정한다.

본인은 "설명은 간결하게, 불필요한 서론 생략"을 박았다. 이 한 줄로 "물론입니다! 좋은 질문이네요" 같은 영어 번역체 인사가 사라졌다. 또 "코드 변경 전 한 줄 설명 후 진행"을 박았다. 그래서 코드를 갑자기 던지지 않고, "이 함수 분리하려고 합니다 — 재사용 때문에" 한 줄을 먼저 쓴다.

블로그 글 쓸 땐 더 디테일하다. 프로젝트 CLAUDE.md에 "했다체 사용", "한 문장 40자 이내", "금지 단어 목록"까지 박았다. 이 글이 지금 그 규칙으로 써지고 있다. 말투는 디테일할수록 박제 효과가 크다. "친근하게"는 모호하지만 "이모지 금지"는 명확하다.

말투는 자주 까먹는 영역이다. 코드는 어기면 티가 나는데 말투는 한참 후에 알아챈다. 그래서 박제가 더 중요하다.

패턴 3 — 코딩 규칙은 "금지 + 대체"로 적어라

시행착오로 배운 부분이다. "App Router를 쓰자"는 약하다. "Pages Router 금지"가 강하다. 그런데 진짜 강한 형태는 둘을 합친 거다. "Pages Router 금지 → App Router 사용" 한 줄로.

차이가 큰 이유가 있다. AI 학습 데이터엔 Pages Router 예제가 훨씬 많다. "App Router 쓰자"고만 하면 다급한 순간에 모델이 다수파인 Pages Router로 빠진다. "Pages Router 금지"라고 박으면 그 단어가 컨텍스트에 박혀서 토큰 단위로 회피한다. 다만 부정문만 던지면 모델이 가끔 "그럼 뭘 써야 하지"에서 멈춰 다른 옛 패턴으로 빠질 수 있다. 그래서 금지 다음에 대체 행동을 붙여둔다. Anthropic 공식 가이드도 "constructive rule이 negative rule만 있을 때보다 일관적"이라고 권장한다.

본인 글로벌엔 negative + alternative rule이 다섯 개 있다. "Pages Router 금지 → App Router 사용", "class 컴포넌트 금지 → 함수형 컴포넌트", "completion handler 금지 → async/await" (iOS), "git push --force 금지", "별도 CSS 파일 최소화 → Tailwind utility 우선". 다 한 번씩 당하고 추가한 항목이다.

negative rule은 본인 자신도 보호한다. 새벽 3시에 짜다 보면 Pages Router가 더 빨라 보일 때가 온다. Claude가 "이건 Pages Router인데 CLAUDE.md에 금지로 박혀 있다"고 막아준다. 미래의 본인을 위한 박제다.

패턴 4 — 작업 방식을 단계로 적어라

"계획 → 승인 → 구현 → 검증". 4단계를 글로벌에 박았다. 이게 없으면 Claude는 "회원가입 만들어줘" 한 줄에 5개 파일을 만들어 던진다.

본인 박제 문장은 "복잡한 작업은 코딩 전에 계획 먼저 제시", "계획 승인 받은 후 구현 시작". 이 두 줄로 Claude가 "1) 라우트 추가, 2) Supabase 테이블 추가, 3) UI. 진행해도 될까?"라고 먼저 묻는다. 본인이 "1번만 먼저"라고 답하면 1번만 한다.

검증도 박제했다. "코드 작성 후 빌드/타입체크 가능하면 실행". 이 한 줄로 코드 던지고 끝나지 않는다. 자기가 짠 코드를 빌드 돌리고 타입 에러 나면 자기가 고친다.

본인이 자주 쓰는 명령도 박아뒀다. 글로벌 끝에 이런 블록이 있다.

```markdown

자주 쓰는 커맨드

Web (Next.js + Supabase)

npm run dev # 개발 서버 (localhost:3000)
npm run build # 프로덕션 빌드
npm run typecheck # TypeScript 타입 체크
npx supabase db push # Supabase 마이그레이션 적용

iOS (Xcode + Swift)

xcodebuild -scheme MyApp -destination 'platform=iOS Simulator,name=iPhone 15' build
```

이 박제로 Claude가 어떤 npm 스크립트를 돌려야 할지 추측하지 않는다. "타입체크 좀 해봐줘"라고 하면 npm run typecheck를 그냥 실행한다.

핵심은 AI가 자율적으로 할 수 있는 일을 미리 허락하는 것이다. 권한이 모호하면 보수적으로 굴면서 자꾸 묻는다. 박아두면 그냥 한다.

패턴 5 — 위험은 명시적으로 박제한다

마지막 패턴이 제일 중요하다. AI한테 절대 시키면 안 되는 일을 따로 박는다.

본인 위험 박제는 셋이다. ".env 파일 절대 읽거나 수정하지 말 것", "production 파일 수정 시 반드시 먼저 물어볼 것", "git push --force 금지". 1인 개발자에게 가장 무서운 사고 패턴이다.

.env 룰은 직접 데여서 추가했다. 한 번은 디버깅 중 Claude가 .env 일부를 출력했고 세션 로그에 남았다. 다행히 dev key였지만 production이면 키를 통째로 갈아야 했다. 그 다음 날 글로벌에 박았다.

production 파일 먼저 물어볼 것 룰은 두 줄짜리 PR로 production 마이그레이션을 처리할 뻔해서 추가했다. 1인 운영은 staging이 없는 경우가 많다. 당연히 위험하다가 아니라 명시적으로 위험하다고 박아둬야 한다.

@import로 길어진 룰을 쪼갠다

룰이 80줄을 넘기 시작하면 @import 문법을 쓴다. Claude Code가 공식 지원하는 기능이다. CLAUDE.md 안에 @docs/conventions.md라고 쓰면 그 파일을 자동으로 끌어와서 합친다.

본인 글로벌은 짧지만 프로젝트 CLAUDE.md엔 import를 쓴다. 이런 식이다.

```markdown

프로젝트 컨벤션

@docs/db-schema.md
@docs/api-conventions.md
@docs/danger-rules.md

추가 룰

  • 결제 관련 코드는 lib/billing/ 안에서만 수정
  • Supabase RLS 정책은 마이그레이션으로만 변경
  • ```

장점은 두 개다. 첫째, 룰을 주제별로 쪼개니 깃허브에서 보기 좋다. 둘째, 여러 프로젝트가 같은 룰을 공유할 때 한 파일만 수정하면 된다. 본인은 docs/danger-rules.md를 SaaS 두 프로젝트가 같이 import한다.

단점은 import된 파일도 다 컨텍스트에 들어간다는 점이다. 토큰을 절약하는 장치는 아니다. 정리용으로만 써라.

CLAUDE.md를 자동 갱신하는 작은 스크립트

본인이 한 가지 더 쓰는 패턴이 있다. 세션 끝에 "오늘 새로 배운 룰 있으면 글로벌에 추가해라"고 시키는 것이다. 다만 매번 손으로 시키면 까먹어서, 작은 helper를 두고 있다.

```bash
#!/usr/bin/env bash

scripts/append-claude-rule.sh — 새 룰을 ~/.claude/CLAUDE.md에 안전하게 추가

set -euo pipefail

CLAUDE_MD="${HOME}/.claude/CLAUDE.md"
TODAY=$(date +%Y-%m-%d)

if [ -z "${1:-}" ]; then
echo "사용법: ./append-claude-rule.sh \"새 룰 한 줄\""
exit 1
fi

자동 백업 후 append

cp "$CLAUDE_MD" "${CLAUDE_MD}.bak.${TODAY}"
printf "\n- %s # added %s\n" "$1" "$TODAY" >> "$CLAUDE_MD"

echo "추가됨 → $CLAUDE_MD"
echo "백업 → ${CLAUDE_MD}.bak.${TODAY}"
```

매번 vim을 열지 않아도 되고, 백업이 자동으로 남아서 실수로 지웠을 때 복구된다. 본인은 이걸 zsh alias로 cmd-rule "Pages Router 금지"처럼 쓴다.

이런 자동화가 왜 중요한지는 따로 풀 이야기지만, 핵심은 박제의 마찰을 줄이는 것이다. 마찰이 0에 가까울수록 박제가 쌓인다. 마찰이 있으면 본인이 게을러진다.

한계 — 박제가 못 막는 것

CLAUDE.md는 만능이 아니다. 1년 굴려보고 인정하는 한계가 셋이다.

첫째, 컨텍스트가 길어지면 무시되기 시작한다. 한 세션에서 코드를 한참 짜면 누적 컨텍스트가 CLAUDE.md보다 우선순위가 높아진다. 세션 후반에 갑자기 영어로 답하거나 Pages Router를 제안한다. 이럴 땐 그냥 새 세션을 연다. 길게 끌지 마라.

둘째, 너무 길게 적으면 디테일이 다 묻힌다. 본인 글로벌은 80줄이다. 처음엔 200줄까지 부풀었는데 룰이 많아질수록 모델이 우선순위를 못 잡았다. 알고는 있다. 200줄 다 지키는 인간 직원도 없다.

셋째, 본인이 룰을 어기면 AI는 안 막아준다. 본인이 "Pages Router로 짜줘"라고 명시하면 Claude는 그렇게 한다. 박제는 기본값을 정하는 거지 본인을 막는 게 아니다. 결국 본인이 본인을 컨트롤해야 한다는 게 변하지 않는다.

상황별 추천 — 어떤 룰부터 박을까

처음 만들 때 어디부터 적을지 막막하다. 본인 경험상 우선순위는 단순하다.

| 상황 | 1순위 박제 | 이유 |
|------|-----------|------|
| 첫 CLAUDE.md 작성 | 답변 언어 + 정체성 | 첫 응답부터 효과 즉시 |
| 같은 잔소리 3번 이상 | 그 잔소리 자체 | 본인이 이미 룰임을 알고 있음 |
| 사고 직후 | 위험 룰 | 다시 안 당하려면 박제 필수 |
| 프로젝트 합류 직후 | 폴더 구조 | 파일 위치 추측을 막는다 |
| 블로그/문서 작성 | 말투 + 금지 단어 | 결과물 톤이 바로 일정해짐 |

이 표 하나가 본인 1년치 시행착오다. 가장 효과 좋았던 박제는 1순위와 2순위 두 줄이다. "한국어로 답해라"와 "내가 같은 말 세 번째 한 룰". 후자가 진짜 강하다.

FAQ

CLAUDE.md를 만들면 Cursor도 그 룰을 따르나?

아니다. Cursor는 CLAUDE.md를 안 읽는다. Cursor는 .cursorrules 또는 .cursor/rules/*.mdc만 본다. 두 도구를 같이 쓰면 같은 룰을 두 파일에 박아야 한다. 본인은 핵심 룰만 양쪽에 복사하고 디테일은 각자 형식으로 둔다.

CLAUDE.md를 너무 길게 쓰면 토큰을 많이 먹나?

먹는다. 매 세션 시작마다 시스템 프롬프트로 통째로 들어간다. 80줄이면 약 400~500 토큰 정도. 부담은 크지 않지만 1000줄까지 부풀면 매 세션 비용이 쌓인다. 그래서 본인은 80줄 상한선을 둔다.

import한 파일도 같이 토큰을 먹나?

먹는다. @import는 그냥 합쳐서 보내는 기능이다. 토큰을 줄이는 마법이 아니다. 정리만 도와줄 뿐이다. 토큰 절약은 Cursor의 globs 매칭 같은 조건부 주입이 진짜 답이다.

글로벌과 프로젝트 둘 다 쓰면 충돌하지 않나?

충돌하면 프로젝트가 이긴다. 같은 주제에 대해 글로벌은 "한국어로 답해라"고 박혀 있어도 프로젝트에 "이 프로젝트는 영어로 답해라"고 박으면 그 프로젝트는 영어로 답한다. 명시적인 게 더 가까운 게 우선이다.

빈 프로젝트 CLAUDE.md를 만들 가치가 있나?

있다. 한 줄만 적어도 된다. "이 프로젝트는 Next.js + Supabase, 결제는 Stripe". 그 한 줄로 첫 응답이 달라진다. 비어 있으면 모델이 폴더 구조를 보고 추측하는데 그게 자주 틀린다.

CLAUDE.md를 git에 커밋해야 하나?

프로젝트 CLAUDE.md는 커밋한다. 협업자가 있다면 더더욱. 글로벌 ~/.claude/CLAUDE.md는 본인 정체성과 말투라 dotfiles repo에 넣어 따로 관리한다. 두 파일의 성격이 다르다.

Claude.ai 웹/모바일에서도 CLAUDE.md가 쓰이나?

아니다. CLAUDE.md는 Claude Code 전용이다. claude.ai 웹과 모바일 앱은 Projects 기능 안의 "프로젝트 지침"이 비슷한 역할을 한다. 다만 같은 파일을 자동으로 안 읽는다. 텍스트를 복사해 넣어야 한다.

마무리

CLAUDE.md는 5분이면 시작한다. 정체성 3줄, 말투 3줄, 코딩 규칙 5줄, 작업 방식 4줄, 위험 3줄. 18줄짜리 첫 버전이면 충분하다. 한 달 굴리며 데인 항목을 추가한다. 1년 뒤엔 본인 작업 방식의 80%가 박제돼 있다.

처음 만들 때 한 가지 팁이 있다. 막 적지 말고 회고 한 번 하고 적어라. 본인은 첫 버전을 쓸 때 "지난 한 주 동안 Claude한테 가장 자주 한 잔소리 5개"를 먼저 떠올렸다. 그게 그대로 글로벌 룰이 됐다. 내가 매번 시키는 것이 곧 박제 1순위다.

CLAUDE.md는 AI한테 주는 사내 위키다. 잘 쓰여 있으면 첫날부터 동료처럼 일한다. 안 쓰여 있으면 매번 본인이 사장이고 신입이고 다 한다. 16개 앱을 1인이 굴리려면 후자는 못 버틴다. 오늘 시작하는 게 낫다.

출처

> 이 글은 2026-04-30 기준 정보다. Claude Code와 각 도구의 메모리 동작은 이후 변경될 수 있다.

Share