--- id: quality-code-metrics title: Code Metrics — Complexity / Coverage / Hot spots category: Coding status: draft source_trust_level: B verification_status: conceptual created_at: 2026-05-09 updated_at: 2026-05-09 tags: [quality, metrics, vibe-coding] tech_stack: { language: "Various", applicable_to: ["Engineering"] } applied_in: [] aliases: [code metrics, cyclomatic complexity, test coverage, code churn, hot spot, SonarQube] --- # Code Metrics > "측정 안 한 거 = 개선 X". **Complexity, coverage, churn, hot spots**. Metrics = signal X target. Goodhart's law 주의. ## 📖 핵심 개념 - Complexity: cyclomatic, cognitive. - Coverage: line / branch / function. - Churn: 자주 변경 file. - Hot spot: complexity × churn = risk. ## 💻 코드 패턴 ### Cyclomatic complexity ``` 함수 안 decision point + 1. if / for / while / case / && / || / ternary 마다 +1. 10 미만: OK 10-20: review 필요 20+: split ``` ```ts // CC = 1 function add(a: number, b: number) { return a + b; } // CC = 4 (3 if + 1 base) function classify(n: number) { if (n < 0) return 'negative'; if (n === 0) return 'zero'; if (n < 10) return 'small'; return 'large'; } ``` ### Cognitive complexity (modern) ``` Nesting 도 카운트. Sequential 보다 nested 가 비싸. CC = 같음 but cognitive 다름: function flat() { if (a) ...; if (b) ...; if (c) ...; // cognitive ≈ 3 } function nested() { if (a) { if (b) { if (c) ...; } } // cognitive ≈ 6 (nesting penalty) } ``` → SonarQube 측정. ### 측정 도구 ```bash # JS / TS npx complexity-report-html src/ # 또는 ESLint { "rules": { "complexity": ["warn", 10], "max-depth": ["warn", 4], "max-lines-per-function": ["warn", 50] } } ``` ```bash # Code Climate (managed) # SonarQube / SonarCloud # CodeScene ``` ### Test coverage ```bash yarn test --coverage # 결과 # Lines: 87.3% # Branches: 76.5% # Functions: 92.1% # Statements: 87.0% ``` ```js // jest.config.js coverageThreshold: { global: { lines: 80, branches: 70, functions: 80 }, './src/payment/': { lines: 95, branches: 90 }, // critical } ``` → Critical 만 high. 모든 곳 100% 무의미. ### Coverage 함정 ``` 100% line = bug 없음 X. - Test 가 assertion 약함 - Edge case 못 잡음 - Logic 정확성 검증 X → Coverage = signal. Mutation testing 가 진짜. ``` ### Code churn ```bash # 자주 변경 file (last 6 months) git log --since="6 months ago" --pretty=format: --name-only | sort | uniq -c | sort -rn | head -20 # 또는 CodeScene / Codacy ``` → 자주 변경 = bug 가능. ### Hot spot (complexity × churn) ``` High complexity + High churn = HIGH RISK. → Refactor priority. Low complexity + Low churn = stable. High complexity + Low churn = legacy (안 변경하면 OK). Low complexity + High churn = OK 자주 변경. ``` ### Churn 자주 변경 file 의 의미 ``` 1. Bug magnet — 같은 곳 자주 fix. 2. 디자인 잘못 — 자주 reorganize. 3. 활발 — 단순 active feature. → 추가 분석 필요. ``` ### Bus factor ```bash # Each file 의 contributor 수 git log --pretty=format:"%an" -- file.ts | sort -u | wc -l # 1 = bus factor 1 (위험) ``` → 1 명만 = pair / share. ### File / function size ``` Function > 50 lines: split File > 500 lines: split / module Class > 1000 lines: God class — split ``` → 정확 cutoff 보다 trend. ### Type coverage (TS) ```bash npx type-coverage --strict --at-least 95 # 95% 미만 = fail ``` → `any` 사용 % 측정. ### Dependency metrics ```bash # Cycles madge --circular src/ # Depth npx dependency-cruiser src/ --output-type metrics # Fan-in / fan-out ``` ### Build time ``` Slow build = 자주 안 build = bug 자주. 목표: - Local dev: instant (HMR) - CI test: < 10 min - Production build: < 5 min 측정 + alarm if 늘어남. ``` ### CI 안 metric ```yaml - name: Test coverage run: yarn test --coverage --coverageReporters=text-summary - name: Complexity run: npx eslint --rule 'complexity: [error, 15]' src/ - name: Type coverage run: npx type-coverage --at-least 95 - name: Bundle size run: yarn size - name: Lint run: yarn lint --max-warnings 0 ``` ### Dashboard (long-term trend) ``` Grafana / Datadog / SonarQube: - 매 commit / day metrics - Trend graph - Per-team / per-module → "지난 분기 보다 좋아짐?" ``` ### Goodhart's law ``` "When a measure becomes a target, it ceases to be a good measure." 목표 = 100% coverage: → 사람 가 의미 없는 test 추가. → Coverage 100% but quality X. → Metric = signal. Target 가 아닌 signal. ``` ### Healthy ranges ``` Cyclomatic: < 10 (most), 15 max. Cognitive: < 15. Function lines: < 50. File lines: < 500. Coverage: 70-90% (critical 95%). Type coverage: 95%+ (TS strict). Cycles: 0. ``` → 정확 number 보다 trend. ### Code review metric ``` - PR cycle time (open → merge) - PR size (median lines) - Time to first review - Number of review iterations 목표: - Cycle time: < 1 day - Median size: < 200 lines - First review: < 4 hours - Iterations: 1-2 ``` → 개선 = 빠른 ship + 적은 bug. ### DORA metrics ``` 1. Deploy frequency 2. Lead time (commit → prod) 3. MTTR (mean time to recover) 4. Change failure rate Elite: - Deploy: multiple per day - Lead time: < 1 hour - MTTR: < 1 hour - Failure: < 15% ``` → Industry benchmark. ### Technical excellence checklist (자체) ``` - [ ] 80%+ test coverage - [ ] Type strict - [ ] Lint clean - [ ] CI < 10 min - [ ] PR cycle < 1 day - [ ] Documentation 80%+ - [ ] On-call < 3 page / week - [ ] Deploy frequency 1/day+ ``` ### 자체 metrics (domain-specific) ``` - API endpoint test count - Schema validation coverage - Error rate per endpoint - Latency p99 per endpoint - Cache hit rate - DB query count ``` ### Metric review meeting ``` Monthly / quarterly: - 어떤 metric 가 worsened? - 어떤 module 가 risky? - 어떤 action? → Action items. ``` ### Per-team vs whole-codebase ``` Per-team metrics: ownership, accountability. Whole-codebase: 전체 health. → 둘 다. ``` ### Anti-metric (bad measures) ``` - LOC (lines of code) — 더 많이 = 더 좋음 X - PR count — 큰 PR vs 많은 작은 PR - Hours worked — quality X quantity - Code review comments — 많이 = 좋음? maybe noise → 의미 없는 measure. ``` ### Senior 의 metric ``` Junior: - Output (LOC, PRs) Senior: - Quality (review feedback) - Mentoring (others' growth) - System health - Tech debt 줄임 - Cross-team impact ``` → Senior 가 LOC 측정 = 잘못된 incentive. ### Manager dashboard ``` - Team velocity - Cycle time - Defect rate - On-call load - Burnout signals (work hours, vacation usage) - Engagement survey → Indicators of team health. ``` ### Tools ``` SonarQube / SonarCloud — full code quality CodeScene — hot spot, knowledge map Codacy — automated review Code Climate — quality grade Codecov — coverage trend LinearB / Jellyfish — DORA + dev productivity ``` ### "측정만 하지 말고 act" ``` Metrics 보기 → action items → 다음 달 비교. 매 quarter: - Top 3 metrics 가 worsened? - 액션 plan - Accountability ``` ## 🤔 의사결정 기준 | 측정 | 자주 | |---|---| | Complexity | PR (CI lint) | | Coverage | PR + dashboard | | Churn | Monthly | | Hot spot | Quarterly | | DORA | Monthly (team) | | Bus factor | Quarterly | ## ❌ 안티패턴 - **Coverage target = 100%**: useless test. - **Metric 가 target**: gaming. - **Single metric judge**: 한 면만. - **No context**: number 만 — meaning 없음. - **개인 별 LOC**: bad incentive. - **측정 + no action**: dashboard 의미 없음. - **모든 코드 같은 standard**: critical 가 다름. ## 🤖 LLM 활용 힌트 - Complexity + coverage + churn = baseline. - Hot spot = complexity × churn. - DORA metrics 가 큰 picture. - Goodhart — 신호 X target. ## 🔗 관련 문서 - [[Quality_Tech_Debt]] - [[Quality_Refactoring]] - [[Testing_Mutation_Testing]]