Claude Code로 레거시 코드를 리팩토링할 때 핵심은 한 번에 전체를 바꾸지 않는 것입니다. 파일 단위로 작업을 나누고, 각 단계마다 테스트를 돌려 회귀를 방지하면 Claude Code는 안전하게 수만 줄의 코드를 현대화할 수 있습니다.
리팩토링 전 준비
1. 현재 상태 파악
cd legacy-project
claude
"이 프로젝트의 코드 품질 문제를 분석해줘:
1. 복잡도가 높은 함수 (100줄 이상)
2. 중복 코드 패턴
3. 타입 안전성 문제
4. 테스트 커버리지 낮은 모듈"
2. 테스트 먼저 확보
리팩토링 전 테스트가 없다면 먼저 작성:
"src/payment.ts의 현재 동작을 캡처하는 테스트를 작성해줘.
리팩토링 전 스냅샷 테스트로 쓸 거야. 구현은 변경하지 말고
외부 동작만 테스트해줘"
이 테스트가 리팩토링 후 회귀를 잡아줍니다.
실전 리팩토링 패턴
패턴 1: 대형 파일 분할
500줄 이상 파일을 모듈로 분리:
/add src/monolith.ts
"이 파일을 책임에 따라 분리해줘:
- 각 모듈의 책임 먼저 설명하고
- 분리 계획 제안하고
- 확인 후 실제 파일 생성할게
일단 계획만 보여줘"
계획 검토 후:
"좋아. 지금 실행해줘.
단, 기존 import를 모두 업데이트하고
각 분리 후 `bun test` 통과 확인해줘"
패턴 2: 콜백 → async/await 마이그레이션
/add src/api/legacy-callbacks.js
"이 파일의 콜백 패턴을 async/await로 변환해줘:
1. 에러 처리는 try/catch로
2. Promise.all 병렬화 가능한 곳 찾아서 최적화
3. 변환 후 동작이 동일한지 확인하는 테스트 추가"
패턴 3: any 타입 제거 (TypeScript)
"src/types 폴더가 없는데:
1. 프로젝트 전체에서 any 타입 사용 위치를 찾아줘
2. 심각도별로 분류해줘 (런타임 위험 / 단순 편의 any)
3. 우선순위 10개부터 proper 타입으로 교체해줘"
패턴 4: 중복 제거
"이 코드베이스에서 중복 패턴을 찾아줘:
- 90% 이상 유사한 함수
- 복사-붙여넣기로 보이는 로직
- 유틸리티로 추출할 수 있는 공통 코드
찾은 후 실제 중복도 측정해줘 (줄 수, 위치)"
점진적 마이그레이션 전략
Express → Fastify 마이그레이션 예제
# 1단계: 현재 라우트 파악
"현재 Express 라우트를 모두 나열하고
각각의 미들웨어, 인증 방식, 에러 핸들링 방식 문서화해줘"
# 2단계: 라우트별 마이그레이션
"POST /api/users 라우트만 Fastify로 변환해줘.
Express 버전과 나란히 실행할 수 있도록 포트 분리해서 구현해줘"
# 3단계: 검증 후 전환
"두 버전을 동시에 실행하는 테스트 스크립트 작성해줘.
같은 입력에 같은 출력이 나오는지 비교"
JavaScript → TypeScript 마이그레이션
# 가장 안전한 순서: 엔트리포인트에서 안쪽으로
"진입점인 src/index.js부터 TypeScript로 변환해줘:
1. .js → .ts 이름 변경
2. any 최소화, 실제 타입 추론
3. 빌드 에러 수정
4. 다음 파일로 넘어가기 전 테스트 통과 확인"
리팩토링 중 Claude Code 활용 팁
컨텍스트 관리
# 큰 리팩토링 세션 시작
/compact 이 프로젝트는 Express → Fastify 마이그레이션 중.
현재까지 users, products 라우트 완료. auth 라우트 진행 중.
# 파일 추가 시 선택적으로
/add src/auth/middleware.ts
/add src/auth/routes.ts
# 전체 src/ 를 한번에 넣지 말 것 — 토큰 낭비
검증 내장 방식
"payment.ts 리팩토링해줘. 각 단계마다:
1. 변경사항 설명
2. `bun test payment` 실행 결과 보여줘
3. 테스트 실패하면 수정 후 계속
완료 시 변경 전/후 성능 차이 있으면 알려줘"
리팩토링 중단 기준 (킬 임계값)
리팩토링 시작 전 중단 조건을 명시하세요:
"auth 모듈 리팩토링 시작 전:
중단 기준: 테스트 커버리지가 80% 밑으로 떨어지거나
기존 API 응답 형식이 변경되면 즉시 중단하고 알려줘"
실측 결과
실제 레거시 Node.js 프로젝트 리팩토링 케이스:
| 작업 | 코드 규모 | Claude Code 시간 | 수동 시간 |
|---|---|---|---|
| 콜백 → async/await | 3,200줄 | 45분 | 3일 |
| TS any 타입 제거 | 87개 위치 | 2시간 | 1주 |
| 라우터 분할 (모놀리식) | 1,800줄 → 12파일 | 1.5시간 | 2일 |
| 중복 제거 | 40% 코드 감소 | 3시간 | 5일 |
Frequently Asked Questions
리팩토링 중 Claude Code가 기존 로직을 바꿀 위험은?
리팩토링 시작 전 테스트를 확보하고, 단계별로 테스트를 실행하면 위험을 최소화할 수 있습니다. "구현 변경 없이 구조만 바꿔줘"라고 명시하면 Claude Code가 동작 보존에 집중합니다.
리팩토링과 새 기능 추가를 동시에 하면 안 되나요?
권장하지 않습니다. 리팩토링과 기능 추가를 동시에 하면 어떤 변경이 버그를 만들었는지 추적이 어렵습니다. 리팩토링 브랜치를 따로 만들고 머지 후 기능을 추가하세요.
대형 파일(3000줄 이상)은 어떻게 처리하나요?
한 번에 처리하면 컨텍스트 창이 부족할 수 있습니다. grep으로 기능별 블록을 찾아서 분할 후 각 블록을 독립적으로 리팩토링하는 것을 권장합니다.
리팩토링 후 성능이 더 나빠질 수도 있나요?
가능합니다. 특히 콜백 → async/await 변환 시 Promise 오버헤드가 생길 수 있습니다. 성능 크리티컬한 경로는 리팩토링 전후 벤치마크를 비교하도록 Claude Code에게 요청하세요.
관련 가이드: Claude Code 완전 가이드 한국어 · Claude Code CI/CD 가이드 한국어 · Claude Code Hooks 한국어
P1 Claude Code Power Prompts 300 — 리팩토링 전용 프롬프트 40개 포함. 레거시 코드 현대화 패턴 검증 완료. 지금 확인 →