Dev Tools10 min

Cursor Rules vs CLAUDE.md 깊이 비교 — AI 코딩 도구 컨텍스트 주입 패턴 정리

1인 개발자가 같은 프로젝트에서 Cursor와 Claude Code 같이 굴리면서 정리한 두 룰 시스템의 진짜 차이. Cursor 4모드 + CLAUDE.md 5위치 + AGENTS.md 단일 정본 흐름까지.

On this page (18)

본인은 같은 프로젝트에서 Cursor와 Claude Code를 같이 굴린다. 두 도구가 같은 코드베이스를 보지만 룰이 박히는 방식이 다르다. 처음에 이걸 모르고 같은 마크다운을 양쪽에 복사했더니 한쪽은 시키는 대로 하고 한쪽은 슬슬 까먹었다. 한 달쯤 헤맨 끝에 "둘은 컨텍스트 주입 방식 자체가 다른 종족"이라는 결론에 도달했다.

이 글은 그 차이를 1인 개발자 관점에서 깊게 푼다. 표면적으론 다 마크다운 한 장이지만 안을 열어보면 cursor Rules는 네 가지 모드가 있고, CLAUDE.md는 세 계층 + import 시스템이다. 이걸 모르고 쓰면 같은 룰이 매 메시지에 두 번 박혀서 토큰만 잡아먹거나, 파일은 있는데 모델이 안 읽거나 한다.

본인은 16개 iOS 앱과 SaaS 몇 개를 1인으로 굴린다. 도구가 두 개 이상 섞이는 게 일상이다. 같은 룰 두 번 적기 싫고, 안 지켜지는 룰 디버깅에 시간 빼앗기기는 더 싫다. 그 동기로 정리한 글이다. AI 코딩 도구 컨텍스트 주입 패턴이 어떻게 다른지, 둘 다 쓸 때 어떻게 분리하는지, 자주 빠지는 함정 다섯 개를 본인 사례로 풀었다.

> 빠른 요약 (TL;DR)
> - Cursor Rules는 inline edit 단위로 주입된다. CLAUDE.md는 세션 시작에 박히고 child dir 파일은 on demand로 추가된다.
> - Cursor의 .mdc엔 4모드(Always Apply / Apply Intelligently / Apply to Specific Files / Apply Manually). CLAUDE.md엔 5위치(~/.claude/, 프로젝트 루트, CLAUDE.local.md, parent dirs, child dirs) + @import.
> - 같은 룰 두 곳에 적을 땐 본인 경험상 Cursor엔 짧은 명령형, Claude엔 서술형 컨텍스트로 갈라쓰면 잘 박혔다. 외부 표준은 아니고 1년 굴려본 사견이다.
> - 글로벌은 절대 git에 안 올린다. 프로젝트 CLAUDE.md는 commit, CLAUDE.local.md는 gitignore가 표준 패턴.
> - 2026년 흐름은 AGENTS.md 단일 정본 + Cursor·Claude·Codex·Copilot 모두 그걸 import. 글 끝에 따로 푼다.
> - 룰이 안 먹으면 대부분 "파일을 못 읽었거나(frontmatter 깨짐·중복 파일)" "두 룰이 모순된" 케이스다.

본문 들어가기 전에 두 시스템의 핵심을 한 표에 모았다. 본인이 이 글에서 풀려는 차이가 어느 줄에 걸려 있는지 먼저 본다.

