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