Use Cases (업데이트: 2026. 6. 1.)

Claude Code로 기술 부채를 안전하게 줄이는 팀 실전 가이드

Claude Code로 기술 부채를 목록화하고 ICE/RICE로 우선순위를 정해 작은 PR로 안전하게 갚는 방법.

Claude Code로 기술 부채를 안전하게 줄이는 팀 실전 가이드

많은 팀이 기술 부채를 줄이고 싶다고 말하지만, 스프린트가 시작되면 새 기능이 항상 먼저입니다. 시간이 지나면 any가 늘고, 오래된 의존성이 쌓이고, CI는 가끔 실패하고, TODO는 임시 메모가 아니라 사실상 설계 문서가 됩니다.

Claude Code는 자동 리팩터링을 무위험으로 만들어 주는 도구가 아닙니다. 더 현실적인 가치는 부채를 목록화하고, 근거를 붙이고, 우선순위를 정한 뒤, 검토 가능한 작은 PR로 나누는 것입니다. 이렇게 해야 기술 부채 상환이 위험한 대청소가 아니라 팀의 반복 가능한 운영 방식이 됩니다.

이 글에서는 코드 스멜, 의존성 부채, flaky test(가끔 실패하는 불안정한 테스트), 중복 로직, 위험한 TODO, ICE/RICE 우선순위, 작은 PR 전략, 거버넌스까지 한 흐름으로 다룹니다. Claude Code 공식 문서의 Common workflows, Memory, Settings도 함께 확인하세요. 관련 글로는 테스트 전략 가이드, CLAUDE.md 베스트 프랙티스, 승인 및 샌드박스 가이드가 도움이 됩니다.

부채를 일회성 청소가 아니라 상환 루프로 만들기

실패하는 패턴은 보통 “이번 주에 한 번에 리팩터링하자”입니다. 브랜치가 커지고, 리뷰어는 동작이 바뀌었는지 판단하기 어렵고, 결국 릴리스 직전에 되돌립니다.

대신 짧은 루프로 운영합니다.

flowchart LR
  A["목록화"] --> B["근거 수집"]
  B --> C["ICE/RICE 점수화"]
  C --> D["작은 PR로 분리"]
  D --> E["테스트와 리뷰"]
  E --> F["부채 대장 업데이트"]
  F --> A

목록화는 “느낌상 지저분하다”가 아닙니다. 파일 경로, 줄 번호, CI 로그, 오래된 패키지, any, 큰 파일, 중복 로직, TODO/FIXME 같은 근거를 모아야 합니다.

접근 방식적합한 상황위험Claude Code 활용
대규모 리팩터링경계가 명확한 프레임워크 이전diff가 커져 리뷰 불가조사와 이전 계획까지만 맡김
작은 상환 PR일상적인 유지보수효과가 작아 보임대장, 점수, PR 체크리스트로 가시화
의존성 업데이트 스프린트보안 패치, EOL 대응깨지는 변경을 놓침changelog 요약과 테스트 계획
flaky test 정리CI 신뢰가 낮아진 경우재시도로 실제 버그를 숨김실패 분류와 재현 절차 작성

유스케이스 1: 코드 스멜 목록화

코드 스멜은 항상 버그라는 뜻이 아닙니다. 앞으로 변경하기 어려워질 신호입니다. 예를 들어 거대한 함수, 책임이 너무 많은 클래스, 중복 검증, 설명 없는 magic number, 타입 시스템을 우회하는 코드가 여기에 해당합니다.

먼저 Claude Code에 수정이 아니라 조사를 요청합니다.

claude -p "
src/와 tests/에서 기술 부채를 조사해 주세요. 아직 파일은 수정하지 마세요.

확인할 항목:
- 80줄을 넘는 함수
- 300줄을 넘는 파일
- 4단계보다 깊은 중첩
- 중복된 입력 검증, 날짜 처리, 권한 체크
- TypeScript any, as any, @ts-ignore
- TODO / FIXME / HACK 주석
- 테스트가 없는 분기 또는 렌더링만 확인하는 빈약한 테스트