| 항목 | Cursor Rules | CLAUDE.md |
|------|--------------|-----------|
| 위치 | .cursor/rules/*.mdc 또는 .cursorrules | ~/.claude/CLAUDE.md + 프로젝트 루트 |
| 주입 시점 | 매 inline edit / chat마다 | 세션 시작 1회 |
| 분할 | 파일 단위 + globs 조건부 | @import 문법으로 chain |
| 모드 | Always / Auto / Agent / Manual | 항상 주입 (계층만) |
| 글로벌 영역 | 앱 설정 화면 (텍스트 X) | 별도 마크다운 파일 |

다섯 줄 다 본인이 직접 굴려보고 정리한 것이다. 차례대로 푼다.

Cursor Rules와 CLAUDE.md가 다른 종족인 이유

표면만 보면 둘 다 마크다운이다. 그런데 도구의 사용 패턴이 다르다. Cursor는 inline edit이 메인이다. 짧은 코드 블록을 즉석에서 고친다. Claude Code는 에이전트 세션이 메인이다. 한 번 시작하면 수십 번 도구를 호출하면서 자율적으로 일을 한다. 이 차이가 룰 파일 구조에 그대로 반영됐다.

Cursor는 매 inline edit 요청마다 시스템 프롬프트를 새로 만든다. 그래서 룰을 매번 주입한다. 토큰 비용이 매번 든다. 그래서 cursor Rules는 짧고 강제력 있는 명령이 잘 먹는다. "Tailwind만 써라", "App Router만 써라" 같은 한 줄 룰을 모델이 매번 다시 읽는다.

Claude Code는 세션이 길다. 한 번 시작하면 같은 시스템 프롬프트를 끝까지 들고 간다. 그래서 CLAUDE.md엔 짧은 명령보다 배경 컨텍스트가 잘 먹는다. "이 코드베이스는 왜 이런 구조이고", "위험 영역은 어디이고", "본인은 어떤 사람이고" 같은 서술형이다. 모델이 자기 판단을 내릴 때 참고하는 자료다.

본인이 이 차이를 모르고 같은 룰을 양쪽에 그대로 복사했더니, Claude는 너무 명령조라 짜증이 났는지 룰을 우회하기 시작했다. Cursor는 너무 길어서 앞쪽 30줄만 듣고 나머지를 흘렸다. 어조 분리만으로 두 도구의 룰 준수율이 눈에 띄게 올라갔다.

Cursor Rules의 4가지 모드

.cursor/rules/*.mdc 파일은 frontmatter를 가진 마크다운이다. frontmatter 필드 조합이 모드를 결정한다. 모드는 네 가지다. 본인은 처음에 이걸 안 읽고 alwaysApply: true만 써서 효율을 다 날렸다.

```mdc


description: SwiftUI iOS 작업 룰
globs: "**/*.swift"
alwaysApply: false


  • Swift 6, async/await 사용
  • @Observable 매크로 우선, ObservableObject 금지
  • completion handler 사용 안 함
  • View가 길어지면 ViewBuilder로 쪼갠다
  • ```

Always 모드(alwaysApply: true)는 매 요청마다 무조건 박힌다. 옛날 .cursorrules 파일과 동일하다. 위험 룰(production 금지, force push 금지)에 박는다. 잊으면 사고나는 항목만 여기 둔다.

Auto 모드(alwaysApply: false + globs 채움)는 globs 매칭될 때만 자동으로 들어간다. 위 예시는 .swift 파일을 만질 때만 룰이 주입된다. 본인은 스택별 컨벤션을 이 모드로 쪼갰다. iOS 룰, Next.js 룰, Tailwind 룰 따로따로다.

Agent-requested 모드(description만 채우고 globs도 alwaysApply도 비움)는 모델이 스스로 가져올지 판단한다. description을 보고 "지금 이 룰이 필요해 보인다"고 판단되면 가져온다. 본인은 가끔 쓰는 코드 리뷰 체크리스트나 마이그레이션 절차 같은 걸 여기 둔다.

Manual 모드(이름만 적고 모든 자동 트리거 비활성)는 채팅에서 @룰이름으로 직접 끌어올 때만 들어간다. 강제로 적용하기 싫고 그때그때 부르고 싶은 템플릿용이다. 본인은 PR 작성 템플릿, 테스트 코드 보일러플레이트 같은 걸 여기에 박는다.

이 네 모드를 섞어 쓰는 게 cursor Rules의 핵심이다. 본인이 1년 굴려보고 정착한 비율은 Always 20%, Auto 60%, Agent 15%, Manual 5%다. Always를 너무 많이 박으면 매 요청 토큰 비용이 늘어나고 모델 주의력이 떨어진다.

CLAUDE.md의 3계층과 @import 시스템

CLAUDE.md는 모드는 없고 계층이 있다. 세 군데서 읽힌다. ~/.claude/CLAUDE.md(글로벌), 프로젝트루트/CLAUDE.md(프로젝트), 하위 폴더 안의 CLAUDE.md(서브 디렉토리). 세 파일 다 세션 시작 시 시스템 프롬프트 앞에 통째로 박힌다.

글로벌은 본인 개인 정체성이다. 이름, 말투, 자주 쓰는 스택, 절대 금지 행동 같은 걸 박는다. 본인 글로벌은 50줄 정도다. "1인 인디 개발자, 빠른 실행 우선, 항상 한국어, .env 절대 안 만짐" 같은 항목만 추렸다.

프로젝트 루트는 그 코드베이스 전용이다. 스택 구조, 폴더 컨벤션, 위험 영역 같은 걸 적는다. 글로벌과 모순되는 게 있으면 여기서 명시적으로 뒤집는다. 예를 들어 글로벌이 "TypeScript strict"인데 어느 레거시 프로젝트는 "any 일단 허용"이라면, 프로젝트 CLAUDE.md에 "글로벌의 strict 룰을 이 프로젝트에선 일시 해제한다"고 박는다. 명시적으로 적어야 Claude가 알아챈다.

서브 디렉토리는 그 폴더 안에서만 적용된다. apps/ios/CLAUDE.md엔 SwiftUI 컨벤션을, apps/web/CLAUDE.md엔 Next.js 컨벤션을 박는 식이다. 모노레포에 잘 어울린다. Claude Code가 그 폴더에서 작업할 때 추가로 그 파일을 읽는다.

추가로 @import 문법이 있다. CLAUDE.md 안에 @docs/conventions.md라고 쓰면 그 파일도 같이 끌어온다. 룰이 길어지면 한 파일에 다 박지 말고 주제별로 쪼갠 뒤 import로 모은다. 본인 프로젝트 CLAUDE.md는 50줄 정도고 그 안에 @docs/stack.md, @docs/danger.md 두 개를 import한다. import된 파일은 그대로 컨텍스트에 들어온다. 일종의 동적 분할이다.

컨텍스트 주입 시점 — 매번 vs 한 번

가장 중요한 차이다. 본인이 두 도구를 같이 쓰면서 가장 많이 미끄러진 지점이기도 하다. Cursor와 Claude는 룰을 주입하는 시점이 근본적으로 다르다.

Cursor는 매 요청마다 시스템 프롬프트를 다시 만든다. inline edit 한 번, chat 메시지 한 번이 다 새 프롬프트다. 그 안에 매번 룰이 박힌다. 토큰 비용도 매번 든다. 대신 룰을 새로 추가하면 다음 요청부터 즉시 적용된다. 세션 재시작이 필요 없다.

Claude Code는 세션 시작 시점에 한 번 읽는다. 그 세션이 끝날 때까지 같은 시스템 프롬프트를 들고 간다. 토큰은 prompt cache가 있어서 두 번째 메시지부턴 거의 안 든다. 단점은 룰을 바꿔도 기존 세션엔 안 반영된다는 점이다. 새 세션을 시작해야 새 룰이 박힌다.

이 차이가 실전 작업에서 어떻게 나타나는지 본인 경험으로 풀면 이렇다. Cursor에서 룰을 추가하고 즉시 다음 inline edit을 날리면 적용된다. 같은 시나리오를 Claude에서 하려면 /clear 명령으로 세션을 리셋하거나 새 대화를 열어야 한다. 본인은 이걸 모르고 30분 동안 "왜 새 룰을 안 듣지" 헤맸다.

또 한 가지. Cursor는 inline edit 컨텍스트가 짧다. 한 함수 단위, 한 파일 단위로 본다. 그래서 룰도 그 범위에 맞춰야 한다. "전체 폴더 구조를 어떻게 짜라"는 식의 룰은 inline edit에서 안 먹는다. Claude는 세션이 길고 도구를 자유롭게 쓴다. 폴더 구조 같은 거시적 룰도 잘 먹는다.

globs 매칭 vs @import — 파일 분할 패턴

룰 파일이 길어지면 쪼개야 한다. 두 도구의 분할 방식이 또 다르다. 본인이 쓰는 패턴을 정리하면 이렇다.

cursor Rules는 globs로 파일 단위 자동 분기한다. .swift 파일을 만지면 iOS 룰만 들어오고, .tsx를 만지면 Next.js 룰만 들어온다. 모델 컨텍스트에 노이즈가 안 섞인다. 본인은 이걸 적극적으로 쓴다. 폴더 구조는 이렇다.

```
.cursor/rules/
├── always-danger.mdc # alwaysApply: true
├── nextjs-stack.mdc # globs: "**/*.{tsx,ts}"
├── ios-swiftui.mdc # globs: "**/*.swift"
├── tailwind.mdc # globs: "**/*.{tsx,jsx,html}"
└── pr-template.mdc # 수동 (manual)
```

이러면 Swift 파일을 열고 inline edit을 하면 always-danger와 ios-swiftui만 시스템 프롬프트에 박힌다. nextjs와 tailwind 룰은 안 들어온다. 토큰을 절약하면서 룰 노이즈도 줄인다.

CLAUDE.md는 @import로 분할한다. 메인 파일이 entrypoint 역할을 하고 import된 파일들이 같이 따라온다. 단점은 globs 매칭이 없어서 작업 컨텍스트와 무관하게 다 들어온다는 것이다. 즉 모든 import는 alwaysApply: true와 동일하게 작동한다.

```markdown

