7.8 KiB
7.8 KiB
id, title, category, status, source_trust_level, verification_status, created_at, updated_at, tags, tech_stack, applied_in, aliases
| id | title | category | status | source_trust_level | verification_status | created_at | updated_at | tags | tech_stack | applied_in | aliases | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| quality-code-metrics | Code Metrics — Complexity / Coverage / Hot spots | Coding | draft | B | conceptual | 2026-05-09 | 2026-05-09 |
|
|
|
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
// 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 측정.
측정 도구
# JS / TS
npx complexity-report-html src/
# 또는 ESLint
{
"rules": {
"complexity": ["warn", 10],
"max-depth": ["warn", 4],
"max-lines-per-function": ["warn", 50]
}
}
# Code Climate (managed)
# SonarQube / SonarCloud
# CodeScene
Test coverage
yarn test --coverage
# 결과
# Lines: 87.3%
# Branches: 76.5%
# Functions: 92.1%
# Statements: 87.0%
// 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
# 자주 변경 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
# 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)
npx type-coverage --strict --at-least 95
# 95% 미만 = fail
→ any 사용 % 측정.
Dependency metrics
# 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
- 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.