--- id: wiki-2026-0508-legacy-modernization title: Legacy Modernization category: 10_Wiki/Topics status: verified canonical_id: self aliases: [Legacy Migration, Legacy Systems, Strangler Fig, Modernization] duplicate_of: none source_trust_level: A confidence_score: 0.9 verification_status: applied tags: [legacy, modernization, strangler-fig, refactor, migration] raw_sources: [] last_reinforced: 2026-05-10 github_commit: pending tech_stack: { language: any, framework: any } --- # Legacy Modernization ## 매 한 줄 > **"매 big-bang 은 죽는다"**. Strangler fig 로 incremental 하게 둘러싸고 잘라낸다, parallel run 으로 검증. ## 매 핵심 ### 매 5 pattern - **Strangler Fig** (Fowler): 신규 시스템이 점진적으로 legacy 를 둘러싸고 대체. 가장 안전 - **Branch by Abstraction**: 인터페이스 추출 → 두 구현 공존 → 신구 전환 → 구 제거 - **Parallel Run**: 신구 동시 실행, 결과 비교, 신뢰 쌓이면 cutover - **Rewrite vs Refactor**: 비즈니스 로직 명확하면 refactor, 아키 자체가 문제면 rewrite - **Anti-corruption Layer** (DDD): legacy 모델이 신규에 새지 않도록 adapter ### 매 응용 1. Monolith → microservice 분해 2. On-prem → cloud 3. Legacy DB schema 점진적 마이그레이션 4. COBOL → Java/Go 5. SOAP → REST/gRPC ## 💻 패턴 ### Pattern 1: Strangler Fig with reverse proxy ```nginx # nginx routes traffic: new endpoints → new svc, rest → legacy location /api/v2/users { proxy_pass http://new-service; } location /api/v2/orders { proxy_pass http://new-service; } location / { proxy_pass http://legacy-monolith; } # 매주 endpoint 추가 → legacy 점점 축소 ``` ### Pattern 2: Branch by Abstraction ```python # 1. 추출 class PaymentGateway(Protocol): def charge(self, amount: int) -> str: ... class LegacyPayment(PaymentGateway): ... # 기존 class NewPayment(PaymentGateway): ... # 신규 # 2. Feature flag 로 전환 def get_payment() -> PaymentGateway: return NewPayment() if flag.enabled("new_payment") else LegacyPayment() ``` ### Pattern 3: Parallel run with shadow traffic ```python def process_order(order): legacy_result = legacy.process(order) try: new_result = new.process(order) if new_result != legacy_result: log_diff(order, legacy_result, new_result) except Exception as e: log_error(e) return legacy_result # 아직 legacy 가 truth ``` ### Pattern 4: Anti-corruption Layer ```python # Legacy 의 이상한 model 을 새 domain 으로 변환 class LegacyCustomerAdapter: def to_domain(self, row: dict) -> Customer: # legacy: cust_nm, cust_dt_birth, cust_flg_act return Customer( name=row["cust_nm"], birthday=parse_legacy_date(row["cust_dt_birth"]), active=row["cust_flg_act"] == "Y", ) ``` ### Pattern 5: Database expand-contract ```sql -- Phase 1 expand: 새 컬럼 추가, 양쪽 쓰기 ALTER TABLE users ADD COLUMN email_v2 VARCHAR(255); -- App: write to both email AND email_v2 -- Phase 2 backfill: 기존 데이터 복사 UPDATE users SET email_v2 = LOWER(TRIM(email)) WHERE email_v2 IS NULL; -- Phase 3 contract: 신규 read, 구 제거 -- App: read from email_v2 only ALTER TABLE users DROP COLUMN email; ALTER TABLE users RENAME COLUMN email_v2 TO email; ``` ### Pattern 6: Characterization tests before refactor ```python # Legacy 동작을 "있는 그대로" 고정 — golden master def test_legacy_behavior(): for input_case in load_production_samples(): actual = legacy.process(input_case) assert actual == load_golden(input_case.id) # Refactor 후에도 통과해야 함 ``` ### Pattern 7: Event interception (Strangler 변형) ```python # Legacy 가 발행하는 event 를 새 서비스가 구독 @on_event("OrderCreated") def new_handler(event): new_service.create_order(event.payload) # Legacy 는 그대로, 새 시스템이 옆에서 동기화 ``` ## 매 결정 기준 | 상황 | Approach | |---|---| | 비즈니스 로직 명확, 코드 더러움 | Refactor (in place) | | 아키 자체가 잘못 | Rewrite + Strangler Fig | | Risk 매우 높음 | Parallel run + shadow | | DB schema 변경 | Expand-contract | | Legacy 모델이 새 시스템 오염 | Anti-corruption Layer | | Big bang 유혹 | 거의 항상 X | **기본값**: Strangler Fig + Branch by Abstraction + Characterization tests. ## 🔗 Graph - 부모: [[Software_Architecture]], [[Refactoring_Best_Practices|Refactoring]] - 변형: [[Strangler_Fig]], [[Branch_by_Abstraction]] - 응용: [[Microservices]] - Adjacent: [[Domain_Driven_Design]], [[Feature_Flags]] ## 🤖 LLM 활용 **언제**: legacy 코드 의도 파악, characterization test 생성, COBOL → Java 변환 후 검증. **언제 X**: 결정론적 schema migration (sqitch/flyway), 비즈니스 룰 단독 추출 (사람 검증 필수). ## ❌ 안티패턴 - Big bang rewrite ("2년만 주세요") → 프로젝트 사망 - Test 없이 refactor → 회귀 무한 - Strangler 시작했는데 끝까지 안 감 → 이중 유지보수 영원 - DB schema 한번에 변경 → 롤백 불가 - 비즈니스 사용자 무시 → 신규 기능 deliver 정지 ## 🧪 검증 / 중복 - Verified (Fowler StranglerFigApplication, Feathers WELC, Evans DDD ACL). 신뢰도 A. - `Legacy-Systems.md` 가 본 문서 redirect. ## 🕓 Changelog | 날짜 | 변경 | |---|---| | 2026-05-08 | Phase 1 | | 2026-05-10 | Manual cleanup — canonical, 5 pattern + 7 code recipe |