프로젝트: apsity

@docs/stack.md
@docs/conventions.md
@docs/danger.md

추가 메모

  • 신규 라우트는 모두 app/ 아래 추가
  • DB 스키마 변경은 항상 마이그레이션 파일로
  • ```

이 차이 때문에 본인은 두 도구의 룰 분할 전략을 다르게 짠다. Cursor엔 스택별로 잘게 쪼개고, Claude엔 큰 덩어리 하나로 묶는다. 어차피 Claude는 다 들어올 거니까 잘게 쪼개는 게 의미가 작다. 대신 import한 파일이 200줄 넘어가면 모델 주의력이 떨어지니 절대 그 선을 넘기지 않는다.

토큰 비용과 노이즈 컨트롤

룰을 너무 많이 박는 게 인디 개발자가 자주 빠지는 함정이다. 본인도 처음엔 한 페이지에 200줄을 쑤셔 넣었다. 결과는 모델이 앞쪽 30줄만 충실히 따랐다. 뒤쪽 룰은 "그런 게 있었나" 모드가 됐다. 시스템 프롬프트가 길어지면 모델 주의력이 떨어진다는 게 체감됐다. 두 도구 다 그렇다.

Cursor에선 이 문제가 토큰 비용으로도 직결된다. 매 요청마다 룰이 들어가니 200줄짜리 룰을 박으면 매 inline edit에 200줄어치 토큰이 깔린다. 본인이 하루 50번 inline edit을 한다면 하루 만 줄어치 토큰이다. 비용이 작지 않다. globs로 쪼개면 보통 30~50줄만 들어가니 토큰이 1/4로 줄어든다.

Claude Code에선 prompt cache 덕에 토큰 비용은 작다. 첫 메시지에서 한 번 비싸고 그다음부턴 캐시된 토큰만 든다. 그래서 토큰보다 노이즈가 더 큰 문제다. 200줄 시스템 프롬프트는 모델이 처음부터 약간 산만한 상태로 시작하게 만든다. 본인은 80줄을 상한으로 둔다.

본인이 정착한 룰 작성 가이드는 셋이다. 첫째, 측정 가능한 형태로 쓴다. "코드를 깨끗하게 짜라"는 안 먹고 "한 함수 50줄 넘으면 쪼개라"는 먹는다. 둘째, 한 줄 룰 하나에 한 가지 명령만. 한 줄에 두세 개 묶으면 모델이 그중 가장 강한 것만 듣는다. 셋째, "왜"를 짧게 붙인다. Claude는 이유를 알면 응용한다.

두 도구 같이 굴리는 분리 전략

본인이 정착한 패턴을 정리한다. 이걸로 1년 굴렸다. 같은 프로젝트에 Cursor도 있고 Claude Code도 있는 케이스다.

| 영역 | 위치 | 어조 | 예시 |
|------|------|------|------|
| 위험 룰 | 양쪽 모두 | 짧은 명령형 | ".env 금지, force push 금지" |
| 스택 컨벤션 | Cursor (globs별) | 명령형 | "Tailwind 유틸만, styled-components 금지" |
| 코드베이스 배경 | Claude (CLAUDE.md) | 서술형 | "App Router 마이그레이션 완료, 신규는 app/" |
| 본인 정체성 | Claude 글로벌만 | 서술형 | "1인 인디, 한국어, 빠른 실행 우선" |
| PR/리뷰 체크리스트 | Cursor (manual) | 단계형 | "@pr-template로 수동 호출" |

위험 룰만 양쪽에 중복한다. 모델이 까먹으면 사고나는 항목이라 중복 비용보다 누락 비용이 훨씬 크다. .env 금지, force push 금지, production 파일 수정 전 확인 같은 항목이다. 양쪽에 같은 어조로 박는다.

스택 컨벤션은 Cursor 쪽에 몰아둔다. inline edit 단위에서 즉시 적용되어야 효과가 큰 룰이다. "App Router만", "Tailwind 유틸만" 같은 짧은 명령형. globs로 파일 타입에 맞춰 쪼개면 노이즈도 줄어든다.

코드베이스 배경은 Claude 쪽에 몰아둔다. 세션 단위로 모델이 자율 판단할 때 참고하는 자료다. "이 SaaS는 RLS로 권한을 막는다, 따라서 백엔드 if문은 안 짠다" 같은 서술형. Cursor에 박아도 inline edit 컨텍스트가 짧아서 잘 안 먹힌다.

본인 정체성은 Claude 글로벌에만 박는다. Cursor 글로벌 설정은 거의 비워둔다. 대신 본인이 운영하는 모든 프로젝트의 CLAUDE.md가 글로벌 정체성을 자동으로 끌어온다. 일관성을 한 곳에 집중한다.

룰이 안 먹을 때 디버깅 순서

본인이 룰 작성보다 더 자주 하는 일이 룰 안 먹는 거 디버깅이다. 거의 모든 케이스가 다음 4단계 안에 잡힌다.

1단계, 파일을 진짜 읽었는지 확인한다. Claude Code면 세션 첫 메시지에서 "내가 박은 CLAUDE.md 룰 중 위험 영역 항목 3개만 다시 말해봐"라고 묻는다. 답이 정확하면 읽은 거다. 엉뚱한 답이면 파일 위치가 잘못됐거나, 인코딩이 깨졌거나, 너무 길어서 잘렸다. Cursor는 채팅창에 "현재 적용된 룰 목록 보여줘"라고 물으면 active rules가 나온다.

2단계, 룰 모드를 다시 본다. Cursor에서 alwaysApply: false인데 globs도 description도 없으면 그 룰은 절대 자동 주입 안 된다. 수동 호출만 가능하다. 본인이 모드를 헷갈려서 "왜 안 먹지" 한 적이 두 번 있다. frontmatter를 먼저 확인한다.

3단계, 룰이 모순되는지 본다. 글로벌과 프로젝트, .cursorrules.cursor/rules/*.mdc가 서로 어긋나면 모델이 더 강하게 박힌 쪽을 따른다. 본인은 이걸 잡으려고 두 파일을 한 화면에 띄워놓고 같이 본다. 어차피 짧으니까 한 번에 다 올라온다.

4단계, 룰이 너무 추상적이지 않은지 본다. "코드를 깨끗하게 짜라"는 안 먹는다. "한 함수 50줄 넘으면 쪼개라"는 먹는다. 측정 가능한 형태로 박아야 한다. 본인이 실패한 룰들 다시 보면 거의 다 추상적이었다.

추가로 한 가지. Cursor의 .cursorrules(옛날 형식)와 .cursor/rules/*.mdc(새 형식)가 같이 있으면 둘 다 적용된다. 새 형식이 우선이 아니다. 두 개를 같이 두면 룰이 중복돼서 모델이 혼란스러워한다. 본인은 새 형식으로 옮길 때 옛날 파일을 즉시 삭제했다.

보안과 git 커밋 정책

자주 묻는 질문이다. 본인 답은 명확하다. 프로젝트 단위 파일은 무조건 commit, 글로벌은 절대 commit 금지.

프로젝트/CLAUDE.md, .cursorrules, .cursor/rules/*.mdc는 코드베이스의 일부다. 신규 협업자나 미래의 본인이 같은 룰을 받아야 한다. .gitignore에 넣지 마라. 차라리 README 옆에 둬라. 본인은 이 파일들을 PR 리뷰 대상에 포함시킨다. 룰 변경이 코드 변경만큼 중요한 결정이라서다.

반대로 ~/.claude/CLAUDE.md, ~/.gemini/GEMINI.md 같은 글로벌은 본인 개인 정체성이다. 이메일 주소, 말투 선호, 본인이 굴리는 앱 이름까지 들어 있다. 이걸 깃에 올리면 사고난다. 본인은 이걸 별도 dotfiles 리포에 private으로 모아두고 새 머신에서 클론한다. 그것도 깃 관리지만 프로젝트 코드와는 분리한다.

또 하나 챙겨야 할 게 룰 파일 안의 비밀 정보다. 본인이 실수로 한 번 CLAUDE.md에 Supabase 프로젝트 ID를 박은 적이 있다. ID 자체는 비밀이 아니지만 그 옆에 환경 변수 이름까지 박혀 있어서 좀 찝찝했다. 그 뒤로 룰 파일엔 환경 변수 이름이나 ID 같은 식별자는 안 적는다. "환경 변수는 .env.local에 있다" 정도까지만.

.cursor/rules/는 한 가지 더 신경 쓴다. 회사 협업 프로젝트라면 거기 박힌 룰이 다른 팀원의 머신에서도 자동 적용된다. 본인 작성 스타일을 강요하는 룰을 박으면 동료가 짜증난다. 협업 프로젝트의 cursor Rules는 코드베이스 안전 룰만 박고, 개인 스타일은 본인 글로벌에 둔다.

실전 코드 — 본인 SaaS 설정

본인이 운영하는 SaaS 한 개의 실제 설정 파일을 부분 공개한다. Next.js + Supabase 스택이고 Cursor와 Claude를 같이 쓴다.

먼저 프로젝트 루트의 CLAUDE.md(서술형 컨텍스트):

```markdown

