누군가 유출된 Claude Code 소스코드 51만 줄을 읽었습니다. 본인 말로는 “내가 읽었다기보다 Claude Code한테 읽혔다"고. 그렇게 해서 나온 결론은 하나입니다.
“대부분의 사람이 Claude Code를 ‘프롬프트 치고, 기다리고, 다시 치는’ 방식으로 쓰고 있는데, 소스코드를 보면 이건 페라리를 1단 기어로만 모는 거다.”
조회 3.1만 회를 기록한 이 Threads 스레드(@unclejobs.ai)에서 정리한 9가지를 상세히 분석합니다.
Sources
- https://www.threads.com/@unclejobs.ai/post/DWjHEgOiT9U
- https://github.com/instructkr/claude-code (유출 리포)
전체 구조 한눈에 보기
flowchart TD
subgraph config["⚙️ 설정 레이어"]
C1[CLAUDE.md 계층 구조]
C2[settings.json 권한 설정]
C3[Hook 시스템]
end
subgraph execution["⚡ 실행 레이어"]
E1[서브에이전트 병렬 실행]
E2[도구 60개+
읽기 병렬 / 쓰기 순차]
E3[즉시 중단 & 맥락 보존]
end
subgraph memory["🧠 메모리 레이어"]
M1[컨텍스트 압축 전략 5가지]
M2[세션 JSONL 저장 & 이어가기]
end
config --> execution
execution --> memory
classDef configStyle fill:#c5dcef,stroke:#4a90d9,color:#333
classDef execStyle fill:#c0ecd3,stroke:#3aaa6c,color:#333
classDef memStyle fill:#fde8c0,stroke:#e6a817,color:#333
class C1,C2,C3 configStyle
class E1,E2,E3 execStyle
class M1,M2 memStyle1. CLAUDE.md는 매 턴마다 읽힌다
세션 시작할 때 한 번 읽는 게 아닙니다. 메시지를 보낼 때마다 다시 읽어요. 소스코드에서 확인된 구조입니다.
flowchart TD
A[사용자 메시지 전송] --> B{CLAUDE.md 재로딩}
B --> C[글로벌
~/.claude/CLAUDE.md]
B --> D[프로젝트
./CLAUDE.md]
B --> E[모듈별 규칙
.claude/rules/*.md]
B --> F[로컬 메모
CLAUDE.local.md]
C & D & E & F --> G[컨텍스트 조합
최대 4만 자]
G --> H[Claude 응답 생성]
H --> A
classDef triggerStyle fill:#ffc8c4,stroke:#e05050,color:#333
classDef fileStyle fill:#fde8c0,stroke:#e6a817,color:#333
classDef resultStyle fill:#c0ecd3,stroke:#3aaa6c,color:#333
class A,B triggerStyle
class C,D,E,F fileStyle
class G,H resultStyle4단계 계층 구조:
| 레벨 | 경로 | 범위 | 특징 |
|---|---|---|---|
| 글로벌 | ~/.claude/CLAUDE.md |
모든 프로젝트 | 개인 설정 |
| 프로젝트 | ./CLAUDE.md |
현재 프로젝트 | Git 공유 |
| 모듈별 | .claude/rules/*.md |
길어지면 분리 | 주제별 파일 |
| 로컬 | CLAUDE.local.md |
개인 전용 | .gitignore |
최대 4만 자까지 쓸 수 있는데, 대부분 200자도 안 쓰고 있습니다. 아키텍처 결정, 파일 규칙, 테스트 패턴, “이건 절대 하지 마” 규칙을 넣어두면 매 메시지마다 자동 반영됩니다.
2. 서브에이전트 5개를 돌려도 비용은 1개와 거의 같다
소스코드에서 확인된 구조입니다. 서브에이전트를 fork하면 부모 컨텍스트의 바이트 단위 복사본을 만들고, API가 이걸 캐시합니다. 5개를 동시에 돌려도 프롬프트 캐시를 공유하기 때문에 비용이 거의 안 늘어요.
flowchart TD
Parent[부모 에이전트
컨텍스트 C] --> Fork1[서브에이전트 1
보안 감사]
Parent --> Fork2[서브에이전트 2
리팩토링]
Parent --> Fork3[서브에이전트 3
테스트 작성]
Parent --> Fork4[서브에이전트 4
문서 업데이트]
Parent --> Fork5[서브에이전트 5
버그 수정]
Cache[(API 프롬프트 캐시
컨텍스트 C 공유)]
Parent -.->|바이트 복사| Cache
Fork1 & Fork2 & Fork3 & Fork4 & Fork5 -.->|캐시 히트| Cache
classDef parentStyle fill:#c5dcef,stroke:#4a90d9,color:#333
classDef forkStyle fill:#c0ecd3,stroke:#3aaa6c,color:#333
classDef cacheStyle fill:#fde8c0,stroke:#e6a817,color:#333
class Parent parentStyle
class Fork1,Fork2,Fork3,Fork4,Fork5 forkStyle
class Cache cacheStyle실행 모델 3가지:
flowchart TD
subgraph fork["fork 모드"]
F1[부모 컨텍스트 상속]
F2[캐시 최적화]
F3[독립 실행]
end
subgraph teammate["teammate 모드"]
T1[tmux / iTerm 별도 패널]
T2[파일 기반 메일박스 통신]
T3[병렬 화면 분할]
end
subgraph worktree["worktree 모드"]
W1[독립 git 워크트리]
W2[에이전트별 브랜치 격리]
W3[충돌 없는 병렬 작업]
end
classDef forkStyle fill:#c5dcef,stroke:#4a90d9,color:#333
classDef tmateStyle fill:#c0ecd3,stroke:#3aaa6c,color:#333
classDef wtStyle fill:#e0c8ef,stroke:#7b5ea7,color:#333
class F1,F2,F3 forkStyle
class T1,T2,T3 tmateStyle
class W1,W2,W3 wtStyle보안 감사·리팩토링·테스트 작성·문서 업데이트·버그 수정을 동시에 돌릴 수 있는 구조가 이미 내장되어 있는데, 대부분 한 번에 하나씩 시키고 있는 것입니다.
3. 권한 팝업을 매번 클릭하고 있다면 설정을 안 한 것이다
“이 작업을 허용할까요?“가 뜰 때마다 클릭하는 건 기능이 아니라 설정 실패입니다.
settings.json에 glob 패턴으로 허용 범위를 정해두면 됩니다.
{
"permissions": {
"allow": [
"Bash(npm *)",
"Bash(git *)",
"Edit(src/**)",
"Read(**)"
]
}
}
flowchart TD
A[도구 실행 요청] --> B{권한 모드}
B -->|default| C[매번 팝업 클릭 필요]
B -->|allowlist 설정| D[glob 패턴 매칭]
B -->|auto 모드 NEW| E[LLM 분류기가 판단]
D --> F{패턴 일치?}
F -->|✅ 일치| G[자동 승인]
F -->|❌ 불일치| H[팝업 표시]
E --> I[위험도 자동 평가]
I --> G
classDef badStyle fill:#ffc8c4,stroke:#e05050,color:#333
classDef goodStyle fill:#c0ecd3,stroke:#3aaa6c,color:#333
classDef newStyle fill:#fde8c0,stroke:#e6a817,color:#333
class C,H badStyle
class G goodStyle
class E,I newStyle특히 auto 모드가 새로 생겼는데, LLM 분류기가 각 동작을 판단합니다. 한 번 설정하면 클릭할 일이 없어집니다.
4. 컨텍스트 압축 전략이 5가지나 있다
Anthropic 엔지니어들이 컨텍스트 넘침 문제에 엄청난 시간을 쏟았다는 증거입니다. 5가지 전략이 내장되어 있어요.
flowchart TD
Problem[컨텍스트 한계 도달] --> Strategy{압축 전략 선택}
Strategy --> S1[microcompact
오래된 도구 결과를
시간 기준으로 삭제]
Strategy --> S2[context collapse
대화 구간을 요약으로 압축]
Strategy --> S3[session memory
핵심 맥락을 파일로 추출·저장]
Strategy --> S4[full compact
전체 히스토리 요약]
Strategy --> S5[PTL truncation
가장 오래된 메시지 그룹 삭제]
S1 & S2 & S3 & S4 & S5 --> Result[컨텍스트 확보
작업 계속]
classDef problemStyle fill:#ffc8c4,stroke:#e05050,color:#333
classDef stratStyle fill:#fde8c0,stroke:#e6a817,color:#333
classDef resultStyle fill:#c0ecd3,stroke:#3aaa6c,color:#333
class Problem problemStyle
class S1,S2,S3,S4,S5 stratStyle
class Result resultStyle핵심 조언: /compact를 게임의 수동 세이브처럼 쓰세요. 자동 압축을 기다리면 중요한 맥락이 먼저 날아갈 수 있습니다. 중요한 건 보존하고, 필요 없는 건 날리고, 계속 진행하는 것이 전략입니다.
5. Hook 시스템이 진짜 확장 API다
라이프사이클 이벤트가 25개 이상 존재합니다. Hook 종류도 5가지입니다.
flowchart TD
subgraph events["라이프사이클 이벤트 (25개+)"]
E1[SessionStart]
E2[UserPromptSubmit
⭐ 특히 강력]
E3[PreToolUse
도구 실행 전]
E4[PostToolUse
도구 실행 후]
E5[SessionEnd]
E6[... 20개+]
end
subgraph hooks["Hook 종류 (5가지)"]
H1[command
쉘 명령 실행]
H2[prompt
LLM에 맥락 주입]
H3[agent
에이전트 검증 루프]
H4[HTTP
웹훅 호출]
H5[function
JS 실행]
end
E2 -->|메시지 전송마다| Auto[자동으로 첨부]
Auto --> A1[테스트 출력]
Auto --> A2[최근 git diff]
Auto --> A3[파일 변경 목록]
classDef eventStyle fill:#c5dcef,stroke:#4a90d9,color:#333
classDef hookStyle fill:#c0ecd3,stroke:#3aaa6c,color:#333
classDef autoStyle fill:#fde8c0,stroke:#e6a817,color:#333
class E1,E2,E3,E4,E5,E6 eventStyle
class H1,H2,H3,H4,H5 hookStyle
class Auto,A1,A2,A3 autoStyleUserPromptSubmit이 특히 강력한 이유: 메시지를 보낼 때마다 자동으로 테스트 출력이나 최근 git diff를 붙일 수 있습니다. 매번 타이핑할 필요가 없어집니다.
예시: 메시지마다 git diff HEAD~1을 자동 첨부하는 Hook 설정:
{
"hooks": {
"UserPromptSubmit": [
{
"type": "command",
"command": "git diff HEAD~1 --stat 2>/dev/null || echo 'no git'"
}
]
}
}
6. 세션을 매번 새로 시작하지 마라
모든 대화가 JSONL 파일로 저장됩니다. 그 파일을 활용하는 3가지 방법이 있어요.
flowchart TD
Sessions[(JSONL 세션 파일들
모든 대화 저장)]
Sessions --> CMD1["--continue
마지막 세션 이어가기"]
Sessions --> CMD2["--resume
특정 세션 선택해서 열기"]
Sessions --> CMD3["--fork-session
과거 대화에서 분기"]
CMD1 --> Result1[어제 하던 작업 그대로 재개]
CMD2 --> Result2[지난주 특정 작업 복원]
CMD3 --> Result3[과거 시점에서 다른 방향 시도]
Sessions --> Memory[session memory 축적]
Memory --> M1[작업 내역]
Memory --> M2[파일 목록]
Memory --> M3[오류 기록]
Memory --> M4[학습한 것들]
classDef storageStyle fill:#c5dcef,stroke:#4a90d9,color:#333
classDef cmdStyle fill:#fde8c0,stroke:#e6a817,color:#333
classDef resultStyle fill:#c0ecd3,stroke:#3aaa6c,color:#333
classDef memStyle fill:#e0c8ef,stroke:#7b5ea7,color:#333
class Sessions storageStyle
class CMD1,CMD2,CMD3 cmdStyle
class Result1,Result2,Result3 resultStyle
class Memory,M1,M2,M3,M4 memStyle세션을 이어가면 session memory가 쌓입니다. 매번 새 세션을 여는 건 IDE를 매시간 껐다 켜는 것과 같습니다.
7. 도구가 60개 넘고, 읽기는 병렬, 쓰기는 순차다
소스코드에서 확인된 설계 원칙입니다.
flowchart TD
subgraph read["📖 읽기 작업 → 병렬"]
R[파일 10개 읽기 요청] --> R1[Read file1]
R --> R2[Read file2]
R --> R3[Read file3]
R --> RN[Read fileN]
R1 & R2 & R3 & RN --> RDone[✅ 동시 완료]
end
subgraph write["✏️ 쓰기 작업 → 순차"]
W[파일 3개 수정 요청] --> W1[Edit file1]
W1 --> W2[Edit file2]
W2 --> W3[Edit file3]
W3 --> WDone[✅ 순서대로 완료
충돌 방지]
end
classDef readStyle fill:#c0ecd3,stroke:#3aaa6c,color:#333
classDef writeStyle fill:#fde8c0,stroke:#e6a817,color:#333
classDef doneStyle fill:#c5dcef,stroke:#4a90d9,color:#333
class R,R1,R2,R3,RN readStyle
class W,W1,W2,W3 writeStyle
class RDone,WDone doneStyleMCP 서버 지연 로딩: 연결해놔도 실제로 사용하지 않으면 비용이 0입니다. 많이 연결해놓는 것을 두려워할 필요가 없어요.
8. 중간에 끊어도 손해가 없다
전체 파이프라인이 비동기 제너레이터 방식으로 구현되어 있습니다.
sequenceDiagram
participant U as 사용자
participant C as Claude Code
participant P as 파이프라인
U->>C: 작업 요청
C->>P: 비동기 스트림 시작
P-->>C: 스트림 청크 1
P-->>C: 스트림 청크 2
Note over U,P: 잘못된 방향 감지
U->>C: Escape (중단)
C->>P: 현재 스트림만 중단
Note over C: 이전 맥락은 그대로 보존
U->>C: 새 방향으로 재지시
C->>P: 새 스트림 시작
P-->>C: 올바른 방향으로 진행Escape를 누르면 현재 스트림만 깔끔하게 중단되고, 이전 맥락은 그대로 남습니다. 잘못된 방향으로 가고 있으면 기다리지 말고 바로 끊으세요. 페어 프로그래밍에서 “아, 그 방향 말고 이쪽으로"라고 말하는 것과 같습니다.
9. 결론: 프롬프트 실력이 아니라 설정 실력이다
소스코드를 보면 분명해지는 것이 있습니다.
“Claude Code를 잘 쓰는 사람들은 프롬프트를 잘 쓰는 게 아닙니다. 설정을 했고, 병렬로 돌렸고, Hook을 걸었고, 세션을 이어갔습니다.”
flowchart TD
Good[Claude Code 고수] --> G1[CLAUDE.md 계층 최적화]
Good --> G2[서브에이전트 병렬 실행]
Good --> G3[Hook으로 자동화]
Good --> G4[세션 연속성 유지]
Good --> G5[권한 glob 패턴 설정]
Good --> G6[/compact 수동 세이브]
Bad[Claude Code 초보] --> B1[프롬프트 잘 쓰기]
Bad --> B2[단일 에이전트]
Bad --> B3[권한 팝업 매번 클릭]
Bad --> B4[매번 새 세션]
Bad --> B5[컨텍스트 넘침 기다림]
Bad --> B6[Escape 두려움]
classDef goodStyle fill:#c0ecd3,stroke:#3aaa6c,color:#333
classDef badStyle fill:#ffc8c4,stroke:#e05050,color:#333
class Good,G1,G2,G3,G4,G5,G6 goodStyle
class Bad,B1,B2,B3,B4,B5,B6 badStyle이건 터미널 채팅이 아니라 에이전트 오케스트레이션 플랫폼이라는 게 소스코드에서 분명히 드러납니다.
핵심 요약
| # | 인사이트 | 실천 방법 |
|---|---|---|
| 1 | CLAUDE.md는 매 턴 재로딩 | 4만 자 계층 구조 최대 활용 |
| 2 | 병렬 에이전트 = 1개 비용 | fork/teammate/worktree 모델 활용 |
| 3 | 권한 팝업 = 설정 실패 | settings.json glob 패턴 + auto 모드 |
| 4 | 컨텍스트 압축 5전략 | /compact를 수동 세이브로 활용 |
| 5 | Hook = 진짜 확장 API | UserPromptSubmit으로 자동 첨부 |
| 6 | 세션은 JSONL로 영속 | –continue/–resume/–fork-session |
| 7 | 읽기 병렬, 쓰기 순차 | MCP 지연 로딩 부담 없이 연결 |
| 8 | Escape = 즉시 중단, 맥락 보존 | 잘못된 방향이면 바로 끊기 |
| 9 | 프롬프트 아닌 설정 실력 | 에이전트 오케스트레이션 플랫폼으로 인식 |
유출 소스코드 리포지토리: github.com/instructkr/claude-code
결론
소스코드 51만 줄이 말해주는 것은 명확합니다. Claude Code는 이미 완성된 에이전트 오케스트레이션 플랫폼인데, 대부분의 사람이 그 1%도 활용하지 못하고 있습니다.
CLAUDE.md 계층을 채우고, 서브에이전트를 병렬로 돌리고, Hook을 설정하고, 세션을 이어가는 것. 이 네 가지만 해도 Claude Code를 완전히 다른 도구로 경험하게 됩니다. 페라리의 기어를 올릴 준비가 됐다면, 설정 파일부터 시작하세요.