---
id: quality-tech-debt
title: Tech Debt — 측정 / 우선순위 / 갚기
category: Coding
status: draft
source_trust_level: B
verification_status: conceptual
created_at: 2026-05-09
updated_at: 2026-05-09
tags: [quality, tech-debt, refactoring, vibe-coding]
tech_stack: { language: "Process", applicable_to: ["Engineering"] }
applied_in: []
aliases: [tech debt, technical debt, refactoring budget, code quality, debt register]
---

# Tech Debt

> 모든 코드는 debt. **의도적 vs 우발적** 구분 + 측정 + 정기 상환. "20% time" / "Friday refactor" / "debt sprint" 같은 budget.

## 📖 핵심 개념
- 의도적 debt: 알고 빠른 해결. (deadline)
- 우발적 debt: 무지 / 변경된 요구.
- Bit rot: 시간 경과로 stale.
- Compound interest: 안 갚으면 더 비싸짐.

## 💻 코드 패턴

### Debt 종류
```
Code:        복잡, 중복, naming
Architecture: monolith → microservice 마이그
Documentation: stale, missing
Test:         coverage 낮음, brittle
Dependency:   옛 version, EOL library
Infrastructure: legacy server, manual deploy
Knowledge:    1명만 아는 system, bus factor
Process:      manual deploy, no monitoring
```

### Debt register
```yaml
# debt-register.yml (git 안 living doc)
- id: TECH-001
  title: Migrate from Express to Hono
  category: dependency
  severity: medium
  estimated-effort: 5d
  blocking: [v2-rewrite]
  owner: backend-team
  created: 2025-08-01
  
- id: TECH-002
  title: Add types to legacy /admin module
  category: code
  severity: low
  estimated-effort: 2d
  owner: alice
  created: 2025-12-01
```

→ 매 sprint 검토 + 우선순위.

### TODO comment 정리
```ts
// ❌ 정보 없음
// TODO: fix this

// ✅ 명시
// TODO(alice, 2026-06-01): Replace with new auth system #ISSUE-123
//   Current: legacy basic auth, no MFA
//   Needed: OAuth + 2FA before EOL of legacy backend
```

```bash
# CI lint
grep -rn 'TODO\|FIXME\|XXX' src/ | wc -l
# 또는 leasot tool
npx leasot src/
```

→ TODO 추적 + 만료 검사.

### Deprecation
```ts
/**
 * @deprecated Use `newApi.fetch()` instead. Remove after 2026-06-01.
 */
function oldApi() { ... }
```

```ts
// runtime
function oldApi() {
  console.warn('oldApi deprecated, use newApi');
  return newApi();
}
```

```bash
# CI fail if deprecated 사용 (after sunset)
// .eslintrc — no-deprecated rule
```

### 측정 — code metrics
```bash
# Complexity
npx complexity-report-html src/

# Duplication
npx jscpd src/

# Test coverage
yarn test --coverage

# Bundle size (위 [[Perf_Bundle_Analysis]])
yarn size

# Type coverage
npx type-coverage --strict
```

### Architecture metrics
```bash
# Dependency cruiser
depcruise src --output-type err

# Madge — circular deps
madge --circular src/

# Cycles, depth, fan-in/out
```

### CodeScene / SonarQube / Codacy
```
- Hot spots: 자주 변경 + 복잡 = high risk.
- "Knowledge silo": 한 명만 변경.
- Trends: getting better / worse?
```

→ 자동 / dashboard.

### Refactoring 우선순위
```
High impact + High risk:
  → 적극 refactor

High impact + Low risk:
  → 작은 PR continuous

Low impact + High risk:
  → Leave alone (or document)

Low impact + Low risk:
  → Ignore
```

### Boy Scout Rule
```
"Always leave the code cleaner than you found it."

매 PR 가 작은 cleanup:
- Variable rename
- 작은 extract function
- Test 추가
- TODO 처리
```

→ 큰 refactor 없이 점진 향상.

### Refactor budget
```
20% rule: 매 sprint 의 20% = debt / refactor.
또는: 매 5 PR 중 1 PR = pure refactor.
또는: 분기마다 1 week debt sprint.

→ 안 잡으면 영원 미룸.
```

### Tech debt sprint
```
매 분기 1주일 = 모든 dev 가 debt 갚기.
Top 10 debt items 선택 → solve.

→ 단순 / focus.
```

### "Make it work, make it right, make it fast"
```
Phase 1: Working code (fast iteration)
Phase 2: Refactor for quality
Phase 3: Optimize bottlenecks

→ 1 phase 만 하면 debt. Phase 2 가 핵심.
```