프로젝트: apsity

스택

  • Next.js 15 App Router, TypeScript strict
  • Supabase (PostgreSQL + Auth + Storage)
  • Vercel 배포, Tailwind v4

구조 결정

  • Server Component 우선, 'use client'는 인터랙션 있을 때만
  • 데이터 페칭은 Server Component에서 직접 Supabase 호출
  • API 라우트는 webhook과 외부 호출용만
  • RLS로 권한 막음, 백엔드 if문 안 짠다

@docs/danger.md
@docs/conventions.md
```

같은 폴더의 .cursor/rules/nextjs-stack.mdc(명령형, globs 자동):

```mdc


description: Next.js + TypeScript 작업 룰
globs: "**/*.{ts,tsx}"
alwaysApply: false


  • App Router only. Pages Router 코드 만들지 마라.
  • 'use client' 최소화. 컴포넌트 트리 최상단에서 분기.
  • Tailwind 유틸만. styled-components 금지.
  • as 캐스팅 금지. 모르면 unknown 후 narrow.
  • 함수 50줄 넘으면 쪼개라.
  • async Server Component에서 await 직접 사용 OK.
  • ```

추가로 .cursor/rules/always-danger.mdc(매번 주입):

```mdc


description: 위험 영역 가드
alwaysApply: true


  • supabase/migrations/ 파일 수정 전 사용자 확인.
  • production env 변수 절대 출력 금지.
  • DB 스키마 변경은 항상 마이그레이션 파일로.
  • git push --force 금지.
  • .env 파일 절대 읽거나 수정 금지.
  • ```

같은 룰셋이지만 Cursor엔 짧은 명령, Claude엔 배경 + 결정 이유를 박았다. Cursor는 매 inline edit에 명령형 룰이 다시 박혀서 코드 스타일을 강제하고, Claude는 세션 시작에 코드베이스 의도를 박아서 자율 판단을 돕는다. 둘이 충돌하지 않는다.

본인은 한 달에 한 번 두 파일을 동기화한다. 룰 추가는 보통 Claude 쪽에서 시작하고, 그게 굳어지면 Cursor에 짧은 버전으로 옮긴다. 거꾸로는 잘 안 한다. 명령형 룰이 갑자기 서술형 컨텍스트로 변하는 건 드물어서다.

상황별 어떤 도구의 어떤 파일을 쓸지

새 프로젝트 시작할 때 어떤 룰 파일을 어디에 둘지 헷갈린다. 본인이 굴려보고 만든 의사결정표다.

| 상황 | 추천 | 이유 |
|------|------|------|
| Cursor만 사용, 1인, 작은 프로젝트 | .cursorrules 한 장 | 분할 비용 > 효과 |
| Cursor만 사용, 스택 둘 이상 | .cursor/rules/*.mdc + globs | 노이즈 컨트롤 |
| Claude Code만 사용 | CLAUDE.md + 글로벌 분리 | 정체성과 코드베이스 분리 |
| 두 도구 같이 사용 | 두 파일 + 어조 분리 | 위험 룰만 중복 |
| 모노레포 + 스택 분리 | 하위 폴더에 CLAUDE.md | 작업 컨텍스트별 자동 분기 |
| 회사 협업 | 프로젝트 파일은 안전 룰만 | 개인 스타일 강요 X |
| 보안 민감 | 글로벌은 절대 commit X | dotfiles repo private |

표만 봐도 새 프로젝트 시작 시 5초 안에 결정 난다. 본인 같은 케이스(두 도구 + 1인 + 스택 여러 개)는 전 항목을 다 활용한다. 거꾸로 Cursor만 쓰는 인디 개발자에겐 .cursor/rules/ 폴더 + globs 분리가 가장 큰 효과를 준다.

추가로 AGENTS.md, GEMINI.md 같은 다른 도구 파일은 처음부터 신경 쓸 필요 없다. 본인이 그 도구를 안 쓰면 미리 박을 이유가 없다. 나중에 Codex나 Gemini를 도입하면 그때 CLAUDE.md를 심볼릭 링크로 걸어두면 된다. ln -s CLAUDE.md AGENTS.md 한 줄이면 끝난다.

FAQ

Cursor Rules와 CLAUDE.md를 합쳐서 한 파일로 관리할 순 없나

완전히는 못 한다. 두 도구가 다른 파일명을 보기 때문이다. 다만 심볼릭 링크로 일부 통일은 가능하다. 본인은 메인을 CLAUDE.md로 두고 .cursorrules 자리에 짧은 명령형 발췌본을 별도로 둔다. 룰 본문을 한 곳에서만 관리하는 셈이다. 두 도구의 작동 방식이 달라서 같은 텍스트를 그대로 공유하면 한쪽은 손해를 본다.

Cursor의 .cursorrules와 .cursor/rules/*.mdc가 같이 있으면 어느 게 우선인가

둘 다 적용된다. 우선순위는 없고 합쳐진다. 결과적으로 룰이 중복되거나 모순될 위험이 있다. Cursor 공식 문서에서도 새 형식인 .cursor/rules/*.mdc로 마이그레이션을 권장한다. 본인은 옛날 형식을 즉시 삭제하고 새 형식 한 가지만 쓴다. 둘 다 두면 디버깅이 어려워진다.

CLAUDE.md를 너무 많이 import하면 어떻게 되나

import된 파일은 다 시스템 프롬프트에 박힌다. 모드 같은 게 없어서 매번 통째로 들어간다. 200줄 import 5개 걸면 1000줄짜리 시스템 프롬프트가 된다. 모델 주의력이 떨어진다. 본인은 import 합쳐서 200줄 이하를 유지한다. 그 이상이면 진짜 필요한 룰만 추리고 나머진 코드 주석으로 옮긴다.

.cursor/rules의 globs는 정확히 어떻게 매칭되나

gitignore 스타일 glob이다. **/*.swift처럼 재귀적이고, apps/web/**/*.tsx처럼 폴더 한정도 가능하다. 매칭 대상은 현재 inline edit이 일어나는 파일이다. chat에서 여러 파일을 첨부하면 그중 하나라도 매칭되는 룰은 다 들어온다. 본인은 globs 작성 후 Cursor 공식 docs의 미리보기 기능으로 한 번 확인한다.

글로벌 CLAUDE.md를 안 쓰는 게 나은 경우도 있나

회사 머신과 개인 머신을 같이 쓰는 경우엔 글로벌을 비우거나 둘로 분리한다. 회사 머신엔 회사 컨벤션, 개인 머신엔 본인 스타일. 본인은 양쪽을 안 섞어서 글로벌 한 장으로 충분했다. 다만 회사 코드 만질 땐 프로젝트 CLAUDE.md에서 글로벌의 일부 룰을 명시적으로 뒤집는다. "글로벌의 빠른 실행 우선 룰을 이 프로젝트에선 일시 해제, 코드 리뷰 우선이 맞음" 식으로.

Cursor에서 룰을 새로 추가했는데 이전 채팅에 적용되지 않는다

이건 캐시가 아니라 의도된 동작이다. 룰은 새 채팅 시작 또는 새 inline edit 요청부터 적용된다. 진행 중인 채팅 흐름엔 안 들어간다. 본인은 룰 추가 직후 새 chat을 열어서 바로 테스트한다. inline edit은 매 요청이 새 프롬프트라 즉시 반영된다.

룰 파일을 너무 짧게 적으면 모델이 무시하지 않나

오히려 짧을수록 잘 듣는다. 본인이 200줄 룰을 80줄로 줄였더니 준수율이 올라갔다. 모델은 시스템 프롬프트가 길수록 앞쪽에 가중치를 둔다. 핵심을 위로 올리고 부수 룰은 globs로 분리하거나 import로 동적 주입한다. "최소한으로 유지, 안 지킬 룰은 박지 말 것"이 본인 1년 결론이다.

MCP 서버나 도구 권한도 룰 파일에서 제어할 수 있나

직접 제어는 안 된다. MCP는 별도 설정 파일이다. 다만 룰 파일에 "이 MCP 도구는 이런 용도로만 써라" 식의 가이드를 적어둘 순 있다. 본인은 데이터베이스 MCP 서버를 붙이면 CLAUDE.md에 "DB MCP는 read-only 쿼리 우선, write는 사용자 확인 후"라고 박는다. 권한 자체는 MCP 설정에서 막고, 룰은 보조 가드다.

AGENTS.md — 2026년의 단일 정본 흐름

여기까지 Cursor와 CLAUDE.md를 별개로 다뤘다. 그런데 같은 룰을 두 파일에 똑같이 박는 건 누가 봐도 비효율이다. 그래서 2025년 말부터 AGENTS.md 라는 표준이 부상했다. OpenAI Codex가 처음 정의했고 2025년 12월 Linux Foundation·AAIF 산하로 기증되며 본격 공통 표준이 됐다. 2026년 현재 Cursor·Claude Code·Codex CLI·GitHub Copilot·Devin·Windsurf·Gemini CLI가 모두 AGENTS.md를 읽는다.

본인의 운영 패턴은 단순해졌다. AGENTS.md를 정본으로 두고, .cursor/rules/index.mdc 한 줄에 @AGENTS.md로 import, CLAUDE.md@AGENTS.md로 import, 그 외 도구도 같은 식으로. 한 파일만 고치면 모든 도구에 반영된다. 도구별로 어조를 미세하게 갈라쓰는 게 필요한 영역(말투·인사 패턴)만 각 파일에 따로 둔다.

다만 Claude Code의 글로벌(~/.claude/CLAUDE.md)과 Cursor의 사용자 룰(앱 설정 화면)은 본인 정체성·말투 같이 도구 외부에서 동기화 못 하는 영역이라 AGENTS.md 정본에서 빠진다. 정본은 프로젝트 컨벤션·코드베이스 룰·위험 룰만 담는다.

.cursorrules 단일파일은 Cursor 공식이 deprecated 방향으로 가고 있다. 신규 프로젝트는 .cursor/rules/*.mdc로 시작하고, 기존 .cursorrules는 마이그레이션 권장이다. AGENTS.md를 정본으로 잡으면 어차피 import하는 형태라 이 마이그레이션도 한 번에 정리된다.

Skills와 Hooks — CLAUDE.md에 안 박는 게 맞는 영역

Anthropic 공식이 명시적으로 분업을 권장하는 영역이 두 가지 더 있다. Skills(.claude/skills/)와 Hooks(.claude/hooks/)다. CLAUDE.md에 다 욱여넣으면 200줄 넘게 부풀고 정작 자주 쓰는 룰이 묻힌다.

Skill은 "도메인 한정·가끔만 필요한 절차"를 담는다. 예를 들어 본인은 "App Store Connect API 호출하는 절차"를 Skill로 빼뒀다. 매 세션 박혀 있을 필요 없고, "App Store 매출 조회해줘" 같은 요청이 올 때만 모델이 그 Skill을 불러온다. CLAUDE.md엔 안 박힌다.

Hook은 "특정 이벤트에 자동 실행되는 행동"을 담는다. PostToolUse hook으로 파일 수정 후 자동 commit 하거나, PreCompact hook으로 컨텍스트 압축 직전 상태를 저장하거나. 이건 행동이지 룰이 아니라 CLAUDE.md에 박는 영역이 아니다.

이 둘을 알고 나면 CLAUDE.md가 다이어트된다. CLAUDE.md엔 "항상 박혀야 하는 핵심 컨텍스트"만 남고, 가끔 필요한 것들은 Skill, 자동화는 Hook으로 분리된다.

마무리

Cursor Rules와 CLAUDE.md는 표면적으론 비슷한 마크다운이지만 안을 열면 전혀 다른 시스템이다. Cursor는 매 inline edit마다 주입되는 짧은 룰셋이고, CLAUDE.md는 세션 단위로 박히는 서술형 컨텍스트다. 본인 경험상 같은 룰을 두 곳에 적을 땐 어조까지 맞춰야 둘 다 잘 들었다.

본인이 1년 굴려본 결론은 단순하다. 처음부터 두 파일 다 박지 말고 한 도구의 한 파일에서 시작한다. 그 파일이 80줄을 넘으면 그때 globs 또는 @import로 쪼갠다. 두 도구를 같이 쓰게 되면 그때 AGENTS.md를 정본으로 빼고 양쪽에서 import한다. 미리 다 만들면 룰만 늘고 정작 안 지킨다. 지금 본인 프로젝트의 룰 파일 한 번 열어보면 의외로 줄일 게 많이 보일 것이다.

> 공식 출처
> - Cursor Rules 공식 문서
> - Anthropic Claude Code 메모리 가이드
> - Anthropic Claude Code Best Practices
> - CLAUDE.md @import 문법 설명
> - AGENTS.md 표준 (Linux Foundation/AAIF)
> - AGENTS.md — OpenAI Codex 가이드
> - Anthropic Claude Code Skills 공식
> - Anthropic Claude Code Hooks 공식
> - Cursor MDC 파일 형식 레퍼런스
> - Anthropic prompt caching 공식 문서

이 글은 2026-04-30 기준 정보다. Cursor와 Claude Code 모두 룰 시스템을 빠르게 업데이트하는 중이라 6개월 뒤엔 다시 점검해야 할 수 있다. 본인이 운영하는 apsity는 1인 개발자를 위한 SaaS다. 같은 룰을 여러 도구에 박는 비효율을 줄이는 작은 CLI도 같이 만들고 있다. 관심 있으면 구경하면 된다.

Share