결과는 docs/tech-debt/register.md에 붙여 넣을 수 있는 Markdown 표로 출력해 주세요.
열은 ID, File, Line, Debt type, Evidence, Risk, Suggested first PR, Confidence로 해 주세요.
"

“아직 파일을 수정하지 말라”는 문장이 중요합니다. 바로 고치게 하면 근거가 약한 변경이 섞일 수 있습니다. Claude Code에는 조사, 분류, 가설 제안을 맡기고, 첫 상환 항목은 팀이 결정합니다.

유스케이스 2: 의존성 부채 찾기

오래된 라이브러리, 유지보수 중단 패키지, 취약점, 같은 목적의 중복 라이브러리도 부채입니다. npm audit 개수만 보면 소음이 큰 경고에 시간을 쓰고, 정작 EOL에 가까운 핵심 패키지를 놓칠 수 있습니다.

claude -p "
package.json, lockfile, npm outdated, npm audit 결과를 기준으로 의존성 부채를 분류해 주세요.

분류:
1. 보안 수정이 필요함
2. major update가 필요하고 breaking change 가능성이 큼
3. 유지보수 중단 또는 대체 권장
4. 같은 역할의 중복 라이브러리
5. 지금은 보류 가능

각 항목에 대해 영향 범위, 먼저 읽어야 할 changelog, 필요한 테스트, 가장 작은 안전 PR을 작성해 주세요.
자동 업데이트 가능한 항목과 사람 리뷰가 필수인 항목을 분리해 주세요.
"

의존성 업데이트는 테스트가 한 번 통과했다고 안전한 것이 아닙니다. 날짜 처리, 인증, 암호화, 라우팅, 빌드 도구, 테스트 러너는 별도 브랜치와 명시적인 롤백 메모가 필요합니다.

유스케이스 3: flaky test와 중복 로직 상환

flaky test는 CI에 대한 신뢰를 망칩니다. “다시 돌리면 통과한다”는 인식이 생기면 테스트는 더 이상 안전망이 아닙니다.

claude -p "
최근 20개의 CI 실패 로그를 읽고 flaky test 후보를 분류해 주세요.

분류 기준:
- 시간, 타임존, 랜덤 데이터에 의존
- 네트워크 또는 외부 API에 의존
- 테스트 간 공유 상태가 누수됨
- 비동기 대기 방식이 불안정함
- flaky로 처리하면 안 되는 제품 버그 가능성이 높음

각 후보에 대해 재현 명령, 최소 수정안, 추가할 assertion을 작성해 주세요.
"

중복 로직도 한 번에 제거하지 않습니다. 권한 체크가 네 파일에 복사되어 있다면 첫 PR은 순수 helper를 추출하고 테스트로 기존 동작을 고정하는 데 그칩니다. 호출부 교체는 후속 PR에서 하나씩 진행해야 리뷰가 가능합니다.

복사해서 쓰는 간단한 스캐너

Claude Code는 분석에 유용하지만, 기계적으로 찾을 수 있는 표식은 스크립트로도 모아야 합니다. 아래 내용을 scripts/debt-scan.mjs로 저장하고 node scripts/debt-scan.mjs src를 실행하세요.

import fs from "node:fs";
import path from "node:path";

const root = process.argv[2] || "src";
const maxLines = Number(process.env.MAX_LINES || 300);
const extensions = new Set([".js", ".jsx", ".ts", ".tsx", ".mjs", ".cjs"]);
const findings = [];

function walk(dir) {
  if (!fs.existsSync(dir)) return;

  for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
    const fullPath = path.join(dir, entry.name);

    if (entry.isDirectory()) {
      if ([".git", "node_modules", "dist", "build", ".next", "coverage"].includes(entry.name)) continue;
      walk(fullPath);
      continue;
    }

    if (entry.isFile() && extensions.has(path.extname(entry.name))) {
      scanFile(fullPath);
    }
  }
}

