--- id: wiki-2026-0508-wrap-method-랩-메서드 title: Wrap Method (랩 메서드) category: 10_Wiki/Topics status: verified canonical_id: self aliases: [Wrap Method, 랩 메서드, Method Wrapping] duplicate_of: none source_trust_level: A confidence_score: 0.9 verification_status: applied tags: [refactoring, legacy, michael-feathers] raw_sources: [] last_reinforced: 2026-05-10 github_commit: pending tech_stack: language: Java/Python/TypeScript framework: refactoring --- # Wrap Method (랩 메서드) ## 매 한 줄 > **"매 새 behavior를 기존 method 호출 사이에 끼우려면 매 기존 method를 rename하고 매 같은 이름의 wrapper를 매 새로 만든다"**. Michael Feathers의 *Working Effectively with Legacy Code* (2004) 의 seam 기법으로, 매 test가 어려운 legacy code에 매 새 cross-cutting behavior 추가. ## 매 핵심 ### 매 절차 1. 매 기존 `pay()` → `payAndRecordTransaction()` 으로 rename (또는 private 화). 2. 매 동일 signature의 `pay()` wrapper 신규. 3. 매 wrapper에 새 step + delegate. 4. 매 caller는 변경 X. ### 매 vs Decorator - **Wrap Method**: 매 same class, 매 같은 method 의 in-place 확장. - **Decorator**: 매 different class, 매 wrapping object 의 외부 확장. ### 매 응용 1. Legacy code에 logging/audit 추가. 2. Feature flag wrapping. 3. 매 deprecation soft-warn. ## 💻 패턴 ### Java — Add audit ```java // before public class PaymentService { public void pay(Order o) { /* charge logic */ } } // after public class PaymentService { public void pay(Order o) { audit.log("pay.start", o.id); payInternal(o); audit.log("pay.end", o.id); } private void payInternal(Order o) { /* charge logic */ } } ``` ### TypeScript — Feature flag ```typescript class Checkout { async submit(cart: Cart): Promise { if (!flags.newCheckout) return this.submitLegacy(cart); // new implementation return this.submitV2(cart); } private async submitLegacy(cart: Cart): Promise { /* old */ } private async submitV2(cart: Cart): Promise { /* new */ } } ``` ### Python — Deprecation wrap ```python import warnings class Api: def fetch(self, id): warnings.warn("fetch() will be removed in v3, use get()", DeprecationWarning) return self._fetch_impl(id) def _fetch_impl(self, id): # original logic ... ``` ### Wrap Class (variant) ```java // 매 file/class 전체 wrapping이 필요할 때 public class LoggingPaymentService extends PaymentService { @Override public void pay(Order o) { log.info("paying {}", o.id); super.pay(o); } } ``` ### Decorator alternative ```typescript function audited any>(fn: T, name: string): T { return ((...args: any[]) => { audit.log(`${name}.start`); const r = fn(...args); audit.log(`${name}.end`); return r; }) as T; } const pay = audited(originalPay, 'pay'); ``` ## 매 결정 기준 | 상황 | Approach | |---|---| | 매 same method에 매 minor 추가 step | Wrap Method | | 매 multiple methods 의 cross-cut | AOP / Decorator pattern | | 매 entire class 의 wrapping | Wrap Class / Subclass and Override | | 매 new code, 매 legacy 아님 | Composition / DI | **기본값**: 매 legacy seam 필요 → Wrap Method, 매 그 외 → composition. ## 🔗 Graph - 부모: [[Refactoring_Best_Practices]] · [[Working-Effectively-With-Legacy-Code]] - 변형: [[Wrap-Class]] · [[Subclass-and-Override]] - 응용: [[Decorator-Pattern]] · [[AOP_Aspect-Oriented_Programming]] - Adjacent: [[Seam]] · [[Extract-Method]] · [[Feature-Flag]] ## 🤖 LLM 활용 **언제**: 매 legacy method에 매 새 behavior, 매 caller 변경 X. **언제 X**: 매 fundamental redesign 이 필요할 때 — Strategy/Composition. ## ❌ 안티패턴 - **매 무한 wrapping**: 매 5겹 wrap → unreadable. - **매 wrapper에 logic 누적**: wrapper의 single 책임 (cross-cut) 만 유지. ## 🧪 검증 / 중복 - Verified (Feathers, *Working Effectively with Legacy Code*, 2004). - 신뢰도 A. ## 🕓 Changelog | 날짜 | 변경 | |---|---| | 2026-05-08 | Phase 1 | | 2026-05-10 | Manual cleanup — Wrap Method seam pattern + 다국어 examples |