d8a80f6272
이름만 다른(표기 변형) [[위키링크]]를 대상 문서의 canonical 제목으로 치환해 끊겼던 1,200개 링크를 연결. 제목/파일명 정규화 일치만 적용하고 별칭 매칭은 과병합 위험으로 제외(애매성 가드). 원본은 _link_reconcile_backup/ 에 백업. 도구: Datacollect/scripts/link_reconcile_apply.mjs Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
5.4 KiB
5.4 KiB
id, title, category, status, canonical_id, aliases, duplicate_of, source_trust_level, confidence_score, verification_status, tags, raw_sources, last_reinforced, github_commit, tech_stack
| id | title | category | status | canonical_id | aliases | duplicate_of | source_trust_level | confidence_score | verification_status | tags | raw_sources | last_reinforced | github_commit | tech_stack | |||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| wiki-2026-0508-legacy-modernization | Legacy Modernization | 10_Wiki/Topics | verified | self |
|
none | A | 0.9 | applied |
|
2026-05-10 | pending |
|
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
매 응용
- Monolith → microservice 분해
- On-prem → cloud
- Legacy DB schema 점진적 마이그레이션
- COBOL → Java/Go
- SOAP → REST/gRPC
💻 패턴
Pattern 1: Strangler Fig with reverse proxy
# 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
# 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
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
# 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
-- 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
# 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 변형)
# 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
- 변형: 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 |