Claude Code를 활용하면서 개발 속도는 확실히 빨라졌습니다.
코드 생성, 리팩토링 같은 반복 작업을 넘어서 구조 설계까지 AI를 활용하는 것이 자연스러워졌습니다.
하지만 속도가 빨라진 만큼, 결과물의 품질이 항상 일정하게 유지되지는 않습니다.
특히 아무 준비 없이 바로 구현을 요청했을 때, 다음과 같은 문제가 자주 발생합니다.
- 현재 코드 컨텍스트를 충분히 반영하지 못한 구조 생성
- 레이어 책임이 섞인 코드 (ViewModel에 네트워크 로직 포함 등)
- 기존 아키텍처(MVVM, Clean Architecture)와 맞지 않는 설계
- 불필요하게 긴 코드 생성으로 인한 토큰 낭비
- 이전 대화 맥락이 오염되면서 점점 일관성이 깨지는 문제
이런 상태에서 수정을 반복하게 되면, 단순 구현보다 오히려 더 많은 시간과 토큰을 소비하게 됩니다.
그래서 중요한 것은 코드를 먼저 생성하는 것이 아니라, 설계부터 만드는 흐름입니다.
이때 사용하는 방식이 바로 Plan Mode입니다.
이번 포스팅에서는 Plan Mode를 활용해 개발 품질까지 확보하는 방법을 정리합니다.
Plan Mode란?
Plan Mode는 Claude Code가 코드를 바로 생성하지 않고, 분석과 계획 수립에만 집중하는 단계입니다.
일반적으로 AI에게 구현을 요청하면 현재 구조를 충분히 반영하지 못한 채 코드부터 생성되기 시작합니다.
반면 Plan Mode에서는 코드를 작성하는 대신, 구현에 앞서 문제를 분석하고 설계를 검토하는 과정에 집중합니다.
이 단계에서 AI는 다음과 같은 작업을 수행합니다.
- 코드베이스를 읽고 현재 구조를 파악
- 아키텍처 흐름과 의존성 관계 분석
- 기능 구현을 위한 설계 및 작업 계획 수립
중요한 점은, 이 과정이 완전히 read-only로 동작한다는 것입니다.
파일 수정, 명령어 실행, 코드 변경은 모두 제한되며
개발자가 플랜을 승인하기 전까지는 아무것도 변경되지 않습니다.
이러한 흐름은 다음과 같은 워크플로우로 이어집니다.
여기서 중요한 포인트는, Plan Mode가 단순히 “설계를 먼저 해보자” 수준이 아니라는 점입니다.
이 단계는 AI가 어떤 기준으로 코드를 생성해야 하는지를 미리 고정하는 과정입니다.
한 번 기준이 정리되면 이후 흐름이 완전히 달라집니다.
- 불필요한 코드 재생성이 줄어들고 → 토큰 사용량이 절약됨
- 구조가 고정되면서 응답의 일관성이 유지됨
- 기존 아키텍처가 깨지지 않음
- 수정이 아닌 “구현” 중심으로 작업이 진행됨
결과적으로, 단순히 빠르게 만드는 것이 아니라 안정성과 유지보수성까지 고려된 결과물을 얻을 수 있습니다.
Plan Mode 실행 방법