function add(file, line, type, severity, detail) {
  findings.push({ file, line, type, severity, detail });
}

function scanFile(file) {
  const text = fs.readFileSync(file, "utf8");
  const lines = text.split(/\r?\n/);

  if (lines.length > maxLines) {
    add(file, 1, "large-file", 3, `${lines.length} lines`);
  }

  lines.forEach((line, index) => {
    const lineNumber = index + 1;

    if (/\b(FIXME|TODO|HACK)\b/i.test(line)) {
      add(file, lineNumber, "unsafe-comment", /FIXME|HACK/i.test(line) ? 4 : 3, line.trim());
    }

    if (/\.(ts|tsx)$/.test(file) && /(:\s*any\b|as\s+any\b|<any>)/.test(line)) {
      add(file, lineNumber, "typescript-any", 4, line.trim());
    }
  });
}

walk(root);

console.log("| file | line | type | severity | detail |");
console.log("| --- | ---: | --- | ---: | --- |");
for (const item of findings.sort((a, b) => b.severity - a.severity || a.file.localeCompare(b.file))) {
  const detail = item.detail.replaceAll("|", "\\|");
  console.log(`| ${item.file} | ${item.line} | ${item.type} | ${item.severity} | ${detail} |`);
}

if (findings.length === 0) {
  console.error("No obvious debt markers found.");
}

이 스크립트가 아키텍처를 이해하거나 모든 중복을 찾지는 못합니다. 그래도 TODO, FIXME, any, 큰 파일을 매주 같은 기준으로 수집할 수 있다는 점이 중요합니다.

부채 대장 템플릿

바로 issue를 만들기 전에 한 번 대장에 모으면 우선순위 비교가 쉬워집니다.

# Technical Debt Register

| ID | Area | Evidence | User or team impact | ICE | RICE | Owner | Next PR | Status |
| --- | --- | --- | --- | ---: | ---: | --- | --- | --- |
| TD-001 | Auth permissions | src/auth/guard.ts duplicates role checks in 4 places | New role changes take 2 days and often miss one path | 420 | 1680 | Backend | Extract pure canAccess() with tests | Ready |
| TD-002 | Dependencies | vite is 2 major versions behind | Security patches and plugin updates are blocked | 280 | 900 | Platform | Upgrade in isolated branch and run build/test | Investigating |

## Scoring note

- ICE = Impact x Confidence x Ease
- RICE = Reach x Impact x Confidence / Effort
- Keep evidence links concrete: file path, line, CI run, or user-facing incident.

ICE는 빠른 정렬에 좋습니다. RICE는 영향받는 사용자 수와 노력을 함께 설명해야 할 때 좋습니다. 둘 다 정답을 계산하는 공식이 아니라 대화를 맞추는 도구입니다.

안전한 리팩터 계획 프롬프트

상환 대상을 정했다면 수정 전에 계획부터 요청합니다.

claude -p "
TD-001을 안전하게 상환하기 위한 계획을 작성해 주세요. 아직 파일은 수정하지 마세요.

범위:
- src/auth/guard.ts
- src/auth/roles.ts
- tests/auth/guard.test.ts

제약:
- 외부 API 동작을 바꾸지 않음
- 기존 테스트를 먼저 확인함
- 동작 테스트가 부족하면 리팩터링 전에 characterization test를 추가함
- PR은 변경 300줄 이하를 목표로 함
- 위험, 롤백 방법, 리뷰 포인트를 포함함

출력:
1. 현재 동작 요약
2. 명시적인 non-goals
3. 첫 PR의 diff 계획
4. 실행할 테스트 명령
5. PR 리뷰 요청 문구
"

non-goals를 쓰게 하면 과도한 개선을 막을 수 있습니다. Claude Code는 도움을 주려는 방향으로 범위를 넓히기 쉬우므로, PR 경계를 먼저 고정해야 합니다.

리팩터 PR 체크리스트

## Refactor PR checklist

