"매 지금 매 필요한 것 만 만들어라 — 매 미래의 매 것 매 추측 의 매 X". 매 Kent Beck 의 매 Extreme Programming 1999 — 매 speculative generality (premature abstraction) 매 매 가장 큰 cost 의 source. 매 2026 매 LLM-assisted 의 매 quick refactor 가능 매 YAGNI 매 더 강해짐 — "needed when needed" 매 거의 free.
매 핵심
매 비용 4 가지 (Martin Fowler)
Cost of build: 매 안 쓰일 feature 매 짓는 시간.
Cost of delay: 매 그 시간 매 진짜 needed feature 매 늦어짐.
Cost of carry: 매 maintenance, test, security patch.
Cost of repair: 매 잘못 추측 매 wrong abstraction 매 제거 의 cost.
매 vs SOLID / DRY
DRY: 매 ≥3 occurrences 매 해야지, 매 2 의 X (Rule of Three).
Open-Closed: extension point 매 매 actually-needed 시 매.
Strategy / Factory pattern 매 매 진짜 다양성 매 발견 시 매.
매 응용
API: 매 v1 매 minimal endpoint, 매 versioning infra 의 매 시작 X.
DB schema: 매 nullable column 의 매 lazy add — 매 not "future-proof" up front.
Config: 매 env var 의 매 hardcode 부터 — 의 의 의 변할 시 추출.
Plugin system: 매 첫 plugin 시까지 매 X — interface 매 그때 design.
Microservice: 매 monolith first, 매 split-when-painful.
💻 패턴
Refactor when needed (not before)
// 매 step 1 — single use case, hardcoded
functionsendWelcomeEmail(user: User){returnmailgun.send({to: user.email,template:"welcome",vars:{name: user.name},});}// 매 step 2 — second template 추가 시 매 추출 (매 그 전 X)
typeTemplate="welcome"|"reset_password";functionsendTemplated(user: User,template: Template,vars: Record<string,string>){returnmailgun.send({to: user.email,template,vars});}
Avoid premature config
// ❌ premature
constCONFIG={retries: process.env.RETRIES??3,timeout: process.env.TIMEOUT??30_000,/* …10 more knobs nobody touches */};// ✅ inline 부터
fetch(url,{signal: AbortSignal.timeout(30_000)});// 매 진짜 다른 timeout 필요 시 그때 param.
No speculative interface
// ❌ premature: single impl 매 의 의 interface
interfacePaymentProvider{charge(amt: number):Promise<void>}classStripeProviderimplementsPaymentProvider{/* … */}// ✅ direct
asyncfunctioncharge(amt: number){returnawaitstripe.charges.create({amount: amt});}// 매 PayPal 매 추가 시 매 그때 interface 추출.
"Worst code first" (start ugly, refactor with tests)
// 매 step 1 — 의 의 작동
functioncheckout(items: Item[],userId: string){lettotal=0;for(constiofitems)total+=i.price*i.qty;if(total>100)total*=0.9;// discount
if(userId.startsWith("vip_"))total*=0.95;db.insert("orders",{userId,total});email.send(userId,`Order: $${total}`);returntotal;}// 매 step 2 — 매 second variant 등장 시 매 split.
Feature flag instead of speculative branch
// 매 unfinished feature 매 main 에 머지 X — flag 매 통제
if(flags.newCheckout)returnnewCheckout(items);returnlegacyCheckout(items);// 매 ready 시 flip + 매 dead branch 제거.
LLM-assisted refactor (2026 reality)
# 매 단순 abstraction 추출 매 LLM 매 1 분 — speculative build 매 더 의미 없음
$ claude refactor "extract PaymentProvider interface from StripeProvider, \
create PayPalProvider stub" --apply
매 결정 기준
상황
Approach
신규 feature, 단일 use case
YAGNI — minimal direct implementation
동일 pattern 2회 등장
매 잠시 wait — 매 3rd 시 추출
동일 pattern 3회+
매 추출 (Rule of Three)
외부 contract (public API, DB schema)
의 매 forward-think 필요 — YAGNI 의 매 X
보안 / cryptographic
매 conservative — 매 "not needed yet" 의 매 위험
기본값: 매 inline 부터, 매 second variant 시 conditional, 매 third 시 abstraction.
언제: Code review (premature abstraction 잡기), refactor 결정, MVP scope.
언제 X: 매 forward-compat 가 매 hard contract — public API, file format, network protocol — 매 careful design needed.
❌ 안티패턴
Speculative generality: "we might need plugins one day" — 매 거의 매 wrong shape.
Configuration over code: 매 모든 magic number 매 env var — 매 cognitive load 폭발.
Layered architecture without need: Service / Repository / Mapper 매 1-table CRUD 의 X.
Premature microservices: 매 monolith 의 매 split easier than merge — start mono.
YAGNI as excuse for hack: 매 testability / observability 의 매 YAGNI 의 매 X — 매 always invest.
Forgetting public API stability: 매 broken consumer 의 매 cost 가 큼.