---
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 |
