---
id: productivity-estimating-effort
title: Estimating Effort — story points / T-shirt / forecast
category: Coding
status: draft
source_trust_level: B
verification_status: conceptual
created_at: 2026-05-09
updated_at: 2026-05-09
tags: [productivity, estimation, planning, vibe-coding]
tech_stack: { language: "process", applicable_to: ["Engineering"] }
applied_in: []
aliases: [story points, T-shirt, estimation, planning, forecasting, #NoEstimates]
---

# Estimating Effort

> 추정 = 항상 틀림. **목표는 정확이 아닌 forecast / risk 식별**. Story points / T-shirt / hours / probability cone. #NoEstimates 흐름. LLM 가 일부 자동.

## 📖 핵심 개념
- 추정 ≠ 약속.
- 작은 task = 정확. 큰 task = 의미 X.
- Variance / risk 가 mean 보다 중요.
- 추정의 cost (time, morale).

## 💻 코드 패턴

### Story points (Fibonacci)
```
1, 2, 3, 5, 8, 13, 21
- 작아 = relative size.
- 비교: 다른 task 와.
- 시간 ≠ point. (관계 없는 척)

team velocity = sprint 당 X points.
```

→ 실제 = 결국 시간 추정. "Hour 가 표현 안 된 시간".

### T-shirt sizing
```
XS / S / M / L / XL / XXL

- 거친 categorize.
- Roadmap / quarter 계획.
- "M 이 보통 1 sprint" 같은 lookup.
```

→ 큰 picture 에 좋음.

### Hours / days
```
- 0.5 / 1 / 2 / 4 / 8 / 16 / 40 hr
- 정직 — 시간.
- 작은 task 만.
- > 16 hr = split.
```

### #NoEstimates
```
원리:
- 추정 비용 > 가치.
- 작은 task 로 split → count 만.
- "이번 주 5개 PR" 가 "20 points" 보다 informative.

조건: small batch + 빠른 throughput.
```

→ 작은 팀 / continuous flow 에 적합.

### Three-point estimate
```
Optimistic: 4 hr
Most likely: 8 hr
Pessimistic: 24 hr

Expected = (O + 4M + P) / 6 = (4 + 32 + 24) / 6 = 10 hr
SD = (P - O) / 6 = 3.3 hr

→ 추정 + uncertainty 둘 다 보고.
```

### Cone of uncertainty
```
프로젝트 시작:    1x → 4x (4배 차이 가능)
요구사항 정리 후: 1x → 1.5x
설계 후:         1x → 1.25x
구현 시작:       1x → 1.1x

→ 시작 시 추정 = 거의 의미 X. Phase 별 재추정.
```

### LLM-assisted estimation
```ts
// LLM 가 코드베이스 보고 추정
const prompt = `
Task: Add OAuth login with Google.
Codebase: Node + Express + Postgres.
Existing auth: Cookie + bcrypt.

Estimate:
- File 가 만들 / 수정될 수
- Task split (5-10 sub-tasks)
- 위험 + 모르는 거
- 시간 (best / typical / worst)
`;
```

→ LLM 가 feature → file / task 분해 잘함.

### Velocity tracking
```
Sprint 1: 22 pts done
Sprint 2: 18 pts
Sprint 3: 25 pts
Avg: ~22 pts

다음 sprint plan: 22 pts.
```

→ 시간 따라 안정. 새 사람 추가 = ramp up 고려.

### Story splitting
```
큰 story:
"User 가 dashboard 에서 모든 metric 본다" — 20 pts

→ Split:
1. CPU graph (3 pts)
2. Memory graph (2 pts)
3. Network graph (3 pts)
4. Filter 시간 (5 pts)
5. Export CSV (3 pts)
6. Refresh button (1 pt)
```

→ INVEST: Independent, Negotiable, Valuable, Estimable, Small, Testable.

### Spike (research)
```
"X 가능?" 모를 때.
- Time-box: 4 hr
- Output: doc + go/no-go
- 진짜 만들지 X — 학습.

→ 답 후 진짜 추정.
```

### Forecast (Monte Carlo)
```python
import random

def simulate_project(stories):
    days = 0
    for points in stories:
        # 과거 velocity: avg 5 pt/day, sd 1.5
        days += points / random.gauss(5, 1.5)
    return days

results = [simulate_project([3, 5, 8, 13]) for _ in range(10000)]
p50 = sorted(results)[5000]
p90 = sorted(results)[9000]

print(f"50% 확률: {p50:.1f} 일")
print(f"90% 확률: {p90:.1f} 일")
```

→ "X 일까지 끝" 보다 "90% 확률로 Y 일" 가 정직.

### 함정: Padding
```
과거: 추정 8 hr → 실제 16 hr.
다음: 추정 16 hr.
실제: 24 hr (work expands to fill time).

→ Parkinson's law. Buffer 가 다른 곳 (project level, 아닌 task level).
```

### Estimation meeting
```
Planning poker:
1. Story 읽음
2. 모두 동시 카드 보임
3. 다른 사람 얘기 → 토의
4. 다시 카드 (수렴)

가장 큰 + 가장 작은 = 발언.
"왜 그렇게 추정?"
```

→ 의견 차이 = 다른 가정 / 정보. 토의 가치.

### Reference task
```
"Login 페이지 = 5 pt" 같은 baseline.
새 task = "이거 와 비교".

→ Anchor 가 변동 줄임.
```

### Tracking (실제 vs 추정)
```sql
-- Actual vs Estimate
SELECT
  story,
  estimate_pts,
  actual_hours,
  actual_hours / NULLIF(estimate_pts * AVG_HR_PER_PT, 0) AS ratio
FROM stories
WHERE done = true
ORDER BY ratio DESC;
```

→ Ratio > 2 = 추정 너무 작거나 task 폭발. 학습.

### Re-estimation
```
50% done 후 재추정.
- 진척 > 50% 가 보이는가? = on track
- 진척 < 30% = 추정 너무 작음. 알리고.

매일 re-estimate 함정: 분석 마비.
```

### Estimation 안 좋은 경우
```
- R&D / 새 기술
- 큰 unknown
- 외부 의존

→ Spike + iterate.
```

### Big project (>3 month)
```
- Quarterly milestone (3-4)
- Each milestone = T-shirt size
- Track velocity
- Re-plan 매 quarter

→ 1년 추정 = 신뢰 X. 3 month chunk.
```

### Burndown / cumulative flow
```
Burndown: pts 남음 시간 따라 ↓
Cumulative flow: backlog / in-progress / done 시간 따라

→ in-progress 늘어남 = WIP 무한 → flow 깨짐.
```

### Cycle time (lead time)
```
Story start → done 시간 평균.

p50 = 2 days
p85 = 5 days
p95 = 14 days

→ "이 task 는 p85 = 5일 안에" 가 추정 보다 정직.
```

### Forecasting (history-based)
```
과거 100 stories cycle time.
→ 새 story = 5 추출 + 합 = forecast.

(Monte Carlo 의 simple version.)
```

→ 추정 하지 않고 forecasting.

### 팀 합의 + 최종 의사결정
```
Tech Lead 가 추정 — 팀 가 confirm.
모두 큰 차이 = 정보 격차 → 토의.

추정 = 기록 (commitment X).
```

## 🤔 의사결정 기준
| 상황 | 추천 |
|---|---|
| Sprint 계획 | Story point + planning poker |
| Roadmap | T-shirt |
| 정밀 task | Hours (3-point) |
| 큰 project | Monte Carlo / phase milestone |
| Continuous flow | Cycle time / forecast |
| R&D | Spike + 재추정 |
| 외부 commitment | 90% confidence + buffer |

## ❌ 안티패턴
- **추정 = 약속**: estimate 가 deadline 됨.
- **모든 task 점**: 1pt 가짜 작업 + 진짜 잃음.
- **점 = 시간 직접 매핑**: "1pt = 1시간" — relative 의미 없음.
- **추정 마비 (analysis paralysis)**: time-box.
- **과거 데이터 무시**: history 가 best 추정.
- **Padding 큰**: Parkinson's law.
- **Re-estimate 안 함**: 진행 정보 무시.

## 🤖 LLM 활용 힌트
- LLM 가 task → sub-task 분해 잘함.
- 시간 보다 cycle time (history) 가 더 좋음.
- Monte Carlo = 90% 확률 forecast.
- 추정 보다 split.

## 🔗 관련 문서
- [[Productivity_Code_Review]]
- [[Productivity_PR_Template]]
- [[Quality_Tech_Debt]]