Claude Code는 일반 모드 → Auto-Accept 모드 → Plan Mode 순으로 전환됩니다.
Plan Mode 사용 방법
1. 계획 수립 후 즉시 구현
Plan Mode 진입 → 기능 설명 → 코드베이스 분석 및 플랜 제시 → 검토 및 수정 → 승인 → 구현
실제로 이렇게 입력합니다.
"WatchConnectivity로 심박수 데이터 실시간 싱크 기능을 추가하려고 해.
현재 Watch 연동 구조를 먼저 파악하고,
어떤 파일을 수정해야 하는지, 작업 순서를 계획해줘."
Claude는 코드베이스를 읽고 아래와 같은 형태로 플랜을 제시합니다.
분석 결과:
- WatchSessionManager.swift: WCSession 초기화 담당
- HealthDataRepository.swift: 아직 Watch 연동 없음
구현 계획:
1. WatchSessionManager에 HKWorkout 수신 핸들러 추가
2. HealthDataRepository에 Watch → 앱 데이터 브릿지 구현
3. RunningViewModel에서 실시간 업데이트 구독
계획을 검토하고 승인하면 그때 코드 작성이 시작됩니다.
이 방법은 작은 단위의 작업에서 사용합니다.
2. 파일 기반 구현
복잡한 기능이라면 이 방법이 더 체계적이고 확장 가능한 접근법입니다.
흐름은 세 단계입니다.
- 상세 스펙 문서 작성: Plan Mode에서 구현 스펙을 문서로 작성합니다.
- 스펙 파일 저장: 계획을 plan.md 과 같은 형태로 저장합니다.
- 스펙 기반 구현: 저장된 스펙을 기반으로 Claude Code가 단계별로 구현합니다.
Plan Mode에서 Claude가 계획을 제시하면, "이 계획을 plan.md로 저장해줘" 라고 요청합니다.
Claude가 직접 파일을 생성해줍니다.
## plan.md 예시
### 목표
WatchConnectivity로 실시간 심박수 데이터를 iOS 앱에 싱크
### 분석 결과
- WatchSessionManager.swift: WCSession 초기화만 있고 데이터 수신 없음
- HealthDataRepository.swift: Watch 연동 로직 미구현
- RunningViewModel.swift: 실시간 업데이트 구독 필요
### 구현 계획
1. WatchSessionManager에 HKWorkout 수신 핸들러 추가
2. HealthDataRepository에 Watch → 앱 데이터 브릿지 구현
3. RunningViewModel에서 실시간 업데이트 구독
### 완료된 작업
- 프로젝트 구조 설계
- CoreData 스키마 정의
### 진행 중인 작업
- WatchConnectivity 연동
- 실시간 심박수 UI 업데이트
이후 세션이 끊겨도 새 세션에서 "plan.md 읽고 미완료 항목 이어서 구현해줘" 한 마디면 컨텍스트가 복구됩니다.
단, 작업이 완료돼도 plan.md는 자동으로 갱신되지 않습니다.
Claude Code는 명시적으로 요청하지 않으면 플랜 파일을 건드리지 않기 때문입니다.
이를 해결하는 가장 좋은 방법은 CLAUDE.md에 규칙을 명시해두는 것입니다.
## 작업 규칙
- 작업 완료 시 plan.md의 해당 항목을
'완료된 작업'으로 이동시킬 것
- 새 세션 시작 시 plan.md를 먼저 읽고
현재 진행 상황을 파악할 것
CLAUDE.md는 프로젝트 루트에 두고 Git에 커밋해두면 팀원 전체가 동일한 규칙을 공유할 수 있습니다.
덕분에 세션이 끊기거나 팀원이 작업을 이어받아도 AI를 매개로 한 협업에서 작업 현황이 항상 동기화된 상태로 유지됩니다.
3. plan.md를 기능별로 분리하기
프로젝트 규모가 커지면 단일 plan.md에 모든 스펙을 담는 것이 오히려 독이 될 수 있습니다.
단일 plan.md에 모든 스펙이 담겨 있으면, 특정 기능 작업을 요청할 때도 파일 전체를 참조하게 됩니다.
파일이 커질수록 불필요한 정보까지 컨텍스트에 올라가고, AI의 집중도가 떨어지는 문제가 생깁니다.
MyProject/
├── CLAUDE.md # 전역 규칙 (항상 읽힘)
├── plans/
│ ├── _overview.md # 전체 진행 현황 인덱스
│ ├── watch_connectivity.md
│ ├── running_viewmodel.md
│ └── naver_maps.md
이 구조의 핵심은 _overview.md입니다. 각 기능의 진행 상태를 한눈에 파악할 수 있는 인덱스 역할을 합니다.
## 전체 진행 현황
| 기능 | 파일 | 상태 |
|------|------|------|
| WatchConnectivity | plans/watch_connectivity.md | 진행중 |
| RunningViewModel | plans/running_viewmodel.md | 완료 |
| Naver Maps | plans/naver_maps.md | 미시작 |
새 세션을 시작할 때 "_overview.md 읽고 진행중인 기능 이어서 해줘" 한 마디면, Claude가 필요한 plan 파일만 골라서 읽습니다.
불필요한 컨텍스트 없이 정확하게 작업을 이어갈 수 있습니다.
CLAUDE.md에는 다음 규칙을 추가합니다.
## 작업 규칙
- 세션 시작 시 plans/_overview.md 먼저 읽기
- 해당 기능의 plan 파일만 추가로 읽기
- 작업 완료 시 해당 plan 파일 업데이트 후 _overview.md 상태 반영
Plan Mode 심화 사용
1. 메타 프롬프팅
메타 프롬프팅이란, "이 작업을 해줘" 대신 "이 작업을 잘 수행할 프롬프트를 설계해줘"라고 요청하는 방식입니다.
Plan Mode에서 파일을 수정하지 않는다는 특성을 활용해, 먼저 프롬프트 자체를 다듬고 그 결과를 실제 구현에 재사용합니다.
다음 작업을 위한 최적의 프롬프트를 생성해 줘
<task>
RunCoach 앱의 AI 음성 코칭 응답 지연 개선
</task>
<context>
- 현재 이슈: Claude API 호출 후 음성 출력까지 2.3초 지연
- 사용 기술: Swift, AVFoundation, Anthropic Claude API
- 목표: 1초 이내 첫 음성 출력
</context>
<output_requirements>
1. 구체적이고 실행 가능한 프롬프트
2. 단계별 분석 절차 포함
3. 성능 측정 방법 명시
4. 검증 기준 제시
</output_requirements>
[Plan Mode에 입력하는 프롬프트]
RunCoach의 음성 코칭 응답 지연을 개선해줘.
## 현재 상황 분석
다음 파일들을 먼저 검토해:
- CoachingService.swift (API 호출 로직)
- SpeechSynthesizer.swift (TTS 처리)
- RunSessionViewModel.swift (흐름 제어)
## 개선 방향 (우선순위 순)
1. Streaming API 적용 — 응답 완료 전에 첫 문장부터 TTS 시작
2. 프롬프트 토큰 수 최소화 — 불필요한 컨텍스트 제거
3. TTS 엔진 선택 — AVSpeechSynthesizer vs 외부 TTS 레이턴시 비교
## 성능 측정 기준
- API 첫 토큰 수신까지: < 500ms
- 첫 음성 출력까지: < 1000ms
- Instruments Time Profiler로 각 단계 측정
## 검증
개선 전후 측정값을 코드 주석에 기록해줘.
[Plan Mode가 설계해준 프롬프트]
Plan Mode가 태스크 구조를 파악해 파일 탐색 순서, 구현 우선순위, 측정 기준까지 포함된 실행 가능한 프롬프트로 변환해줬습니다.
이걸 복사해서 일반 모드에 바로 붙여 넣어도 되고, 다시 Plan Mode에 입력해 구현 계획을 수립한 뒤 plan.md로 저장해 활용할 수도 있습니다.
2. 확장된 사고 모드
사고 깊이를 직접 지정할 수 있습니다.
think → 기본 분석
think hard → 심층 분석
think harder → 더 깊은 분석
ultrathink → 최대 심층 분석
프롬프트 끝에 키워드를 붙이면 됩니다.
"현재 네트워크 레이어의 에러 핸들링 구조를 분석하고
개선 방안을 제시해줘. ultrathink"
아키텍처 설계나 복잡한 의존성 분석처럼 판단이 많이 필요한 작업에 유효합니다.
단, 사고 깊이가 깊어질수록 내부적으로 소모하는 토큰이 늘어납니다.
ultrathink는 그만큼 응답이 느려지고 비용도 올라가기 때문에, 단순한 작업에 무조건 붙이는 건 비효율적입니다.
복잡도에 맞게 골라 쓰는 것이 핵심입니다.
모델 전략적 분리 - Opus로 계획, Sonnet으로 실행
Claude Code에서는 작업 성격에 따라 모델을 나눠 쓰는 것만으로도 토큰 비용을 크게 줄일 수 있습니다.
Opus → 설계, 아키텍처 분석, 복잡한 의사결정
Sonnet → 코드 작성, 파일 수정, 반복 구현
Plan Mode에서 Opus로 전환해 구현 계획을 수립하고, 계획이 확정되면 Sonnet으로 전환해 실제 코드를 작성합니다.
판단이 필요한 구간에만 Opus를 쓰고, 나머지는 Sonnet에 맡기는 방식입니다.
앞서 소개한 plan.md 방식과 조합하면 더 효과적입니다.
Opus가 수립한 계획을 plan.md로 저장해두면, Sonnet은 그 파일만 읽고 군더더기 없이 구현에 집중할 수 있습니다.
'AI' 카테고리의 다른 글
| 하네스 엔지니어링 🐴 (0) | 2026.04.24 |
|---|---|
| Claude Code 반복작업으로 부터 토큰 낭비를 없애는 가장 확실한 방법 (CLAUDE.md) (0) | 2026.04.22 |
| Claude Code가 느려지는 이유와 컨텍스트 관리 전략 (1) | 2026.04.21 |