### Debt 가 아닌 것
```
- 다른 디자인 선호 (의견)
- "예전 방식"
- 새 lib 안 사용
- Style 차이 (lint 가 처리)

→ Debt = 명확 cost (slow, bug, friction).
```

### Communicate debt to stakeholders
```
PM / Manager 에게:
- Cost: "이 debt 가 매 feature 의 30% 시간 추가"
- Risk: "EOL 의존 — 보안 patch 안 옴"
- ROI: "1 week refactor = 매 sprint 2 day 절감"

→ 비즈니스 언어.
```

### Debt vs new feature trade
```
"Refactor or new feature?"

매 sprint:
- 60-70% new feature
- 20-30% debt
- 5-10% buffer / unknowns

→ 100% feature = debt 폭발.
```

### Common debts to address
```
1. 옛 dependencies (EOL → security risk)
2. No tests (regression risk)
3. Manual deploy / runbook
4. Single point of failure (bus factor 1)
5. Performance hotspot
6. UI / a11y 옛 standard
7. DB schema (FK 없음, index 없음)
```

### Quick wins
```
- Add prettier / eslint
- Add CI test gate
- TypeScript adoption (점진)
- Test for high-traffic endpoints
- Bundle analyzer
- Dependency update batch (Dependabot)

→ 작은 effort + 큰 gain.
```

### Big projects
```
- Monolith → microservice (몇 분기)
- DB migration (Postgres major)
- Framework upgrade (React 17 → 19)
- 옛 codebase 재작성
- Cloud migration

→ Roadmap + milestone.
```

### Strangler fig pattern
```
Big rewrite 대신:
1. 새 system + old system 동시 운영
2. 점진적으로 traffic 이동
3. 옛 system 점차 사라짐

→ Risk ↓.
```

### Recognize sunk cost
```
"이미 X 시간 투자했으니 계속" = sunk cost fallacy.

Decision = future cost only.
```

### Avoid premature abstraction
```
Rule of three: 3번 반복 = abstract.
1-2번 = 그대로.

→ Wrong abstraction = debt.
```

### Yagni (You Aren't Gonna Need It)
```
"미래에 필요할 것 같아" = often not needed.

Build for current requirement.
Refactor when needed.
```

### Document the why
```
Debt 갚을 때:
"왜 이렇게 했었는지" 옛 author 에게 물어봄.
이유 있을 수도.

→ 무지 X — 의도 이해 후 변경.
```

### Test before refactor
```
1. 현재 behavior 가 무엇인지 test
2. Refactor
3. Test 통과 = 같은 behavior

→ Test 없는 코드 = 옛 안 알 수 없음. 작은 변경 위험.
```

### Mikado method
```
큰 변경 = 작은 가능 step:
1. 목표 변경 시도 → fail.
2. Prerequisites 식별.
3. 각 prereq → 작은 step → repeat.
4. Tree 구조.

→ 큰 refactor 의 단계 명확.
```

### Refactor anti-patterns
```
- 한 PR 가 1000+ line 변경
- 모든 거 한 번에
- 작동하는 거 망가뜨림
- Test 없는 refactor
- 본질 안 보고 Style 만
- 다른 더 큰 issue 무시
```

## 🤔 의사결정 기준
| 상황 | 추천 |
|---|---|
| Debt 많음 + 새 feature 우선 | 20% time + boy scout |
| 큰 architectural debt | 분기마다 milestone |
| Library EOL | 즉시 plan |
| 코드 hot spot | 작은 PR 자주 |
| Bus factor 1 | Pair / docs / share |
| Test 없는 critical | Test first |

## ❌ 안티패턴
- **Big rewrite (모든 거 다시)**: 보통 실패.
- **Debt 무측정**: 안 보임.
- **모든 거 debt 라고 lab**: 의미 없음 — focus.
- **새 feature 가 항상 우선**: debt 폭발.
- **Dev 가 boss 에게 communicate X**: budget 못 받음.
- **Refactor 하면서 feature 추가**: 둘 다 망침.
- **Test 없는 refactor**: behavior 변경 모름.

## 🤖 LLM 활용 힌트
- Debt register + 정기 review.
- 20% time 또는 분기 sprint.
- Boy scout rule 매 PR.
- Strangler fig 대규모.

## 🔗 관련 문서
- [[Quality_Refactoring]]
- [[Productivity_Code_Review]]
- [[Productivity_Documentation]]
