--- 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]]