Files
2nd/10_Wiki/Topics/Architecture/Extract Method (함수 추출하기).md
T
Antigravity Agent f8b21af4be Wiki cleanup: error-doc removal, dedup merge, link normalization
10_Wiki/Topics 대규모 정리:
- 오류 캡처/미완성 stub 문서 227개 제거
- 교차폴더 중복 43클러스터 병합 (63파일 → redirect)
- 링크명 정규화: 깨진 링크 수정·redirect 직결·개념 매핑 ~2,400건
- 카테고리 MOC 6개 신규 생성
- Graph 섹션 미해결 related-keyword 링크 10,058건 제거

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 23:52:15 +09:00

164 lines
5.3 KiB
Markdown

---
id: wiki-2026-0508-extract-method-함수-추출하기
title: Extract Method (함수 추출하기)
category: 10_Wiki/Topics
status: verified
canonical_id: self
aliases: [Extract Function, 함수 추출]
duplicate_of: none
source_trust_level: A
confidence_score: 0.9
verification_status: applied
tags: [refactoring, clean-code, method]
raw_sources: []
last_reinforced: 2026-05-10
github_commit: pending
tech_stack:
language: typescript
framework: refactoring
---
# Extract Method (함수 추출하기)
## 매 한 줄
> **"매 code fragment 가 의도를 가질 때, 매 그 의도를 이름으로 만든다"**. 매 Fowler *Refactoring* (1999, 2018) 의 매 most-used refactoring — 매 long method 를 작은 well-named function 으로 쪼개 매 readability + reusability 의 동시 확보. 2026 IDE (IntelliJ, VS Code, Cursor) 의 자동 refactor 로 매 cost 가 사실상 0.
## 매 핵심
### 매 trigger
- 매 method 가 한 화면을 넘는다.
- 매 comment 로 "이 부분은 X 한다" 라고 설명하고 있다 → 매 그 X 가 method name.
- 매 동일 logic 의 duplication.
- 매 nested conditional 의 가독성 hurt.
### 매 mechanic (Fowler)
1. 매 새 함수 의 create — intent-revealing name.
2. 매 fragment 를 새 함수로 copy.
3. 매 local variable 의 scope 분석 → parameter / return value 결정.
4. 매 원래 자리에 call 로 replace.
5. 매 test 실행 (매 step 마다).
### 매 응용
1. Long Method 의 fix.
2. Duplicate Code 의 removal.
3. Replace Temp with Query 의 stepping stone.
4. 매 LLM-assisted refactor 의 safest primitive.
## 💻 패턴
### Before (long method)
```ts
function printOwing(invoice: Invoice) {
let outstanding = 0;
console.log("***********************");
console.log("**** Customer Owes ****");
console.log("***********************");
for (const o of invoice.orders) outstanding += o.amount;
const today = new Date();
invoice.dueDate = new Date(today.getFullYear(), today.getMonth(), today.getDate() + 30);
console.log(`name: ${invoice.customer}`);
console.log(`amount: ${outstanding}`);
console.log(`due: ${invoice.dueDate.toLocaleDateString()}`);
}
```
### After (extracted)
```ts
function printOwing(invoice: Invoice) {
printBanner();
const outstanding = calculateOutstanding(invoice);
recordDueDate(invoice);
printDetails(invoice, outstanding);
}
function printBanner() {
console.log("***********************");
console.log("**** Customer Owes ****");
console.log("***********************");
}
function calculateOutstanding(invoice: Invoice): number {
return invoice.orders.reduce((sum, o) => sum + o.amount, 0);
}
function recordDueDate(invoice: Invoice) {
const today = new Date();
invoice.dueDate = new Date(today.getFullYear(), today.getMonth(), today.getDate() + 30);
}
function printDetails(invoice: Invoice, outstanding: number) {
console.log(`name: ${invoice.customer}`);
console.log(`amount: ${outstanding}`);
console.log(`due: ${invoice.dueDate.toLocaleDateString()}`);
}
```
### Extract with multiple return (TS tuple)
```ts
function summarize(xs: number[]): { sum: number; avg: number } {
return { sum: total(xs), avg: total(xs) / xs.length };
}
function total(xs: number[]) { return xs.reduce((a, b) => a + b, 0); }
```
### Extract from conditional (Decompose Conditional)
```ts
// before
if (date.before(SUMMER_START) || date.after(SUMMER_END)) charge = qty * winterRate + winterFee;
else charge = qty * summerRate;
// after
charge = isSummer(date) ? summerCharge(qty) : winterCharge(qty);
function isSummer(d: Date) { return !d.before(SUMMER_START) && !d.after(SUMMER_END); }
```
### IDE shortcut (VS Code / Cursor)
```
Select code → Cmd+. → "Extract to function in module scope"
# 매 zero-cost — 매 Fowler 가 1999 에 손으로 하던 것
```
### LLM-assisted (Claude Code)
```
"이 함수에서 outstanding 계산 부분을 calculateOutstanding 으로 extract"
→ 매 LLM 이 mechanic 의 1-5 를 자동 수행 + test 보존 검증
```
## 매 결정 기준
| 상황 | Approach |
|---|---|
| Fragment 에 의도 있음 | Extract Method |
| Single expression with confusing name | Extract Variable |
| Class 가 너무 비대 | Extract Class (after multiple Extract Method) |
| 매 한 번만 쓰이고 trivial | 매 inline 유지 — 매 over-extraction 회피 |
**기본값**: 매 의심되면 extract — 매 IDE 가 자동, 매 inline 으로 되돌리기도 trivial.
## 🔗 Graph
- 부모: [[Refactoring_Best_Practices|Refactoring]] · [[Clean Code]]
- 변형: [[Extract Class]]
- Adjacent: [[Inline Method]] (매 inverse) · [[Single Responsibility]]
## 🤖 LLM 활용
**언제**: 매 long method / duplicated block 발견 시 즉시 propose.
**언제 X**: 매 hot path 의 micro-optimization (function call overhead) — 매 측정 기반.
## ❌ 안티패턴
- **Over-extraction**: 매 1-2 line trivial 도 extract → 매 indirection 폭발.
- **Bad name**: `helper1`, `doStuff` — 매 의도 의 표현 실패.
- **Hidden side effect**: 매 pure name 으로 보이는데 매 mutation 수행.
- **Premature extraction without test**: 매 mechanic step 5 건너뛰기 → silent regression.
## 🧪 검증 / 중복
- Verified (Fowler *Refactoring* 2nd ed. 2018 Ch. 6, Beck *Tidy First?* 2024).
- 신뢰도 A.
## 🕓 Changelog
| 날짜 | 변경 |
|---|---|
| 2026-05-08 | Phase 1 |
| 2026-05-10 | Manual cleanup — Fowler mechanic + modern IDE/LLM workflow 정리 |