시리즈 이전 편: [Part 0] 소스코드 51만 줄이 유출됐다
목차
- 1,900개 파일, 어떻게 정리했을까
- 전체 디렉토리 구조
- 핵심 디렉토리 5개 해부
- src/tools/ — LLM이 사용하는 도구들
- src/commands/ — 사용자가 치는 슬래시 명령어
- src/components/ — 터미널 UI의 모든 것
- src/services/ — 외부 세계와의 접점
- src/entrypoints/ — 앱이 시작되는 곳
- 진입점 흐름: cli.tsx -> init.ts -> main.tsx
- 그래서 뭐가 달라지나 -- 구조 설계 교훈
1,900개 파일, 어떻게 정리했을까
Claude Code의 src/ 디렉토리 안에는 정확히 1,920개의 파일이 들어 있습니다. 이 정도 규모면 아무리 잘 만든 프로젝트라도 디렉토리 구조가 엉망이면 개발자가 파일 하나 찾는 데 5분씩 쓰게 됩니다.
Anthropic 엔지니어들은 이걸 어떻게 정리했을까요? 실제 소스를 열어보니, 예상보다 훨씬 체계적이었습니다. 오늘은 디렉토리 구조만 집중적으로 뜯어보겠습니다.
전체 디렉토리 구조
src/ 아래 최상위 디렉토리는 총 30개입니다. 핵심만 추리면 아래와 같습니다.
src/
entrypoints/ # 진입점 (cli.tsx, init.ts, mcp.ts)
main.tsx # CLI 메인 로직 (Commander.js 기반)
tools/ # 40개 도구 (BashTool, FileReadTool, GrepTool...)
commands/ # 102개 슬래시 명령어 (/commit, /compact, /config...)
components/ # React(Ink) UI 컴포넌트 389개
services/ # API, MCP, OAuth, LSP 등 외부 연동
constants/ # 시스템 프롬프트, 설정값
hooks/ # React 훅
state/ # 전역 상태 관리
utils/ # 유틸리티 함수
bootstrap/ # 초기화 단계 상태 셋업
context/ # 프로젝트 컨텍스트 감지
types/ # TypeScript 타입 정의
...
눈에 띄는 건 tools/와 commands/가 명확히 분리되어 있다는 점입니다. 도구(LLM이 호출하는 것)와 명령어(사용자가 /로 호출하는 것)는 완전히 다른 디렉토리에 삽니다.
핵심 디렉토리 5개 해부
src/tools/ — LLM이 사용하는 도구들
파일 수: 184개 | 도구 수: 40개
tools/
BashTool/
FileReadTool/
FileEditTool/
FileWriteTool/
GrepTool/
GlobTool/
AgentTool/
WebFetchTool/
WebSearchTool/
MCPTool/
TaskCreateTool/
ToolSearchTool/
...
각 도구는 독립된 폴더 안에 구현 파일, 테스트 파일, 유틸리티가 함께 들어갑니다. 이건 전형적인 "feature-based 구조"입니다. 도구 하나를 수정할 때 다른 폴더를 건드릴 일이 거의 없습니다.
src/commands/ — 사용자가 치는 슬래시 명령어
파일 수: 209개 | 명령어 수: 102개
/commit, /compact, /config, /clear 같은 슬래시 명령어가 여기 있습니다. agents, bridge, chrome 같은 하위 폴더도 보이는데, 복잡한 명령어는 자체 디렉토리를 가집니다.
| 구분 | tools/ | commands/ |
|---|---|---|
| 호출 주체 | LLM (Claude) | 사용자 (슬래시 입력) |
| 예시 | BashTool, GrepTool | /commit, /compact |
| 구조 | 도구당 폴더 1개 | 명령어당 파일 또는 폴더 |
| 파일 수 | 184개 | 209개 |
src/components/ — 터미널 UI의 모든 것
파일 수: 389개
Claude Code의 터미널 UI는 React + Ink로 만들어져 있습니다. App.tsx, AutoUpdater.tsx, BridgeDialog.tsx 같은 이름을 보면, 일반적인 웹 프론트엔드 프로젝트와 구조가 거의 같습니다. 터미널인데 React라니 -- 이 부분은 나중 편에서 더 파겠습니다.
src/services/ — 외부 세계와의 접점
파일 수: 136개
services/
api/ # Anthropic API 호출
mcp/ # MCP 서버 연동
oauth/ # OAuth 인증
lsp/ # Language Server Protocol
analytics/ # 텔레메트리, GrowthBook
compact/ # 컨텍스트 압축
policyLimits/ # 사용량 제한
...
API 호출, 인증, MCP 프로토콜, LSP 연동이 모두 여기 모여 있습니다. tools/가 "무엇을 할 수 있는가"라면 services/는 "외부와 어떻게 통신하는가"입니다.
src/entrypoints/ — 앱이 시작되는 곳
파일 수: 8개
entrypoints/
cli.tsx # 최초 진입점
init.ts # 초기화 로직
mcp.ts # MCP 서버 모드 진입점
sdk/ # Agent SDK 진입점
agentSdkTypes.ts
sandboxTypes.ts
겨우 8개 파일이지만, 여기가 모든 것의 시작점입니다. 다음 섹션에서 흐름을 따라가 봅니다.
진입점 흐름: cli.tsx -> init.ts -> main.tsx
Claude Code를 실행하면 어떤 순서로 파일이 로드될까요?
1단계: cli.tsx -- 빠른 분기 처리
// src/entrypoints/cli.tsx
async function main(): Promise<void> {
const args = process.argv.slice(2);
// Fast-path for --version/-v: zero module loading needed
if (args.length === 1 && (args[0] === '--version' || args[0] === '-v')) {
console.log(`${MACRO.VERSION} (Claude Code)`);
return;
}
const { profileCheckpoint } = await import('../utils/startupProfiler.js');
profileCheckpoint('cli_entry');
// ...
--version 같은 간단한 플래그는 모듈을 하나도 로드하지 않고 바로 응답합니다. 주석에 "zero module loading"이라고 적혀 있을 정도로, 시작 속도에 집착하는 모습이 보입니다.
2단계: init.ts -- 초기화
설정 로드, OAuth 인증 확인, 텔레메트리 셋업, LSP 서버 준비, 프록시 설정 등 "무거운 준비 작업"이 여기서 일어납니다. import 목록만 봐도 40줄이 넘습니다.
3단계: main.tsx -- 본격 실행
// src/main.tsx
profileCheckpoint('main_tsx_entry');
startMdmRawRead(); // MDM 설정 병렬 읽기
startKeychainPrefetch(); // macOS 키체인 병렬 프리페치
main.tsx는 시작하자마자 MDM 설정 읽기와 키체인 프리페치를 병렬로 실행합니다. 모듈 import가 ~135ms 걸리는 동안 이 작업들이 백그라운드에서 돌아가도록 설계한 겁니다. Commander.js로 CLI 옵션을 파싱하고, 최종적으로 React(Ink) REPL을 띄웁니다.
그래서 뭐가 달라지나 -- 구조 설계 교훈
1,920개 파일을 관리하는 이 프로젝트에서 배울 점을 정리하면 이렇습니다.
feature-based 폴더 구조를 쓴다. tools/BashTool/ 안에 구현, 테스트, 유틸리티가 다 들어갑니다. controllers/, models/, views/ 식의 레이어 분리가 아닙니다. 도구 40개가 서로 간섭 없이 독립적으로 존재할 수 있는 이유입니다.
호출 주체로 디렉토리를 나눈다. LLM이 호출하는 건 tools/, 사용자가 호출하는 건 commands/. 이 구분이 없으면 "이 코드를 누가 부르는 거지?"라는 질문에 매번 코드를 뒤져야 합니다.
진입점을 극도로 가볍게 만든다. cli.tsx는 fast-path 분기만 처리하고, 무거운 import는 전부 dynamic import로 미룹니다. 0.5초 안에 터미널에 반응을 보여주려는 설계입니다.
services와 tools를 분리한다. "무엇을 할 수 있는가(tools)"와 "외부와 어떻게 통신하는가(services)"를 섞지 않습니다. 덕분에 도구를 추가할 때 API 통신 코드를 건드릴 필요가 없습니다.
다음 편에서는 이 구조 위에서 실제로 부팅이 어떻게 일어나는지, 0.5초 안에 무슨 일이 벌어지는지를 코드 레벨로 추적합니다.
다음 편 예고: [Claude Code 해부학 Part 2] 클로드 코드(Claude Code) 부팅 과정 분석 — 실행하면 0.5초 안에 벌어지는 일들
[Claude Code 해부학] 시리즈
- Part 0: 소스코드 51만 줄이 유출됐다
- Part 2: 부팅 과정 분석
- Part 3: 시스템 프롬프트 분석
'AI 코딩 에이전트' 카테고리의 다른 글
| Claude Code 시스템 프롬프트 분석: 915줄은 어떻게 조립되는가 (해부학 Part 3) (0) | 2026.04.01 |
|---|---|
| Claude Code 부팅 과정 분석: 실행 후 0.5초 안에 벌어지는 일들 (해부학 Part 2) (0) | 2026.04.01 |
| Claude Code BashTool 분석: 도구 프롬프트가 500줄인 이유 (해부학 Part 7) (0) | 2026.04.01 |
| Claude Code 소스코드 51만 줄 전체 분석: 유출된 코드를 전부 뜯어본다 (해부학 Part 0) (0) | 2026.04.01 |
| Notion AI로 회의록 자동 정리하는 방법 — 실제 사용 후기 (0) | 2026.03.31 |