- [ ] This PR changes structure, not product behavior.
- [ ] Existing behavior is covered by tests before the refactor.
- [ ] New helper names describe domain behavior, not implementation detail.
- [ ] Public API, response shape, permissions, and logging are unchanged or explicitly documented.
- [ ] The diff is small enough to review in one sitting.
- [ ] Rollback is simple: revert this PR without reverting unrelated work.
- [ ] The debt register is updated with status and follow-up PRs.

Claude Code가 작성하는 PR 본문에 이 체크리스트를 넣으면 “그냥 리팩터링입니다”가 아니라 검토 가능한 근거가 됩니다.

구체적인 함정

자동 수정을 과신하기 타입이 통과해도 안전하다고 말할 수 없습니다. 권한, 결제, 날짜, 비동기 처리, 마이그레이션은 동작 고정 테스트와 사람 리뷰가 필요합니다.

모든 TODO를 삭제하기 일부 TODO는 릴리스 차단 이슈이고, 일부는 단순 메모입니다. remove before release, bypass auth, temporary token, FIXME 같은 위험 표현부터 처리합니다.

의존성 업데이트를 한 PR에 묶기 major update 10개를 한 PR에 넣으면 실패 원인 분리가 어렵습니다. 빌드 도구, UI 라이브러리, 인증 라이브러리, 테스트 러너는 나눕니다.

점수를 정치적으로 쓰기 ICE/RICE는 의견이 아니라 근거를 담아야 합니다. 파일 경로, CI 실행, 장애, 노력 가정을 함께 기록하세요.

팀 기억을 남기지 않기 “권한 코드는 승인 필수”, “리팩터 PR은 300줄 이하” 같은 규칙은 CLAUDE.md나 프로젝트 설정에 남깁니다. Claude Code의 Memory와 Settings를 쓰면 매번 같은 설명을 줄일 수 있습니다.

팀 거버넌스

현실적인 방식은 매주 30분의 부채 리뷰입니다.

  1. 스캐너와 Claude Code의 목록화 결과를 본다.
  2. 상위 10개만 ICE/RICE를 갱신한다.
  3. 다음 스프린트에서 상환할 PR 하나를 고른다.
  4. flaky test와 보안 의존성은 우선순위를 높게 본다.
  5. 완료 후 대장에 “무엇이 쉬워졌는지” 한 줄로 남긴다.

ClaudeCodeLab은 부채 대장, PR 체크리스트, Settings, CLAUDE.md 시작 템플릿을 팀 상황에 맞게 정리해 드립니다. 저장소와 리뷰 문화에 맞춘 도입이 필요하다면 Claude Code 교육, 템플릿, 컨설팅을 확인하세요.

정리

Claude Code로 기술 부채를 안전하게 줄이는 방법은 “전체를 한 번에 리팩터링”이 아닙니다. 증거를 모으고, 점수를 매기고, 작은 PR로 하나씩 갚는 것입니다. 코드 스멜, 의존성 부채, flaky test, 중복 로직, 위험한 TODO는 모두 같은 루프 안에서 관리할 수 있습니다.

이 글의 흐름을 Masa의 작은 프로젝트에 실제로 적용해 보니, 가장 큰 효과는 “지금 갚아야 할 부채”와 “기록만 해도 되는 부채”가 분리된 점이었습니다. any 정리와 오래된 TODO 제거를 작은 PR로 나누자 리뷰 부담은 크게 늘지 않았고 불안한 부분은 줄었습니다. 반면 의존성 major update는 예상보다 검증이 무거웠기 때문에, Claude Code에 바로 변경을 맡기기보다 테스트와 릴리스 메모를 먼저 준비하는 편이 안전했습니다.

#claude-code #tech-debt #refactoring #code-quality
무료

무료 PDF: Claude Code 치트시트

이메일을 입력하면 명령, 리뷰 습관, 안전한 워크플로를 정리한 PDF를 받을 수 있습니다.

개인정보를 안전하게 관리하며 스팸을 보내지 않습니다.

Masa

작성자 소개

Masa

Claude Code 실무 워크플로와 팀 도입을 검증하는 엔지니어입니다.