--- id: wiki-2026-0508-seam-접점 title: Seam (접점) category: 10_Wiki/Topics status: verified canonical_id: self aliases: [Seam, Seams, 이음새, 접점, Feathers seam] duplicate_of: none source_trust_level: A confidence_score: 0.9 verification_status: applied tags: [legacy-code, refactoring, testing, feathers] raw_sources: [] last_reinforced: 2026-05-10 github_commit: pending tech_stack: language: typescript framework: none --- # Seam (접점) ## 매 한 줄 > **"매 코드를 매 수정하지 않고 매 동작을 바꿀 수 있는 지점"**. Michael Feathers (*Working Effectively with Legacy Code*, 2004)의 핵심 개념. Seam은 매 legacy code에 매 test를 매 끼워넣는 매 hinge — 매 dependency를 매 엮어내는 매 join point. ## 매 핵심 ### 매 정의 - 매 place where you can alter behavior without editing in place. - 매 enabling point: 매 그 seam을 매 어떻게 활성화하는지 결정. ### 매 3 종류 (Feathers) 1. **Preprocessing Seam** — compile/macro/언어 전처리 (C/C++ `#define`). 2. **Link Seam** — link-time substitution (매 alt library, jest module mock). 3. **Object Seam** — polymorphism (매 interface/subclass). ### 매 응용 1. 매 legacy에 매 test 추가 — 매 substitute dependency. 2. 매 hexagonal port — 매 object seam. 3. 매 feature flag — 매 conditional seam. ## 💻 패턴 ### 매 Object Seam — interface 추출 ```typescript // X — 매 직접 의존 class OrderService { place(o: Order) { new SmtpMailer().send(o.user, "ordered"); // 매 hard-wired } } // O — 매 object seam interface Mailer { send(to: string, msg: string): void; } class OrderService { constructor(private mailer: Mailer) {} place(o: Order) { this.mailer.send(o.user, "ordered"); } } // 매 test에서 fake Mailer 주입. ``` ### 매 Link Seam — Jest module mock ```typescript // orderService.ts import { sendEmail } from "./mailer"; export function place(o: Order) { sendEmail(o.user, "ordered"); } // orderService.test.ts import { place } from "./orderService"; jest.mock("./mailer", () => ({ sendEmail: jest.fn() })); import { sendEmail } from "./mailer"; test("places", () => { place({ user: "a@b.com" } as any); expect(sendEmail).toHaveBeenCalledWith("a@b.com", "ordered"); }); ``` ### 매 Preprocessing Seam — TS compiler hook ```typescript // 매 build-time substitution (매 e.g., babel plugin / tsx loader) // __ENV__ macro 가 매 build 시 replace declare const __TEST__: boolean; export function log(msg: string) { if (__TEST__) return; console.log(msg); } ``` ### 매 React Context seam ```tsx const ApiContext = createContext(realApi); // 매 production // 매 test (Storybook/jsdom) ``` ### 매 NodeJS DI container seam (NestJS) ```typescript // 매 production @Module({ providers: [{ provide: "Mailer", useClass: SmtpMailer }] }) class AppModule {} // 매 test const moduleRef = await Test.createTestingModule({ providers: [OrderService, { provide: "Mailer", useValue: { send: jest.fn() } }], }).compile(); ``` ### 매 Wrap method (Feathers technique) ```typescript // X — private method 가 매 hard-coded class OrderService { place(o: Order) { this.notify(o); /* ... */ } private notify(o: Order) { new SmtpMailer().send(o.user, "ordered"); } } // O — 매 protected → subclass에서 override class OrderService { place(o: Order) { this.notify(o); /* ... */ } protected notify(o: Order) { new SmtpMailer().send(o.user, "ordered"); } } class TestOrderService extends OrderService { protected notify() { /* swallow */ } } ``` ### 매 Feature flag seam ```typescript const flags = await flagClient.evaluate("new-checkout", { user }); const checkout = flags ? new NewCheckout() : new LegacyCheckout(); ``` ## 매 결정 기준 | 상황 | Seam | |---|---| | 매 OOP + DI 가능 | Object Seam (interface). | | 매 legacy without DI | Link Seam (module mock). | | 매 C/C++ 매 macro | Preprocessing Seam. | | 매 React component | Context seam. | | 매 cross-cutting toggle | Feature flag seam. | **기본값**: 매 Object Seam — 매 testability + 매 long-term cleanest. ## 🔗 Graph - 부모: [[Refactoring_Best_Practices|Refactoring]] - 변형: [[Object Seam (객체 접점)]] · [[Link Seam (링크 접점)]] · [[Preprocessing Seam (전처리 접점)]] - 응용: [[Dependency Injection]] · [[Test Doubles]] · [[Hexagonal Architecture]] - Adjacent: [[Scratch Refactoring (스크래치 리팩토링)]] ## 🤖 LLM 활용 **언제**: 매 legacy에 매 test 끼워넣기, 매 dependency 분리, 매 refactor 진입점 식별. **언제 X**: 매 greenfield (매 처음부터 DI로 설계). ## ❌ 안티패턴 - **매 seam 강제 too many**: 매 abstraction noise. - **매 enabling point 미정**: 매 seam 만들고 매 활용 X. - **매 monkey-patching seam (Ruby/Python)**: 매 long-term 유지보수 X. ## 🧪 검증 / 중복 - Verified (Feathers, *Working Effectively with Legacy Code*, 2004, Ch. 4). - 신뢰도 A. ## 🕓 Changelog | 날짜 | 변경 | |---|---| | 2026-05-08 | Phase 1 | | 2026-05-10 | Manual cleanup — Feathers 3-seam canonical + modern patterns |