Claude Code Fundamentals for Practical Use: Basic Architecture & Tips
0. 들어가면서
Claude Code를 설치하고 아무 세팅 없이 바로 사용하기 시작하면 여러가지 문제들을 경험하게 됩니다.
이 포스팅과 함께 Claude Code 환경을 처음부터 최대한 올바르고 적절하게 구축해보고자 합니다. 각 설정이 왜 필요한지 이해하려면 Claude Code가 내부적으로 어떻게 동작하는지부터 알아야 합니다. 가장 먼저 Context Window의 실제 구조를 정확하게 짚고 이후 각 설정이 그 구조 안에서 어떤 역할을 하는지 순서대로 이어갑니다.
현재 작성한 포스트 기반으로 구축 후에 업무 및 개인 개발을 진행하면서 더 좋은 설정이나 내용상 수정할 부분들은 개선하면서 완성형 포스트를 만들 예정입니다.
1. Claude Code: Context Window
모든 설정을 이해하는 열쇠는 Claude Code가 매 응답을 생성할 때 무엇을 보고 있는가입니다.
Claude Code 터미널에서 /context 명령을 통해 현재 Context가 어떻게 구성되어 있는지 직접 확인할 수 있습니다.
![]()
1.1 Claude Code: CLAUDE.md & System Prompt
Anthropic API를 직접 호출할 때 system 파라미터에 CLAUDE.md 내용을 넣는 구조로 구현할 수 있습니다.
하지만 Claude Code 터미널의 실제 /context 출력을 보면 CLAUDE.md는 “System prompt” 영역이 아니라 “Memory files” 영역에 별도로 분류됩니다.
System prompt 영역은 Anthropic이 작성한 Claude Code 자체의 내장 지시문이 차지하며 사용자가 관여할 수 없습니다.
| 영역 | 내용 | 수정 가능 여부 |
|---|---|---|
| System prompt | Claude Code 내장 Agent 지시문 (Anthropic 제공) | ❌ 불가 |
| Memory files | CLAUDE.md (사용자 작성) | ✅ 가능 |
1.2 Context Window: Conception
MCP 서버는 System tools 영역에 합산되며 비용이 생각보다 크다.
- MCP 서버를 추가하면 해당 도구 정의가 System tools 수치에 포함됩니다. 사용하지 않는 MCP 서버를 켜두는 것만으로도 매 요청마다 수백~수천 토큰이 낭비됩니다.
Messages 영역이 Context 소진의 주범이다.
- Tool Call 한 번이 실행될 때마다 요청(Tool Call)과 결과(Tool Result)가 쌍으로 쌓입니다.
- 파일을 읽고 코드를 수정하고 빌드를 실행하는 작업 하나가 수십 개의 Tool Call 쌍으로 기록됩니다.
- Session이 길어질수록 Messages가 Context 대부분을 잠식하고 결국 자동 Compaction이 트리거됩니다.
Compaction은 Messages만 요약으로 대체하며 핵심 결정이 소실될 수 있다.
- Context Window가 Autocompact buffer 한계에 도달하면 Claude Code는 Conversation History를 압축된 요약으로 교체합니다.
- Memory files는 이 과정에서 영향받지 않습니다. 요약 과정에서 “PostgreSQL을 쓰기로 결정했다”나 “이 API는 멱등성이 보장되어야 한다” 같은 구체적인 결정 사항이 소실될 수 있습니다.
- 핵심 결정은 반드시 CLAUDE.md에 기록해두어야 합니다.
“Lost in the Middle” 문제로 Context 후반부 품질이 떨어진다.
- LLM은 Context의 앞부분과 끝부분에 더 많은 Attention을 부여하는 경향이 있습니다.
- Context Window 사용량이 80%를 넘어서면 중간에 위치한 정보가 상대적으로 덜 참조되어 메모리 집약적인 작업의 품질이 저하됩니다.
Prompt Caching은 Prefix가 동일할 때만 작동한다.
- Anthropic의 Prompt Caching은 이전 요청과 동일한 Byte-identical Prefix가 반복될 때 해당 토큰 처리를 캐시하여 비용과 지연을 줄입니다.
- System prompt, System tools, Memory files는 거의 변하지 않기 때문에 Cache hit rate가 높습니다.
- /model 명령어로 세션 중 모델을 전환하면 캐시가 무효화됩니다.
2. Architecture: 파일 구조 전체 그림
User Root
~/.claude/ ← 전역 (홈 디렉토리, git 공유 X)
├── CLAUDE.md ← 모든 프로젝트 공통 적용 개인 설정
├── settings.json ← 전역 개인 권한/설정
└── commands/ ← 전역 커스텀 슬래시 명령어
├── pr-review.md
├── commit.md
└── deploy-check.md
My Project Root
/project-backend/
├── CLAUDE.md ← 프로젝트 전체 규칙 (git 포함)
├── .claude/
│ ├── settings.json ← 팀 공유 권한 제어 (git 포함)
│ ├── settings.local.json ← 개인 로컬 전용 설정 (git 제외)
│ ├── agents/ ← 커스텀 서브에이전트 정의
│ │ └── backend-expert.md
│ ├── commands/ ← 프로젝트 커스텀 슬래시 명령어
│ │ ├── pr-review.md
│ │ ├── commit.md
│ │ └── deploy-check.md
│ └── notes/ ← 작업 기억 파일 (Session 간 상태 유지)
│ └── current-task.md
└── src/
└── analytics/
└── CLAUDE.md ← 특정 도메인에만 적용되는 규칙 (선택)
3. CLAUDE.md: Memory files
CLAUDE.md가 Context Window의 Memory files 영역에 배치된다는 것을 이해했다면 CLAUDE.md는 “항상 로드되는 프로젝트 기억”입니다.
- CLAUDE.md가 없으면 Claude Code는 프로젝트 구조, 기술 스택, 비즈니스 규칙, 코딩 컨벤션을 전혀 모른 채 범용 지식만으로 코드를 작성합니다.
- CLAUDE.md가 올바르게 설계되면 별도 설명 없이도 프로젝트 맥락을 유지하고 Compaction이 발생해도 핵심 결정사항은 다음 Session에서도 그대로 로드됩니다.
3.1 CLAUDE.md: 계층별 역할과 Prompt Caching
CLAUDE.md는 세 단계 계층으로 관리됩니다.
- Global 레벨 (
~/.claude/CLAUDE.md): 모든 프로젝트에 공통 적용되는 개인 설정 - Project 레벨 (프로젝트 루트의
CLAUDE.md): 해당 프로젝트의 아키텍처와 규칙 - Module 레벨 (서브디렉토리의
CLAUDE.md): 특정 도메인에만 적용되는 규칙
계층은 글로벌 → 프로젝트 루트 → 서브디렉토리 순으로 누적 로드되어 모두 합쳐져 Memory files에 포함됩니다.
- 전역 CLAUDE.md에 모든 도메인 규칙을 다 넣으면 무관한 정보까지 항상 Memory files에 쌓이면서 토큰을 낭비하고 응답 품질도 떨어집니다.
- 특정 도메인의 멱등성 보장, 분석 규칙, 보상 트랜잭션 같은 특수 규칙은
src/main/java/com/example/analytics/CLAUDE.md에만 두면, 해당 디렉토리에서 작업할 때만 로드됩니다.
이 계층 설계는 Prompt Caching과도 직결됩니다.
글로벌과 프로젝트 레벨 CLAUDE.md는 거의 변하지 않기 때문에 Byte-identical Prefix 조건을 안정적으로 충족합니다. Cache hit rate가 극대화되고 비용과 응답 속도 모두 개선됩니다.
여기서 중요한 제약이 있습니다.
- Attention 메커니즘 상 현재 Query(작업)와 관련도가 낮은 내용은 낮은 가중치를 받아 사실상 무시됩니다. 현업 기준으로 CLAUDE.md는 30~100줄 안에서 핵심만 유지하는 것이 권장됩니다.
- 200줄을 초과하면 Signal-to-Noise 비율이 떨어지고 불필요한 토큰 소비만 늘어납니다.
- Memory files 전체 예산도 10,000 토큰 이하로 유지하는 것이 좋습니다 (200k 컨텍스트의 5% 수준)
이 한계를 보완하는 것이 뒤에서 다룰 특정 Action 뒤에 무조건적으로 실행시키는 Hooks입니다.
3.2 User Root CLAUDE.md: 시스템 공통 적용정
시스템(글로벌) 레벨에는 프로젝트와 무관하게 특정 시스템 위에서 항상 원하는 행동 방식을 정의합니다. 언어 설정, 응답 스타일, 커밋 컨벤션처럼 모든 작업에 공통으로 적용할 규칙을 넣습니다.
프로젝트별로 다르거나 프로젝트 내에 특정 부분별 규칙을 여기에 넣으면 다른 프로젝트 또는 파일에도 불필요하게 로드되므로 반드시 분리해야 합니다.
Example: System (Global) CLAUDE.md
# 시스템 설정
## 언어 및 응답 방식
- 항상 한국어로 답변한다
- 코드 주석과 커밋 메시지는 영어로 작성한다
- 핵심 결론을 먼저 말하고 이유를 설명한다 (Bottom-line up front)
- 설명 시 코드 예시를 항상 포함한다
- 불필요한 경고나 면책 조항은 생략한다
## 커밋 메시지
- Conventional Commits 형식 준수
- type(scope): description 구조
- type: feat, fix, refactor, test, docs, chore, perf
3.3 Project CLAUDE.md: 구성 요소
프로젝트 레벨 CLAUDE.md에는 Claude가 코드만 읽어서는 절대 알 수 없는 정보를 담아야 합니다. 결정의 배경, 금지된 패턴, 팀이 합의한 이유가 없으면 Agent가 엣지 케이스마다 사람에게 물어보거나 잘못된 판단을 내립니다.
1) Architecture & Reason
- 결정의 이유가 없으면 Agent(Cursor)가 임의로 다른 선택을 합니다. 규칙만 나열하지 말고 이유를 함께 적어야 합니다.
2) Strictly Prohibited List & Reason
- 이유 없이 규칙만 나열하면 Agent가 엣지 케이스에서 잘못된 판단을 내릴 수 있습니다.
3) Tech Stack & Commands
- 어떤 기술을 쓰는지 명시하고 테스트와 빌드 명령어를 정확히 적어야 Agent가 검증 단계를 올바르게 실행합니다.
4) Directory Structure & Role
- 각 디렉토리가 어떤 책임을 가지는지 명시하면 Agent가 코드를 어디에 위치시킬지 스스로 판단합니다.
5) Coding Convention
Example: Project CLAUDE.md
# 프로젝트 설정
<!-- 1. Architecture & Reason -->
## 프로젝트 아키텍처
### DB: PostgreSQL (MySQL 아님)
이유: ...
### API 통신: REST (GraphQL 아님)
이유: ...
### ORM: JPA / Hibernate (MyBatis 아님)
이유: ...
<!-- 2. Strictly Prohibited List & Reason -->
## 절대 금지하는 목록
- build/, .gradle/ 디렉토리 수정 금지
- application-prod.yml, application-secret.yml 파일 읽기 및 내용 출력 금지
- 테스트 코드 수정 금지
→ 이유: 테스트는 스펙 문서이므로 구현 변경 시 테스트를 수정하지 않고 구현을 맞춘다
- DB 마이그레이션(Flyway/Liquibase) 직접 실행 금지
→ 이유: 프로덕션 스키마 변경은 DBA 승인 후 배포 파이프라인으로만 실행한다
- 프로덕션 브랜치(main, release)에 직접 Push 금지
<!-- 3. Tech Stack & Commands -->
## 기술 스택
- Language: Java 21 (LTS)
- Framework: Spring Boot 3.x
- Build: Gradle 8.x (Kotlin DSL)
- ORM: Spring Data JPA / Hibernate 6
- DB: PostgreSQL 15, Redis 7
- Test: JUnit 5, Mockito, Testcontainers
## 주요 명령어
- 빌드: ./gradlew build
- 빌드 (테스트 제외): ./gradlew build -x test
- 단위 테스트 전체 실행: ./gradlew test
- 특정 클래스 테스트: ./gradlew test --tests "com.example.payment.PaymentServiceTest"
- 특정 메서드 테스트: ./gradlew test --tests "com.example.payment.PaymentServiceTest.환불금액초과시예외발생"
- 통합 테스트: ./gradlew integrationTest (로컬 DB 또는 Testcontainers 구동 필수)
- 체크스타일 검사: ./gradlew checkstyleMain
- 코드 품질 검사: ./gradlew pmdMain
- 애플리케이션 실행: ./gradlew bootRun --args='--spring.profiles.active=local'
<!-- 4. Directory Structure & Role -->
## 디렉토리 구조
src/main/java/com/example/
├── domain/ # 도메인 엔티티, 도메인 서비스, Repository 인터페이스 (순수 비즈니스 로직)
├── application/ # UseCase(ApplicationService), 트랜잭션 경계, 도메인 조합
├── infrastructure/ # JPA Repository 구현체, 외부 API 클라이언트, 메시지 발행
├── interfaces/ # REST Controller, Request/Response DTO, 예외 핸들러
└── config/ # Spring 설정 클래스 (@Configuration), 환경별 Bean 정의
src/main/resources/
├── application.yml # 공통 설정
├── application-local.yml # 로컬 환경 설정
└── db/migration/ # Flyway 마이그레이션 스크립트 (직접 실행 금지)
<!-- 5. Coding Convention -->
## 코딩 컨벤션
- 모든 외부 입력은 @Valid + Jakarta Bean Validation 어노테이션으로 검증한다
- 예외는 반드시 커스텀 Exception 클래스로 래핑한다 (RuntimeException 직접 throw 금지)
- 비즈니스 로직은 ApplicationService 또는 Domain Service에만 위치한다
- Controller는 요청/응답 변환과 라우팅만 담당한다
- 로깅은 System.out.println 금지, SLF4J + Logback 사용 (@Slf4j)
- 주석은 '무엇을 하는가'가 아닌 '왜 이렇게 하는가'를 설명한다
- @Transactional은 ApplicationService 레이어에만 선언한다 (Controller, Repository 금지)
3.4 CLAUDE.md: 작업 완료 기준 (자동 품질 검사 지시문)
완료 기준을 명시하면 Claude가 이를 항상 만족해야 하는 강제 조건으로 인식하여 스스로 검증 단계를 실행합니다.
- 이 섹션이 없으면 Claude는 코드를 작성하고 나서 자체적으로 “완료”로 판단합니다.
- 실제로 빌드가 깨지거나 테스트가 실패하는 상태에서 응답이 끝나는 일이 생깁니다.
Example: Project CLAUDE.md
## 작업 완료 기준
코드 수정 후 다음 순서 실행 필수:
1. `./gradlew build -x test` → 컴파일 오류 없는지 확인 및 오류 있으면 즉시 수정
2. `./gradlew checkstyleMain` → 스타일 위반 없는지 확인 및 오류 있으면 즉시 수정
3. 수정한 클래스 관련 테스트: `./gradlew test --tests "com.example.[패키지].[클래스명]Test"`
**모두 통과해야만 작업 완료로 간주하고 내가 요청하지 않아도 자동 실행할 것**
3.5 CLAUDE.md: 작업 상태 기록 (Current Focus)
/clear로 Context를 초기화하거나 새 Session을 시작하면 Messages 영역이 초기화됩니다.
- Claude가 작업을 이어받으려면 현재 상태를 파악할 수 있는 정보가 필요합니다.
- CLAUDE.md는 Memory files 영역에 위치하여 Session 리셋에도 유지되므로 여기에 작업 상태를 기록해두면 맥락을 빠르게 복원할 수 있습니다.
Example: Project CLAUDE.md
## Current Focus
- [2026-02-24] 결제 모듈 환불 처리 로직 구현 중
- 관련 파일: src/main/java/com/example/payment/application/PaymentService.java
- 현재 이슈: PG사 웹훅 멱등성 처리 방식 결정 필요
- 결정된 사항: 환불은 별도 보상 트랜잭션으로 처리 (직접 취소 API 호출 금지)
- 다음 작업: RefundPolicy 도메인 객체 추가 후 PaymentServiceTest 작성
4. settings.json: 권한 제어 & 환경 설정
Claude Code를 제한 없이 사용하면 Agent가 의도치 않게 .env 파일을 읽거나 허용하지 않은 명령어를 실행하거나 민감한 디렉토리의 파일을 수정할 수 있습니다.
Prompt Injection이 발생했을 때 막을 수단도 없습니다.
명시적으로 허용된 도구와 명령어만 실행할 수 있게 설정하면 허용 목록에 없는 명령어는 아예 실행되지 않습니다.
4.1 settings.json: 팀 공유 설정 vs 개인 로컬 설정
-
settings.json은 팀 전체가 공유해야 하므로 git에 커밋합니다. 이 파일이 없으면 팀원마다 다른 권한 환경에서 작업하게 됩니다. -
settings.local.json은 개인 로컬 환경에서만 적용할 설정을 담으며.gitignore에 반드시 추가합니다.
Example: Project settings.json
{
"model": "...",
"permissions": {
"allow": [
"Bash(npm run *)",
"Bash(git status)",
"Bash(git diff *)",
"Bash(git add *)",
"Bash(git commit *)",
"Bash(npx prisma *)"
],
"deny": [
"Bash(rm -rf *)",
"Bash(curl *)",
"Bash(wget *)",
"Read(./.env)",
"Read(./.env.*)"
]
},
"env": {
"CLAUDE_AUTOCOMPACT_PCT_OVERRIDE": "80"
}
}
Example: Local settings.json
{
"permissions": {
"allow": [
"Bash(docker *)"
]
}
}
설정 우선순위(각 레벨의 deny 규칙은 하위 레벨의 allow를 덮어씁니다.)
- Managed settings(기업 관리 정책)
- 전역 시스템 설정(
~/.claude/settings.json) - 프로젝트 공유 설정(
.claude/settings.json) - 개인 로컬 설정(
.claude/settings.local.json)
4.2 settings.json: Least Privilege Principal
Agent에게는 현재 작업에 필요한 최소한의 권한만 부여해야 합니다. “일단 다 허용하고 나중에 막자”는 방식은 위험합니다.
- Bad Example :
"Bash(*)"— 모든 bash 명령을 허용 - Good Example :
"Bash(npm run *)","Bash(git *)","Bash(npx prisma *)"— 개별적으로 허용
4.3 settings.json: Human-in-the-loop Checkpoint
되돌리기 어려운 작업은 Agent에게 완전히 위임하면 안 됩니다.
- 자동 실행해도 안전한 작업: 코드 분석, 읽기 작업, 단위 테스트 실행, 린트 실행
- 반드시 사람이 승인해야 하는 작업: 패키지 설치/삭제, DB 마이그레이션 실행, 결제·이메일 같은 외부 API 실제 호출, 프로덕션 배포
4.4 settings.json: 모델 선택과 전환 전략
{
"model": "..."
}
- Sonnet로 충분한 작업: 코드 작성, 리팩토링, 버그 수정, 테스트 작성처럼 명확한 요구사항이 있는 작업
- Opus로 전환해야 하는 작업: 아키텍처 설계, 복잡한 버그의 근본 원인 분석, 여러 선택지 간의 심층 트레이드오프 분석
세션 중 /model 명령어로 모델을 전환하면 Prompt Cache 무효화가 발생합니다. 모델 전환이 필요한 작업은 별도 Session에서 진행하는 것이 비용 측면에서 유리합니다.
4.5 settings.json: MCP 설정
MCP 서버의 도구 정의는 System tools 수치에 합산됩니다.
/context출력에서 별도 항목으로 표시되지 않으므로 MCP 서버 추가 전후의 System tools 토큰 수를 비교하는 방식으로 소비량을 확인할 수 있습니다.- 사용하지 않는 MCP 서버를 켜두는 것만으로도 이 수치가 눈에 띄게 올라가므로 필요한 서버만 활성화하는 것을 지향합니다.
5. Custom Commands: 반복 작업의 자동화
코드 리뷰를 요청할 때마다 “보안 취약점, 성능 병목, 에러 처리 누락, 테스트 커버리지, 컨벤션 위반을 각각 심각도 레벨과 함께 보고해줘”라는 긴 지시를 반복해서 작성하면 사람마다 다른 방식으로 요청하기 때문에 결과 형식도 매번 달라집니다.
.claude/commands/review.md 파일을 한 번 만들어두면 이후 /project:review 한 줄로 동일한 작업이 실행되고 팀 전체가 git을 통해 동일한 명령어 세트를 공유하므로 결과 형식도 일관됩니다.
Custom Commands는 .claude/commands/ 디렉토리에 마크다운 파일로 정의합니다. review.md는 /project:review로 호출합니다.
~/.claude/commands/에 두면 전역 명령어로 모든 프로젝트에서 사용 가능합니다. $ARGUMENTS 플레이스홀더를 사용하면 명령어에 인자를 넘길 수 있습니다 (예: /project:fix-issue 123).
5.1 Custom Commands: 코드 리뷰 명령어
Example: ~/commands/review.md
# PR Code Review
다음 코드를 검토하고 아래 항목별로 결과를 서술해라.
## 검토 항목
1. 보안 취약점: SQL Injection, XSS, 인증 누락, 민감 정보 노출
2. 성능 병목: N+1 쿼리, 불필요한 루프, 메모리 누수 가능성
3. 에러 처리 누락: try-catch 누락, 예외 전파 미처리, 엣지 케이스 미고려
4. 테스트 누락: 커버리지가 필요하지만 없는 케이스
5. 컨벤션 위반: CLAUDE.md에 정의된 규칙 위반
## 보고 형식
각 항목별로 발견 내용, 파일 경로와 라인 번호, 심각도(High/Medium/Low), 개선 방향을 서술한다.
발견된 문제가 없으면 해당 항목은 "이상 없음"으로 기록한다.
5.2 Custom Commands: 커밋 메시지 생성 명령어
Example: ~/commands/commit.md
# Commit Message 생성
현재 staged된 변경사항을 git diff --staged로 확인하고
Conventional Commits 형식의 커밋 메시지를 작성해라.
형식: type(scope): description
- type: feat, fix, refactor, test, docs, chore, perf
- scope: 변경된 모듈명 또는 파일 범위
- description: 현재형 동사로 시작, 50자 이내, 영어 작성
변경 범위가 크거나 설명이 필요하면 body를 추가한다.
Breaking Change가 있으면 footer에 BREAKING CHANGE: 를 추가한다.
5.3 Custom Commands: 배포 전 체크 명령어
Example: ~/commands/deploy-check.md
# 배포 전 체크리스트
배포 전 다음 항목을 순서대로 확인하고 결과를 보고해라.
1. `npm run build` 실행 → 빌드 오류 없는지 확인
2. `npm run test` 실행 → 전체 테스트 통과 여부 확인
3. `npm run lint` 실행 → 린트 오류 없는지 확인
4. `.env.example` 파일과 실제 환경변수 키 일치 여부 확인
5. Prisma 스키마가 최신 마이그레이션과 일치하는지 확인
모든 항목이 통과되어야만 배포 준비 완료로 간주한다.
실패한 항목이 있으면 즉시 수정 후 재확인한다.
6. Hooks: CLAUDE.md 넘어서는 강제 실행
CLAUDE.md는 Claude가 무시할 수 있지만 Hooks는 Claude의 판단과 무관하게 지정된 이벤트가 발생할 때 무조건 실행됩니다.
- CLAUDE.md에 “작업 후 반드시 lint를 실행해라”고 적어도 Claude가 이를 건너뛸 수 있습니다.
- Hooks로 설정하면 Claude의 의지와 무관하게 지정 이벤트마다 코드가 실행됩니다.
Hook은 /hooks 인터랙티브 메뉴로도 생성할 수 있습니다.
- Claude Code CLI에서
/hooks를 입력하면 이벤트 선택 → matcher 설정 → 명령어 입력 순으로 단계별 안내가 제공됩니다.
6.1 Hooks: 전체 이벤트 종류
| 이벤트 | 실행 시점 | matcher 지원 | 주요 용도 |
|---|---|---|---|
PreToolUse |
도구 실행 직전 | ✅ tool name | 명령어 차단, 실행 전 검증, Tool Input 수정 |
PermissionRequest |
Claude가 권한 요청 팝업을 표시할 때 | ✅ tool name | 자동 승인/거부 로직 구현 |
PostToolUse |
도구 실행 완료 후 | ✅ tool name | 자동 포매팅, 테스트 자동 실행, 감사 로그 |
Notification |
Claude Code가 알림을 보낼 때 | ✅ permission_prompt / idle_prompt |
데스크탑 알림, Slack 알림 |
UserPromptSubmit |
사용자가 프롬프트를 제출한 직후, Claude 처리 전 | ❌ | 프롬프트 검증, Context 자동 주입, 위험 패턴 차단 |
Stop |
Claude가 응답을 완료하고 대기 상태가 될 때 | ❌ | 작업 완료 알림, 최종 검증 |
SubagentStop |
Sub-agent가 작업을 완료했을 때 | ❌ | Sub-agent 완료 처리 |
PreCompact |
Compaction 실행 직전 | ✅ manual / auto |
트랜스크립트 백업, 중요 정보 보존 |
SessionStart |
Session 시작 또는 재개 시 | ✅ startup / resume / clear / compact |
git status 로드, 환경 초기화, TODO 목록 주입 |
SessionEnd |
Session 종료 시 | ❌ | 상태 저장, 클린업, 로그 기록 |
SessionStart는 startup, resume, clear, compact matcher를 지원하므로 startup 시에만 무거운 Context 로드를 하고 /clear 이후 재개 시에는 다른 동작을 지정할 수 있습니다.
Example: /.claude/settings.json
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
...
}
]
}
],
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
...
}
]
}
],
"SessionStart": [
{
"matcher": "startup",
"hooks": [
{
...
}
]
}
]
}
}
6.2 Hooks: Process & Exit Code
Hook 명령어는 JSON 데이터를 stdin으로 받아 실행됩니다.
Exit 0 — 정상 실행
- raw stdout이 Claude Context에 직접 주입되는 이벤트는
UserPromptSubmit과SessionStart두 가지입니다. PostToolUse는 JSON 필드hookSpecificOutput.additionalContext를 통해 Claude Context에 정보를 전달합니다.- 그 외 이벤트에서 exit 0의 stdout은 verbose mode(Ctrl+O)에서 사용자에게만 표시되며 Claude는 보지 못합니다.
Exit 2 — 차단 오류(stderr 내용만 사용)
PreToolUse: 해당 Tool Call이 차단되고 stderr가 Claude에게 전달됩니다.PermissionRequest: 권한 요청이 거부되고 stderr가 Claude에게 전달됩니다.PostToolUse: 도구는 이미 실행된 상태이므로 차단되지 않으며 stderr가 Claude에게 전달됩니다.Stop: Claude의 응답 완료가 차단되고 stderr가 Claude에게 전달됩니다.Notification,PreCompact,SessionStart,SessionEnd: 차단 동작 없음. stderr가 사용자에게만 표시됩니다.
그 외 exit code — 비차단 오류(stderr는 verbose mode에서만 표시되고 실행은 계속됨)
- PostToolUse에서 Claude와 소통하는 두 가지 방법은 목적에 따라 명확히 구분해야 합니다.
- 단순 피드백 및 오류 전달이 목적이라면
exit 2 + stderr를 사용합니다. - Claude가 완료로 판단하고 멈추려는 것을 강제로 계속 실행시키려면
exit 0 + JSON { "decision": "block", "reason": "..." }을 사용합니다.
Security Consideration : Hook 명령어는 현재 사용자의 전체 권한으로 실행됩니다. 잘못된 Hook은 파일을 삭제하거나 시크릿을 노출시킬 수 있습니다. Hook을 프로덕션 코드와 동일한 수준으로 다루십시오. (No Sandbox)
7. Context: Manage Strategy
7.1 Context: /context
Context Window 구조를 실제로 확인하는 방법은 /context 명령입니다.
/context # 전체 Context 영역별 토큰 소비 확인 (색상 그리드로 사용량 시각화)
/cost # 현재 Session의 총 비용 확인
7.2 Context: /clear, /compact (Management)
Session이 길어지면 Context 대부분을 차지하는 상황이 지속되면 이전 결정이 사라지거나(Context Rot) Compaction이 반복 발생하고 Hallucination이 증가합니다.
![]()
/clear: 현재 Context를 완전히 초기화합니다.- Messages 영역만 초기화되고 Memory files(CLAUDE.md)는 그대로 유지됩니다.
- 독립된 새 작업으로 넘어갈 때 사용합니다.
/clear전에 핵심 결론을 CLAUDE.md 또는 notes 파일에 업데이트하는 것이 좋습니다.
/compact: 현재까지의 대화를 압축된 형태로 요약합니다.- 하나의 기능 구현이 완료되어 테스트까지 통과한 시점처럼 큰 작업 단위가 완료된 시점에 수동으로 실행하면 더 의미 있는 요약이 만들어집니다.
7.3 Context: Session 재개 방법
# 가장 최근 대화를 자동으로 재개 (같은 세션에 이어 붙임)
claude --continue
# 대화형 Session picker 또는 Session ID로 재개 (같은 세션에 이어 붙임)
claude --resume
claude --resume <session-id>
# 특정 시점에서 새 세션으로 분기 (기존 세션은 유지, 새 Session ID 발급)
claude --resume <session-id> --fork-session
![]()
이와 함께 .claude/notes/current-task.md 같은 파일 기반 기억 시스템을 구축하면 Session 간 상태를 더 명확하게 유지할 수 있습니다. SessionStart Hook으로 자동화하면 Session 시작 시 자동으로 이 파일이 Context에 주입됩니다.
7.4 Context: Compaction 운영 전략
Compaction에만 의존하면 안 됩니다. 자동 요약 과정에서 “우리는 PostgreSQL을 쓰기로 결정했다”나 “이 API는 멱등성이 보장되어야 한다” 같은 핵심 결정이 소실될 수 있습니다.
CLAUDE.md는 Memory files 영역에 위치하여 Compaction에 영향받지 않으므로 소실되면 안 되는 결정은 반드시 CLAUDE.md에 기록해야 합니다.
- Compaction이 잘 처리하는 것: 중간 시행착오 로그, 이미 완료된 구현 과정의 세부 내용
- CLAUDE.md에 수동 기록이 필요한 것: 아키텍처 결정과 그 이유, 팀이 합의한 컨벤션, 특정 방식을 선택한 배경
CLAUDE_AUTOCOMPACT_PCT_OVERRIDE로 Compaction 트리거 시점을 조정할 수 있습니다.
- 공식 기본값은 95이며 80으로 낮추면 Context Window가 80% 찼을 때 자동 압축이 시작됩니다.
- 더 일찍 압축하면 여유 컨텍스트가 많이 남아 있어 요약 품질이 향상됩니다.
- 다만 너무 낮게 설정하면 Compaction이 너무 자주 발생하여 Cache 무효화 비용 늘어납니다.
{
"env": {
"CLAUDE_AUTOCOMPACT_PCT_OVERRIDE": "80"
}
}
8. Prompt Engineering
8.1 Prompt Engineering: Plan Mode
복잡한 작업 전에 Plan Mode를 활용하면 Claude가 실제로 코드를 수정하기 전에 접근 방법을 먼저 제안합니다.
Plan Mode는 read-only 도구만 사용하기 때문에 파일 수정 및 빌드 실행에서 발생하는 Tool Call 쌍이 쌓이지 않아 Messages 영역 누적이 크게 줄어드는 부수 효과가 있습니다.
Plan Mode 진입 방법은 두 가지입니다.
- 새 Session 시작 시
claude --permission-mode plan플래그를 사용 - Session 진행 중
Shift+Tab을 두 번 눌러 Normal → Auto-accept → Plan Mode 순으로 전환합니다.
8.2 Prompt Engineering: 작업 범위를 파일 경로 수준으로 명시
Example: User Prompt
# Bad Prompt
"결제 관련 버그 수정해줘"
# Good Prompt
"src/payment/payment.service.ts의 processRefund 함수에서
환불 금액이 원래 결제 금액을 초과할 때 예외 처리가 없는 버그를 수정해줘.
다른 파일은 건드리지 마."
8.3 Prompt Engineering: 구체적인 스펙 기반 프롬프트
Example: User Prompt
# Bad Prompt
"로그인 기능 만들어줘"
# Good Prompt
"src/auth/login.service.ts 파일에 다음 스펙으로 로그인 기능을 구현해줘:
- 입력: email(string), password(string)
- 처리: bcrypt로 패스워드 검증, JWT 액세스 토큰(15분) + 리프레시 토큰(7일) 발급
- 출력: { accessToken: string, refreshToken: string, user: UserDto }
- 실패 케이스: 이메일 없음 → 404, 패스워드 불일치 → 401
- 리프레시 토큰은 Redis에 저장 (key: refresh:{userId}, TTL: 7일)
- 완료 후 lint와 type-check 실행"
8.4 Prompt Engineering: Output 토큰 제어
Output 토큰은 Input의 약 3~5배 비쌉니다. 필요 이상의 길이를 요청하지 않는 것이 중요합니다.
- 비효율 : “이 아키텍처에 대해 자세히 설명해줘”
- 효율 : “이 아키텍처의 핵심 트레이드오프 3가지만 서술해줘”
9. Summary: Basic Setting CheckList
1. 파일 구조 생성
2. 전역 CLAUDE.md 작성 (~/.claude/CLAUDE.md)
- 언어 설정, 응답 방식, 커밋 컨벤션 등 개인 공통 설정
- 30~100줄 이내로 유지 (경험적 권장)
- Memory files 예산: 전체 합산 10,000 토큰 이하
3. 프로젝트 CLAUDE.md 작성 (프로젝트 루트/CLAUDE.md)
- 아키텍처 결정 기록 (ADR, 이유 포함)
- 절대 금지 목록 (이유 포함)
- 기술 스택 및 실행 명령어
- 디렉토리 구조 및 역할
- 코딩 컨벤션
- 작업 완료 기준 (자동 품질 검사)
- Current Focus 섹션
4. .claude/settings.json 작성 (git 포함)
- 모델 설정
- permissions allow/deny
- CLAUDE_AUTOCOMPACT_PCT_OVERRIDE: "80"
5. .claude/settings.local.json 작성 (.gitignore에 추가)
- 개인 로컬에서만 필요한 추가 허용 명령어
6. Hooks 설정 (.claude/settings.json)
- PostToolUse(Edit|Write): 파일 저장 시 자동 포매팅
- PreToolUse(Bash): 위험 명령어 차단
- SessionStart(startup): git status + 작업 기록 자동 주입
- PreCompact(auto): transcript_path를 파싱해 트랜스크립트 백업
7. Custom Commands 작성 (.claude/commands/)
- pr-review.md, commit.md, deploy-check.md 등
8. 작업 기억 파일 생성 (.claude/notes/current-task.md)
- 현재 작업 상태, 결정 사항 기록
9. 세팅 후 검증
- /context 실행 → 각 영역별 토큰 소비 확인
- MCP tools 영역이 과도하게 크다면 미사용 서버 비활성화
- Memory files가 10,000 토큰을 초과한다면 CLAUDE.md 분리 재검토
✅ Conclusion
- Claude Code의 초기 세팅은 한 번 제대로 해두면 그 이후 모든 작업의 품질과 효율을 결정합니다.
- Context Window의 구조 위에서 각 설정의 역할이 명확해집니다.
CLAUDE.md가 Memory files 영역에서 프로젝트 맥락을 고정하고settings.json이 Claude가 할 수 있는 것과 없는 것의 경계를 설정하고Hooks가 그 경계를 Claude의 판단과 무관하게 강제로 지킵니다.Custom Commands는 반복 작업을 일관된 형태로 자동화하고 Context 관리 전략은 긴 작업에서 Session이 오염되는 것을 방지합니다. - 해당 포스트에서 아직 다루지 못한 Sub Agent, Skills, MCP 관련 부분들은 기본 구축을 진행하면서 추가적으로 포스팅할 예정입니다.