Claude Code는 괴물이다 - 6개월간의 집중 사용에서 얻은 팁
원문: Claude Code is a Beast — Tips from 6 Months of Heavy Usage
들어가며
게으른 사람을 위한 꿀팁: 이 긴 글을 ElevenLabs Reader나 Natural Reader 같은 TTS AI 서비스에 넣으면 읽어줍니다 :)
수정: 많은 분들이 레포지토리를 요청해서 며칠 내로 올리려고 합니다. 현재 회사 프로젝트의 일부라서 새 프로젝트에 복사하고 식별 정보를 지우는 데 시간이 좀 걸립니다. 올리면 여기에 링크를 공유하겠습니다.
수정 (최종?): 오후 시간을 들여서 GitHub 레포를 만들었습니다.
🎯 Repository: https://github.com/diet103/claude-code-infrastructure-showcase
면책 조항
약 6개월 전에 Claude Code(클로드 코드)를 일주일간 집중적으로 사용한 후 경험을 공유하는 글을 올렸었다. 이제 6개월간의 집중 사용 후, 더 많은 팁과 트릭, 그리고 이런저런 이야기를 공유하고자 한다. 좀 과하게 썼을 수도 있으니, 커피 한 잔 들고 편하게 읽어주길 바란다.
먼저 면책 조항부터: 이 글의 모든 내용은 단순히 나에게 현재 가장 잘 작동하는 설정을 공유하는 것이며, 절대적인 진리나 유일한 정답으로 받아들여서는 안 된다. 이 글이 여러분의 AI 에이전트 코딩 설정과 워크플로우를 개선하는 데 영감을 주길 바랄 뿐이다. 나는 그냥 한 명의 개발자일 뿐이고, 이건 그냥 내 의견일 뿐이다.
또한, 나는 20x Max 플랜을 사용 중이므로 결과가 다를 수 있다. 그리고 vibe-coding 팁을 찾고 있다면 다른 곳을 찾아보길 바란다. CC(Claude Code)에서 최고의 결과를 얻으려면, 함께 작업해야 한다: 계획하고, 검토하고, 반복하고, 다양한 접근 방식을 탐색하는 등.
간단한 개요
6개월간 Claude Code를 한계까지 밀어붙이면서 (혼자서 30만 줄의 코드를 재작성하며) 구축한 시스템은 다음과 같다:
- 필요할 때 실제로 자동 활성화되는 Skills
- Claude가 맥락을 잃지 않도록 하는 Dev Docs 워크플로우
- 에러를 하나도 남기지 않는 PM2 + Hooks
- 리뷰, 테스트, 계획을 위한 전문화된 Agent 군단
자, 시작해보자.
배경
나는 약 7년간 프로덕션 웹 앱을 개발해온 소프트웨어 엔지니어다. 그리고 AI의 물결을 두 팔 벌려 환영했다. AI가 곧 내 일자리를 빼앗을 거라고 걱정하지 않는다. AI는 내 능력을 확장하는 도구이기 때문이다. 그 과정에서 Claude(클로드)와 GPT-5 Thinking을 활용해 많은 새로운 기능을 만들고, 우리 프로덕션 앱에 새로운 AI 시스템을 통합하는 다양한 제안서를 작성해왔다. AI를 워크플로우에 통합하기 전에는 시간이 없어서 고려조차 못 했을 프로젝트들이다. 이 모든 것 덕분에 상당한 직업 안정성을 확보했고, 다른 사람들이 AI 통합에서 약 1년 정도 뒤처져 있어서 회사의 AI 전문가가 되었다.
새로 얻은 자신감으로, 회사 내부 도구로 사용되는 웹 앱의 대규모 리디자인/리팩토링을 제안했다. 이건 내가 인턴 시절 개발한 프로젝트에서 포크된 상당히 조잡한 대학생 수준의 프로젝트였다 (원본은 약 7년 전에 만들어졌고, 포크된 건 4년 전). 이해관계자들에게 팔기 위해, 꽤 큰 규모의 프로젝트(~10만 LOC)를 몇 달 안에 완전히 재설계하겠다고 혼자서 동의했으니 좀 과한 야심이었을 수도 있다. CC의 도움이 있어도 추가 근무를 해야 한다는 걸 알고 있었다. 하지만 마음 깊은 곳에서는 이게 성공할 거라는 걸 알았다. 여러 수동 프로세스를 자동화하고 회사의 많은 사람들에게 많은 시간을 절약해줄 테니까.
6개월이 지났다... 그래, 아마 이 일정에 동의하지 말았어야 했다. 이걸 끝내려고 Claude와 내 정신력 모두를 한계까지 테스트했다. 모든 게 심각하게 구식이었고 최신 기술을 써보고 싶어서 기존 프론트엔드를 완전히 버렸다. React 16 JS → React 19 TypeScript, React Query v2 → TanStack Query v5, React Router v4 w/ hashrouter → TanStack Router w/ file-based routing, Material UI v4 → MUI v7로, 모두 베스트 프랙티스를 엄격히 준수하면서. 프로젝트는 이제 약 30-40만 LOC가 되었고 내 수명은 약 5년 줄었다. 마침내 테스트할 준비가 되었고, 결과에 매우 만족한다.
이건 감당할 수 없는 기술 부채, 테스트 커버리지 제로, 끔찍한 개발자 경험(테스트가 완전한 악몽이었다), 온갖 엉망인 것들이 있던 프로젝트였다. 괜찮은 테스트 커버리지, 관리 가능한 기술 부채로 이 모든 문제를 해결했고, 테스트 데이터 생성을 위한 CLI 도구와 프론트엔드의 다양한 기능을 테스트하기 위한 dev 모드를 구현했다. 이 기간 동안 CC의 능력과 기대할 수 있는 것들을 알게 되었다.
품질과 일관성에 대한 노트
포럼과 토론에서 반복되는 주제를 봤다 - 사용량 제한에 대한 좌절과 시간이 지남에 따라 출력 품질이 저하된다는 우려. 먼저 분명히 하고 싶다: 그런 경험을 무시하거나 단순히 "잘못 사용하고 있다"고 주장하려는 게 아니다. 모든 사람의 사용 사례와 맥락은 다르며, 유효한 우려는 경청받을 자격이 있다.
그렇긴 하지만, 나에게 잘 작동하고 있는 것을 공유하고 싶다. 내 경험상, CC의 출력은 지난 몇 달간 실제로 상당히 개선되었고, 이는 대체로 내가 계속 개선해온 워크플로우 덕분이라고 믿는다. 내 시스템에서 작은 영감이라도 얻어 CC 워크플로우에 통합한다면, 만족스러운 품질의 출력을 얻을 가능성이 높아지길 바란다.
솔직히 말하면 - Claude가 완전히 빗나가서 최적이 아닌 코드를 생산하는 때가 분명히 있다. 이는 여러 이유로 발생할 수 있다. 첫째, AI 모델은 확률적(stochastic)이다. 즉, 같은 입력에서 크게 다른 출력을 얻을 수 있다. 때로는 운이 안 좋아서, 당신의 잘못 없이 정말로 품질이 낮은 출력을 받을 수 있다. 다른 때는 프롬프트 구조의 문제다. 모델이 말을 상당히 문자 그대로 받아들이기 때문에, 약간 다른 문구로 출력에 상당한 차이가 생길 수 있다. 잘못 표현하거나 모호하게 말하면, 훨씬 열등한 결과로 이어질 수 있다.
때로는 직접 나서야 할 때가 있다
AI는 놀랍지만, 마법은 아니다. 패턴 인식과 인간의 직관이 이기는 문제들이 분명히 있다. Claude가 30분간 뭔가를 해결하려고 애쓰는 걸 보고 있는데, 당신이 2분 만에 고칠 수 있다면, 그냥 직접 고쳐라. 부끄러워할 것 없다. 자전거 타는 법을 가르치는 것처럼 생각해라. 때로는 다시 놓아주기 전에 잠시 핸들을 잡아줘야 한다.
논리 퍼즐이나 실제 세계의 상식이 필요한 문제에서 특히 이런 걸 봤다. AI는 많은 것을 무차별 대입할 수 있지만, 때로는 인간이 그냥 더 빨리 "이해한다". 고집이나 "AI가 모든 걸 해야 해"라는 잘못된 생각이 시간을 낭비하게 두지 마라. 나서서, 문제를 고치고, 계속 나아가라.
나도 끔찍한 프롬프팅을 많이 했다. 보통 하루가 끝날 무렵 게을러져서 프롬프트에 많은 노력을 들이지 않을 때 그렇다. 그리고 결과가 정말 보인다. 그러니 다음에 "요즘 Anthropic이 몰래 Claude를 너프한 것 같아서 출력이 훨씬 나빠졌다"고 생각할 때, 한 발 물러서서 어떻게 프롬프팅하고 있는지 반성해보길 권한다.
자주 다시 프롬프트해라. ESC를 두 번 누르면 이전 프롬프트를 불러와서 하나를 선택해 분기할 수 있다. 원하지 않는 것에 대한 지식을 갖추고 같은 프롬프트를 줄 때 훨씬 나은 결과를 얻을 수 있다는 걸 알면 놀랄 것이다. 요컨대, 출력 품질이 나빠 보이는 데는 여러 이유가 있을 수 있고, 자기 성찰을 하고 원하는 출력을 얻을 최선의 기회를 주기 위해 무엇을 할 수 있는지 고려하는 게 좋다.
어딘가의 현명한 사람이 말했을 것이다:
"Claude가 당신을 위해 무엇을 할 수 있는지 묻지 말고, 당신이 Claude에게 어떤 컨텍스트를 줄 수 있는지 물어라" ~ 현명한 사람
자, 이제 훈계는 그만하고 좋은 내용으로 넘어가자.
나의 시스템
지난 6개월간 CC와 관련된 워크플로우에 많은 변경을 구현했고, 결과는 내 생각에 꽤 훌륭하다.
Skills 자동 활성화 시스템 (게임 체인저!)
이건 Claude Code로 작업하는 방식을 완전히 바꿔놓았기 때문에 별도 섹션이 필요하다.
문제점
Anthropic이 Skills 기능을 출시했을 때, "이거 대박인데!"라고 생각했다. Claude가 참조할 수 있는 이식 가능하고 재사용 가능한 가이드라인이라는 아이디어는 거대한 코드베이스 전체에서 일관성을 유지하는 데 완벽해 보였다. Claude와 함께 프론트엔드 개발, 백엔드 개발, 데이터베이스 작업, 워크플로우 관리 등을 위한 포괄적인 Skills를 작성하는 데 상당한 시간을 들였다. 수천 줄의 베스트 프랙티스, 패턴, 예제에 대해 말하는 거다.
그런데... 아무것도 안 됐다. Claude가 그냥 사용하지 않았다. 문자 그대로 Skill 설명의 정확한 키워드를 사용해봤다. 아무것도. Skills를 트리거해야 하는 파일에서 작업해봤다. 아무것도. 잠재력은 보이는데 Skills가 그냥 비싼 장식품처럼 앉아 있어서 엄청나게 답답했다.
"아하!" 순간
그때 Hooks를 사용하자는 아이디어가 떠올랐다. Claude가 자동으로 Skills를 사용하지 않는다면, 뭔가를 하기 전에 관련 Skills를 확인하도록 강제하는 시스템을 만들면 어떨까?
그래서 Claude Code의 Hook 시스템에 뛰어들어 TypeScript Hooks로 다층 자동 활성화 아키텍처를 구축했다. 그리고 실제로 작동한다!
작동 방식
두 가지 주요 Hook을 만들었다:
1. UserPromptSubmit Hook (Claude가 메시지를 보기 전에 실행):
- 프롬프트에서 키워드와 의도 패턴을 분석
- 어떤 Skills가 관련될 수 있는지 확인
- Claude의 컨텍스트에 포맷된 리마인더를 주입
이제 "레이아웃 시스템이 어떻게 작동해?"라고 물으면, Claude는 내 질문을 읽기도 전에 "🎯 SKILL ACTIVATION CHECK - Use project-catalog-developer skill"이라는 큰 알림을 본다 (project catalog는 내 프론트엔드의 대규모 복잡한 데이터 그리드 기반 기능이다).
2. Stop Event Hook (Claude가 응답을 완료한 후 실행):
- 어떤 파일이 편집되었는지 분석
- 위험한 패턴 확인 (try-catch 블록, 데이터베이스 작업, async 함수)
- 부드러운 자가 점검 리마인더 표시
- "에러 처리를 추가했나요? Prisma 작업이 Repository 패턴을 사용하고 있나요?"
- 비차단, 성가시지 않게 Claude가 인지하도록만 함
skill-rules.json 설정
모든 Skill을 정의하는 중앙 설정 파일을 만들었다:
- Keywords: 명시적 주제 매치 ("layout", "workflow", "database")
- Intent patterns: 동작을 잡는 정규식 ("(create|add).*?(feature|route)")
- File path triggers: 편집 중인 파일에 따라 활성화
- Content triggers: 파일에 특정 패턴이 포함되면 활성화 (Prisma imports, controllers 등)
예시 스니펫:
{
"backend-dev-guidelines": {
"type": "domain",
"enforcement": "suggest",
"priority": "high",
"promptTriggers": {
"keywords": ["backend", "controller", "service", "API", "endpoint"],
"intentPatterns": [
"(create|add).*?(route|endpoint|controller)",
"(how to|best practice).*?(backend|API)"
]
},
"fileTriggers": {
"pathPatterns": ["backend/src/**/*.ts"],
"contentPatterns": ["router\\.", "export.*Controller"]
}
}
}결과
이제 백엔드 코드 작업 시, Claude는 자동으로:
- 내 프롬프트를 읽기 전에 Skill 제안을 봄
- 관련 가이드라인을 로드
- 실제로 패턴을 일관되게 따름
- 부드러운 리마인더를 통해 마지막에 자가 점검
차이는 하늘과 땅이다. 더 이상 일관성 없는 코드가 없다. 더 이상 "잠깐, Claude가 또 이전 패턴을 썼네"가 없다. 더 이상 매번 수동으로 가이드라인을 확인하라고 말할 필요가 없다.
Anthropic의 베스트 프랙티스 따르기 (어렵게 배운 방법)
자동 활성화가 작동한 후, 더 깊이 파고들어 Anthropic의 공식 베스트 프랙티스 문서를 찾았다. 알고 보니 내가 잘못하고 있었다. 그들은 메인 SKILL.md 파일을 500줄 이하로 유지하고 리소스 파일로 점진적 공개(progressive disclosure)를 사용하라고 권장한다.
이런. 내 frontend-dev-guidelines Skill은 1,500줄 이상이었다. 그리고 1,000줄 이상인 다른 Skill도 몇 개 있었다. 이 모놀리식 파일들은 Skills의 전체 목적(필요한 것만 로드)을 무너뜨리고 있었다.
그래서 모든 것을 재구조화했다:
- frontend-dev-guidelines: 398줄 메인 파일 + 10개 리소스 파일
- backend-dev-guidelines: 304줄 메인 파일 + 11개 리소스 파일
이제 Claude는 처음에 가벼운 메인 파일을 로드하고, 실제로 필요할 때만 상세 리소스 파일을 가져온다. 대부분의 쿼리에서 토큰 효율이 40-60% 개선되었다.
내가 만든 Skills
현재 내 Skill 라인업:
가이드라인 & 베스트 프랙티스:
- backend-dev-guidelines - Routes → Controllers → Services → Repositories
- frontend-dev-guidelines - React 19, MUI v7, TanStack Query/Router 패턴
- skill-developer - 더 많은 Skills를 만들기 위한 메타 Skill
도메인 특화:
- workflow-developer - 복잡한 워크플로우 엔진 패턴
- notification-developer - 이메일/알림 시스템
- database-verification - 컬럼 이름 오류 방지 (이건 실제로 편집을 차단하는 가드레일!)
- project-catalog-developer - DataGrid 레이아웃 시스템
이 모든 것이 내가 작업 중인 것에 따라 자동으로 활성화된다. 모든 패턴을 실제로 기억하는 시니어 개발자가 Claude의 어깨 너머로 지켜보는 것과 같다.
왜 이게 중요한가
Skills + Hooks 이전:
- 새로운 패턴을 문서화했는데도 Claude가 이전 패턴을 사용
- 매번 수동으로 Claude에게 BEST_PRACTICES.md를 확인하라고 말해야 함
- 30만줄 이상의 코드베이스에서 일관성 없는 코드
- Claude의 "창의적 해석"을 고치는 데 너무 많은 시간 소비
Skills + Hooks 이후:
- 일관된 패턴이 자동으로 강제됨
- 내가 코드를 보기도 전에 Claude가 자가 수정
- 가이드라인이 따라지고 있다고 신뢰할 수 있음
- 리뷰와 수정에 훨씬 적은 시간 소비
확립된 패턴이 있는 대규모 코드베이스에서 작업한다면, 이 시스템을 강력히 추천한다. 초기 설정에 며칠이 걸렸지만, 10배 이상의 가치가 있었다.
CLAUDE.md와 문서의 진화
6개월 전에 쓴 글에서 규칙이 최고의 친구라는 섹션이 있었는데, 여전히 그 생각이다. 하지만 CLAUDE.md 파일이 빠르게 손에 넘치게 되었고 너무 많은 것을 하려고 했다. 또한 Claude가 때때로 읽고 때때로 완전히 무시하는 거대한 BEST_PRACTICES.md 파일(1,400줄 이상)도 있었다.
그래서 Claude와 함께 오후를 들여 모든 것을 새로운 시스템으로 통합하고 재구성했다. 변경된 내용은 다음과 같다:
Skills로 이동한 것
이전에 BEST_PRACTICES.md에는 다음이 포함되어 있었다:
- TypeScript 표준
- React 패턴 (hooks, components, suspense)
- Backend API 패턴 (routes, controllers, services)
- 에러 처리 (Sentry 통합)
- Database 패턴 (Prisma 사용법)
- 테스팅 가이드라인
- 성능 최적화
이 모든 것이 이제 Skills에 있고, 자동 활성화 Hook이 Claude가 실제로 사용하도록 보장한다. 더 이상 Claude가 BEST_PRACTICES.md를 확인하기를 바라지 않아도 된다.
CLAUDE.md에 남은 것
이제 CLAUDE.md는 프로젝트 특화 정보에만 집중한다 (약 200줄):
- 빠른 명령어 (
pnpm pm2:start,pnpm build등) - 서비스별 설정
- 태스크 관리 워크플로우 (dev docs 시스템)
- 인증된 라우트 테스팅
- 워크플로우 dry-run 모드
- 브라우저 도구 설정
새로운 구조
Root CLAUDE.md (100줄)
├── 중요한 범용 규칙
├── 레포별 claude.md 파일 참조
└── 상세 가이드라인은 Skills 참조
Each Repo's claude.md (50-100줄)
├── Quick Start 섹션:
│ ├── PROJECT_KNOWLEDGE.md - 아키텍처 & 통합
│ ├── TROUBLESHOOTING.md - 일반적인 이슈
│ └── 자동 생성된 API 문서
└── 레포별 특이사항과 명령어마법은: Skills가 모든 "코드 작성 방법" 가이드라인을 처리하고, CLAUDE.md는 "이 특정 프로젝트가 어떻게 작동하는지"를 처리한다. 관심사의 분리 승리.
Dev Docs 시스템
이 시스템은 (Skills 외에) 모든 것 중에서 CC에서 얻는 결과에 가장 큰 영향을 미쳤다고 생각한다. Claude는 극도의 건망증을 가진 극도로 자신감 넘치는 주니어 개발자와 같아서, 하고 있는 일을 쉽게 잃어버린다. 이 시스템은 그런 단점들을 해결하는 것을 목표로 한다.
내 CLAUDE.md의 dev docs 섹션:
### 대규모 태스크 시작하기
승인된 계획으로 plan mode를 종료할 때:
1. **태스크 디렉토리 생성**: mkdir -p ~/git/project/dev/active/[task-name]/
2. **문서 생성**:
- `[task-name]-plan.md` - 승인된 계획
- `[task-name]-context.md` - 핵심 파일, 결정사항
- `[task-name]-tasks.md` - 작업 체크리스트
3. **정기적으로 업데이트**: 완료된 태스크는 즉시 표시
### 태스크 계속하기
- `/dev/active/`에서 기존 태스크 확인
- 진행하기 전에 세 파일 모두 읽기
- "Last Updated" 타임스탬프 업데이트이것들은 모든 기능이나 대규모 태스크에 대해 항상 생성되는 문서다. 이 시스템을 사용하기 전에는 갑자기 Claude가 맥락을 잃어버리고 30분 전에 계획했던 것을 더 이상 구현하지 않고 어떤 이유로든 옆길로 새버렸다는 걸 깨닫는 경우가 많았다.
나의 계획 프로세스
내 프로세스는 계획으로 시작한다. 계획이 왕이다. Claude에게 뭔가를 구현하라고 요청하기 전에 최소한 planning mode를 사용하지 않는다면, 고생할 거다. 건축업자에게 도면도 없이 집에 와서 증축 공사를 시작하라고 하지 않을 것 아닌가.
기능 계획을 시작할 때, 결국 Claude가 마크다운 파일에 계획을 작성하게 될 것임에도 planning mode에 넣는다. Planning mode가 필요한지 확실하지 않지만, 코드베이스를 조사하고 계획을 세우는 데 필요한 모든 올바른 컨텍스트를 얻는 데 더 나은 결과를 얻는 것 같다.
기본적으로 계획의 달인인 strategic-plan-architect 서브에이전트를 만들었다. 이것은:
- 효율적으로 컨텍스트 수집
- 프로젝트 구조 분석
- 요약, 단계, 태스크, 리스크, 성공 지표, 타임라인이 포함된 포괄적인 구조화된 계획 생성
- 세 개의 파일 자동 생성: plan, context, tasks 체크리스트
하지만 에이전트의 출력을 볼 수 없다는 게 정말 짜증나고, 계획에 no라고 하면 계속 계획하는 대신 에이전트를 그냥 죽여버린다는 게 더 짜증난다. 그래서 메인 CC 인스턴스에서 사용할 같은 프롬프트로 커스텀 슬래시 명령어(/dev-docs)도 만들었다.
Claude가 그 아름다운 계획을 내뱉으면, 시간을 들여 철저히 검토한다. 이 단계는 정말 중요하다. 이해하는 데 시간을 들여라. 어리석은 실수나 Claude가 요청이나 태스크의 매우 중요한 부분을 오해한 것을 얼마나 자주 잡아내는지 놀랄 것이다.
대부분의 경우, plan mode를 종료한 후 15% 이하의 컨텍스트만 남아 있다. 하지만 괜찮다. 새로 시작하는 데 필요한 모든 것을 dev docs에 넣을 것이기 때문이다. Claude는 보통 총 들고 뛰어들기를 좋아하니까, 즉시 ESC 키를 눌러 중단하고 /dev-docs 슬래시 명령어를 실행한다. 이 명령어는 승인된 계획을 가져와 세 파일을 모두 생성하고, 컨텍스트가 충분히 남아 있으면 빈틈을 채우기 위해 약간 더 조사하기도 한다.
그게 끝나면, auto-compaction을 거치더라도 Claude가 길을 잃거나 하던 일을 잃어버리지 않고 기능을 완전히 구현할 준비가 된다. 그냥 Claude에게 가끔씩 태스크와 관련 컨텍스트로 context 파일을 업데이트하라고 상기시키기만 하면 된다. 그리고 현재 세션에서 컨텍스트가 부족해지면, /update-dev-docs 슬래시 명령어를 실행한다. Claude가 관련 컨텍스트(다음 단계 포함)를 기록하고 완료된 태스크를 표시하거나 새 태스크를 추가한 후 대화를 압축한다. 그리고 새 세션에서 "continue"라고만 말하면 된다.
구현 중에, 기능이나 태스크의 크기에 따라, Claude에게 한 번에 한두 개의 섹션만 구현하라고 구체적으로 말한다. 그렇게 하면 각 태스크 세트 사이에 코드를 검토할 기회가 생긴다. 그리고 주기적으로 서브에이전트가 변경사항을 검토해서 큰 실수를 일찍 잡을 수 있다. Claude가 자기 코드를 검토하게 하지 않는다면, 강력히 추천한다. 중요한 오류, 누락된 구현, 일관성 없는 코드, 보안 결함을 잡아내서 많은 골칫거리를 줄여줬다.
PM2 프로세스 관리 (백엔드 디버깅 게임 체인저)
이건 비교적 최근에 추가한 것이지만, 백엔드 이슈 디버깅을 훨씬 쉽게 만들었다.
문제점
내 프로젝트에는 7개의 백엔드 마이크로서비스가 동시에 실행된다. 문제는 서비스가 실행 중일 때 Claude가 로그를 볼 수 없다는 것이었다. "이메일 서비스에 무슨 문제가 있어?"라고 물어볼 수 없었다 - 내가 수동으로 로그를 복사해서 채팅에 붙여넣지 않으면 Claude가 로그를 볼 수 없었다.
중간 솔루션
한동안 각 서비스가 devLog 스크립트를 사용해 타임스탬프가 있는 로그 파일에 출력을 쓰게 했다. 이건... 그럭저럭 작동했다. Claude가 로그 파일을 읽을 수 있었지만, 투박했다. 로그가 실시간이 아니었고, 크래시 시 서비스가 자동 재시작되지 않았고, 모든 것을 관리하는 게 고통이었다.
진짜 솔루션: PM2
그러다 PM2를 발견했고, 게임 체인저였다. 모든 백엔드 서비스를 단일 명령어로 PM2를 통해 실행하도록 설정했다: pnpm pm2:start
이것이 주는 것:
- 각 서비스가 자체 로그 파일을 가진 관리되는 프로세스로 실행
- Claude가 실시간으로 개별 서비스 로그를 쉽게 읽을 수 있음
- 크래시 시 자동 재시작
pm2 logs로 실시간 모니터링pm2 monit으로 메모리/CPU 모니터링- 쉬운 서비스 관리 (
pm2 restart email,pm2 stop all등)
PM2 설정:
// ecosystem.config.js
module.exports = {
apps: [
{
name: "form-service",
script: "npm",
args: "start",
cwd: "./form",
error_file: "./form/logs/error.log",
out_file: "./form/logs/out.log",
},
// ... 6개 더 많은 서비스
],
};PM2 이전:
나: "이메일 서비스가 에러를 던지고 있어"
나: [수동으로 로그를 찾아서 복사]
나: [채팅에 붙여넣기]
Claude: "분석해볼게..."지금의 디버깅 워크플로우:
나: "이메일 서비스가 에러를 던지고 있어"
Claude: [실행] pm2 logs email --lines 200
Claude: [로그를 읽고] "문제를 봤어 - 데이터베이스 연결 타임아웃..."
Claude: [실행] pm2 restart email
Claude: "서비스를 재시작했어, 에러 모니터링 중..."하늘과 땅 차이다. Claude가 이제 내가 인간 로그 가져오기 서비스가 되지 않아도 자율적으로 이슈를 디버깅할 수 있다.
한 가지 주의점: Hot reload는 PM2와 작동하지 않아서, 프론트엔드는 여전히 pnpm dev로 별도로 실행한다. 하지만 자주 hot reload가 필요하지 않은 백엔드 서비스에는 PM2가 놀랍다.
Hooks 시스템 (#NoMessLeftBehind)
내가 작업하는 프로젝트는 멀티 루트이고 루트 프로젝트 디렉토리에 약 8개의 다른 레포가 있다. 프론트엔드용 하나와 백엔드용 7개의 마이크로서비스 및 유틸리티. 기능에 따라 한 번에 몇 개의 레포에서 변경사항을 만들며 계속 왔다 갔다 한다.
그리고 끝없이 짜증나는 한 가지는 Claude가 편집 중인 레포에서 에러를 잡기 위한 빌드 명령어를 실행하는 것을 잊어버릴 때다. 그리고 내가 모르는 사이에 10여 개의 TypeScript 에러를 그냥 남겨둔다. 그러다 몇 시간 후에 Claude가 착한 아이처럼 빌드 스크립트를 실행하는 걸 보고 출력을 본다: "몇 개의 TypeScript 에러가 있지만, 관련 없으니 괜찮아요!"
아니, 괜찮지 않아, Claude.
Hook #1: 파일 편집 추적기
먼저, 모든 Edit/Write/MultiEdit 작업 후에 실행되는 post-tool-use Hook을 만들었다. 기록하는 것:
- 어떤 파일이 편집되었는지
- 어떤 레포에 속하는지
- 타임스탬프
처음에는 각 편집 후 즉시 빌드를 실행하게 했는데, 그건 멍청하게 비효율적이었다. Claude는 빠르게 고치기 전에 항상 뭔가를 망가뜨리는 편집을 한다.
Hook #2: 빌드 체커
그 다음 Claude가 응답을 완료할 때 실행되는 Stop Hook을 추가했다. 이것은:
- 편집 로그를 읽어 어떤 레포가 수정되었는지 확인
- 영향받은 각 레포에서 빌드 스크립트 실행
- TypeScript 에러 확인
- 5개 미만의 에러: Claude에게 보여줌
- 5개 이상의 에러: auto-error-resolver 에이전트 실행 권장
- 디버깅을 위해 모든 것 로깅
이 시스템을 구현한 이후, Claude가 나중에 내가 찾을 에러를 코드에 남긴 경우가 단 한 번도 없었다. Hook이 즉시 잡고, Claude가 다음으로 넘어가기 전에 고친다.
Hook #3: Prettier 포매터
이건 간단하지만 효과적이다. Claude가 응답을 완료한 후, 해당 레포의 적절한 .prettierrc 설정을 사용해 모든 편집된 파일을 Prettier로 자동 포맷.
지난주에 파일을 만들 때 Claude가 trailing comma를 빼기로 했기 때문에 prettier가 실행되어 20개의 변경사항을 만드는 것을 보려고 수동으로 파일을 편집하러 들어갈 필요가 없다.
⚠️ 업데이트: 이 Hook은 더 이상 추천하지 않는다
게시 후, 한 독자가 파일 수정이 상당한 컨텍스트 토큰을 소비할 수 있는 system-reminder 알림을 트리거한다는 상세 데이터를 공유했다. 그들의 경우, Prettier 포매팅이 파일 diff를 보여주는 system-reminder로 인해 단 3라운드에서 16만 토큰이 소비되었다.
영향은 프로젝트에 따라 다르지만 (큰 파일과 엄격한 포매팅 규칙이 최악의 시나리오), 이 Hook을 내 설정에서 제거하고 있다. 어차피 수동으로 파일을 편집할 때 포매팅이 일어나게 두는 건 큰 문제가 아니고, 잠재적인 토큰 비용은 편의성의 가치가 없다.
자동 포매팅을 원한다면, Claude 대화 중이 아닌 세션 사이에 수동으로 Prettier를 실행하는 것을 고려하라.
Hook #4: 에러 처리 리마인더
이건 앞서 언급한 부드러운 철학 Hook이다:
- Claude가 완료한 후 편집된 파일 분석
- 위험한 패턴 감지 (try-catch, async 작업, 데이터베이스 호출, controllers)
- 위험한 코드가 작성되면 부드러운 리마인더 표시
- Claude가 에러 처리가 필요한지 자가 평가
- 차단 없음, 마찰 없음, 그냥 인식만
예시 출력:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📋 ERROR HANDLING SELF-CHECK
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
⚠️ Backend Changes Detected
2 file(s) edited
❓ Did you add Sentry.captureException() in catch blocks?
❓ Are Prisma operations wrapped in error handling?
💡 Backend Best Practice:
- All errors should be captured to Sentry
- Controllers should extend BaseController
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━완전한 Hook 파이프라인
이제 모든 Claude 응답에서 일어나는 일:
Claude가 응답 완료
↓
Hook 1: Prettier 포매터 실행 → 모든 편집된 파일 자동 포맷
↓
Hook 2: 빌드 체커 실행 → TypeScript 에러 즉시 잡음
↓
Hook 3: 에러 리마인더 실행 → 에러 처리를 위한 부드러운 자가 점검
↓
에러 발견 시 → Claude가 보고 수정
↓
에러가 너무 많으면 → Auto-error-resolver 에이전트 권장
↓
결과: 깨끗하고, 포맷되고, 에러 없는 코드그리고 UserPromptSubmit Hook은 작업을 시작하기도 전에 Claude가 관련 Skills를 로드하도록 보장한다.
남겨진 엉망진창 없음. 아름답다.
Skills에 첨부된 스크립트
GitHub의 Anthropic 공식 Skill 예제에서 배운 정말 멋진 패턴: Skills에 유틸리티 스크립트를 첨부하라.
예를 들어, 내 backend-dev-guidelines Skill에는 인증된 라우트 테스팅에 대한 섹션이 있다. 인증이 어떻게 작동하는지만 설명하는 대신, Skill이 실제 스크립트를 참조한다:
### 인증된 라우트 테스팅
제공된 test-auth-route.js 스크립트를 사용하세요:
node scripts/test-auth-route.js http://localhost:3002/api/endpoint스크립트가 모든 복잡한 인증 단계를 처리한다:
- Keycloak에서 refresh token 획득
- JWT secret으로 토큰 서명
- Cookie 헤더 생성
- 인증된 요청 수행
Claude가 라우트를 테스트해야 할 때, 어떤 스크립트를 사용하고 어떻게 사용하는지 정확히 안다. 더 이상 "테스트 스크립트를 만들어볼게"라고 하며 매번 바퀴를 재발명하지 않는다.
이 패턴을 확장할 계획이다 - 관련 Skills에 더 많은 유틸리티 스크립트를 첨부해서 Claude가 처음부터 생성하는 대신 바로 사용할 수 있는 도구를 갖도록.
도구와 기타 것들
Mac의 SuperWhisper
타이핑에 손이 지칠 때 프롬프팅을 위한 음성-텍스트 변환. 놀랍게도 잘 작동하고, Claude가 내 횡설수설하는 음성-텍스트를 놀랍게도 잘 이해한다.
Memory MCP
이제 Skills가 대부분의 "패턴 기억" 작업을 처리하면서 시간이 지남에 따라 덜 사용한다. 하지만 Skills에 속하지 않는 프로젝트별 결정과 아키텍처 선택을 추적하는 데는 여전히 유용하다.
BetterTouchTool
- Cursor에서 상대 URL 복사 (코드 참조 공유용)
- VSCode를 열어두고 파일을 더 쉽게 찾고, CAPS-LOCK을 두 번 탭하면 BTT가 상대 URL 복사 단축키를 입력하고, 클립보드 내용에 ‘@’ 기호를 앞에 붙여 변환하고, 터미널에 포커스한 다음, 파일 경로를 붙여넣는다. 한 번에 다.
- 앱을 빠르게 포커스하는 더블탭 핫키 (CMD+CMD = Claude Code, OPT+OPT = 브라우저)
- 일반적인 동작을 위한 커스텀 제스처
솔직히, 앱 사이에서 허둥대지 않는 것만으로도 시간 절약이 BTT 구매 가치가 있다.
모든 것을 위한 스크립트
짜증나는 지루한 작업이 있다면, 아마 그것을 위한 스크립트가 있을 것이다:
- 모의 테스트 데이터 생성 CLI 도구: Claude Code를 사용하기 전에는, 단 하나의 테스트 제출을 생성하기 위해 약 120개의 질문이 있는 폼에 제출해야 해서 모의 데이터를 생성하는 게 극도로 짜증났다.
- 인증 테스팅 스크립트 (토큰 획득, 라우트 테스트)
- 데이터베이스 리셋 및 시딩
- 마이그레이션 전 스키마 diff 체커
- 개발 데이터베이스를 위한 자동 백업 및 복원
프로 팁: Claude가 유용한 스크립트를 작성하는 걸 도와주면, 즉시 CLAUDE.md에 문서화하거나 관련 Skill에 첨부하라. 미래의 당신이 과거의 당신에게 감사할 것이다.
문서화 (여전히 중요하지만 진화함)
계획 다음으로, 문서화가 거의 마찬가지로 중요하다고 생각한다. 각 태스크나 기능에 대해 생성되는 dev docs 외에도 진행하면서 모든 것을 문서화한다. 시스템 아키텍처, 데이터 흐름 다이어그램, 실제 개발자 문서와 API 등.
하지만 변한 것은 이것이다: 문서화가 이제 Skills를 대체하는 것이 아니라 함께 작동한다.
- Skills에 포함: 재사용 가능한 패턴, 베스트 프랙티스, 방법 가이드
- 문서화에 포함: 시스템 아키텍처, 데이터 흐름, API 참조, 통합 포인트
예를 들어:
- "controller 만드는 방법" → backend-dev-guidelines Skill
- "우리 워크플로우 엔진이 어떻게 작동하는지" → 아키텍처 문서
- "React 컴포넌트 작성 방법" → frontend-dev-guidelines Skill
- "알림이 시스템을 통해 어떻게 흐르는지" → 데이터 흐름 다이어그램 + notification Skill
여전히 많은 문서가 있지만 (850개 이상의 마크다운 파일), 이제 Skills가 더 잘 제공하는 일반적인 베스트 프랙티스를 반복하는 대신 프로젝트별 아키텍처에 레이저처럼 집중한다.
꼭 그렇게까지 할 필요는 없지만, 여러 수준의 문서화를 설정하는 것을 강력히 추천한다. 특정 서비스의 광범위한 아키텍처 개요를 위한 것들, 그 안에 아키텍처의 다른 부분에 대해 더 구체적으로 들어가는 다른 문서로 가는 경로를 포함. Claude가 코드베이스를 쉽게 탐색하는 능력에 큰 차이를 만들 것이다.
프롬프트 팁
프롬프트를 작성할 때, 원하는 결과에 대해 가능한 한 구체적으로 하려고 노력해야 한다. 다시 말하지만, 최소한 계획을 논의하지 않고 건축업자에게 와서 새 욕실을 만들라고 하지 않을 것 아닌가?
"정말 맞아요! 샤그 카펫은 아마 욕실에 두기에 좋은 아이디어가 아닐 거예요."
때로는 구체적인 것을 모를 수도 있고, 그건 괜찮다. 질문이 없다면, Claude에게 조사하고 여러 잠재적 솔루션을 가지고 돌아오라고 말해라. 조사를 위해 전문화된 서브에이전트나 다른 AI 채팅 인터페이스를 사용할 수도 있다. 세상은 당신의 굴이다. 이것이 이익을 가져다줄 것이라고 약속한다. Claude가 만든 계획을 보고 좋은지, 나쁜지, 조정이 필요한지 더 잘 알 수 있기 때문이다. 그렇지 않으면, 그냥 눈 가리고 날아가는 것이다, 순수 vibe-coding. 그러면 고치려는 것과 관련된 파일이 뭔지 모르기 때문에 어떤 컨텍스트를 포함해야 하는지도 모르는 상황에 처하게 된다.
정직하고 편향되지 않은 피드백을 원한다면 프롬프트에서 유도하지 않으려고 노력해라. Claude가 한 것에 대해 확신이 없다면, "이게 좋아 나빠?"라고 말하는 대신 중립적인 방식으로 물어봐라. Claude는 당신이 듣고 싶어하는 것을 말하는 경향이 있어서, 유도 질문은 응답을 왜곡할 수 있다. 상황을 설명하고 생각이나 대안을 묻는 게 더 낫다. 그렇게 하면 더 균형 잡힌 답을 얻을 것이다.
Agents, Hooks, 그리고 Slash Commands (성삼위일체)
Agents
전문화된 Agent의 작은 군대를 구축했다:
품질 관리:
- code-architecture-reviewer - 베스트 프랙티스 준수를 위한 코드 리뷰
- build-error-resolver - TypeScript 에러를 체계적으로 수정
- refactor-planner - 포괄적인 리팩토링 계획 생성
테스팅 & 디버깅:
- auth-route-tester - 인증으로 백엔드 라우트 테스트
- auth-route-debugger - 401/403 에러와 라우트 이슈 디버그
- frontend-error-fixer - 프론트엔드 에러 진단 및 수정
계획 & 전략:
- strategic-plan-architect - 상세한 구현 계획 생성
- plan-reviewer - 구현 전 계획 검토
- documentation-architect - 문서 생성/업데이트
전문화:
- frontend-ux-designer - 스타일링과 UX 이슈 수정
- web-research-specialist - 웹에서 이슈와 많은 다른 것들 조사
- reactour-walkthrough-designer - UI 투어 생성
Agent의 핵심은 매우 구체적인 역할과 무엇을 반환해야 하는지에 대한 명확한 지침을 주는 것이다. 어디론가 가서 뭔지 모를 걸 하고 "고쳤어요!"라고만 돌아와서 뭘 고쳤는지 말해주지 않는 Agent를 만든 후에 이걸 어렵게 배웠다.
Hooks (위에서 다룸)
Hook 시스템은 솔직히 모든 것을 함께 묶는 것이다.
Hooks 없이:
- Skills가 사용되지 않고 앉아 있음
- 에러가 빠져나감
- 코드가 일관성 없이 포맷됨
- 자동 품질 검사 없음
Hooks와 함께:
- Skills 자동 활성화
- 남겨진 에러 제로
- 자동 포매팅
- 품질 인식 내장
Slash Commands
꽤 많은 커스텀 슬래시 명령어가 있지만, 가장 많이 사용하는 것들:
계획 & 문서:
/dev-docs- 포괄적인 전략적 계획 생성/dev-docs-update- 압축 전 dev docs 업데이트/create-dev-docs- 승인된 계획을 dev doc 파일로 변환
품질 & 리뷰:
/code-review- 아키텍처 코드 리뷰/build-and-fix- 빌드 실행 및 모든 에러 수정
테스팅:
/route-research-for-testing- 영향받는 라우트 찾고 테스트 실행/test-route- 특정 인증된 라우트 테스트
슬래시 명령어의 아름다움은 전체 프롬프트로 확장된다는 것이다. 그래서 간단한 명령어에 엄청난 컨텍스트와 지침을 담을 수 있다. 매번 같은 지침을 타이핑하는 것보다 훨씬 낫다.
결론
6개월간의 집중 사용 후, 배운 것:
필수 요소:
- 모든 것을 계획하라 - planning mode나 strategic-plan-architect 사용
- Skills + Hooks - 자동 활성화가 Skills가 실제로 안정적으로 작동하는 유일한 방법
- Dev docs 시스템 - Claude가 맥락을 잃는 것을 방지
- 코드 리뷰 - Claude가 자기 작업을 리뷰하게 하라
- 백엔드용 PM2 - 디버깅을 실제로 견딜 만하게 만듦
있으면 좋은 것:
- 일반적인 태스크를 위한 전문화된 Agents
- 반복되는 워크플로우를 위한 슬래시 명령어
- 포괄적인 문서화
- Skills에 첨부된 유틸리티 스크립트
- 결정을 위한 Memory MCP
지금은 생각나는 게 이게 다다. 말했듯이, 나는 그냥 한 명의 개발자일 뿐이고, 다른 사람들의 팁과 트릭뿐만 아니라 비판도 듣고 싶다. 워크플로우를 개선하는 데 항상 열려 있으니까. 솔직히 나에게 작동하는 것을 다른 사람들과 공유하고 싶었을 뿐이다. IRL에서 이것을 공유할 사람이 별로 없으니까 (우리 팀은 매우 작고, 그들 모두 AI 열차에 타는 게 매우 느리다).
여기까지 읽었다면, 시간을 들여 읽어줘서 감사하다. 이것들에 대해 질문이 있거나 구현에 대한 더 자세한 내용을 원한다면, 기꺼이 공유하겠다. Hooks와 Skills 시스템은 특히 제대로 작동하게 하는 데 시행착오가 좀 걸렸지만, 이제 작동하니까 돌아가는 건 상상할 수 없다.
TL;DR
TypeScript Hooks를 사용해 Claude Code Skills의 자동 활성화 시스템을 구축하고, 컨텍스트 손실을 방지하기 위한 dev docs 워크플로우를 만들고, PM2 + 자동화된 에러 검사를 구현했다.
결과: 6개월 만에 혼자서 30만 LOC를 일관된 품질로 재작성.