"매 large-scale refactor 의 성공은 incremental migration + automated codemod + tight feedback loop". 매 big-bang rewrite 는 매 90% fail. 매 strangler fig pattern, type-safe boundaries, CI-enforced invariants 가 정답. 2026 의 AI-assisted refactor (Claude, Cursor) 는 매 codemod 를 augment.
매 핵심
매 전략 종류
Strangler Fig: 매 old + new 동시 운영, gradual cutover.
Branch by Abstraction: 매 interface 추가 → impl 교체.
Codemod: 매 AST-based bulk rewrite (jscodeshift, ts-morph).
Feature flag: 매 new 코드 toggle, rollback 즉시.
매 사전 준비
Test coverage 가 안전망: 매 critical path 80%+ 권장.
Type system 활용: 매 TS strict, branded types 로 invariant.
Metrics baseline: 매 perf, bundle size, error rate 의 before/after.
Rollback plan: 매 feature flag, blue-green deploy.
매 응용
JS → TS migration (Airbnb, Stripe).
Pages Router → App Router (Next.js).
Redux → Zustand / Jotai.
CRA → Vite.
Single repo → Turborepo / Nx monorepo.
💻 패턴
Strangler Fig — old/new gateway
// gateway.ts
exportasyncfunctionfetchUser(id: string){if(awaitflags.isEnabled("new-user-api",id)){returnnewUserApi.get(id);// 매 new
}returnlegacyUserApi.get(id);// 매 old fallback
}// 매 traffic % gradually 100%
Codemod with ts-morph (rename API)
import{Project}from"ts-morph";constproject=newProject({tsConfigFilePath:"./tsconfig.json"});project.getSourceFiles().forEach((sf)=>{sf.getDescendantsOfKind(SyntaxKind.CallExpression).forEach((call)=>{constexpr=call.getExpression();if(expr.getText()==="oldFetch"){expr.replaceWithText("newFetch");}});});awaitproject.save();// 매 매 file 수동 X — 매 1000 file 도 1초
Branch by Abstraction
// 매 step 1: interface 도입
interfaceUserStore{get(id: string):Promise<User>;save(u: User):Promise<void>;}// 매 step 2: old impl 을 interface 뒤로
classReduxUserStoreimplementsUserStore{/* ... */}// 매 step 3: 매 callsite 가 interface 사용 — 매 internal 구조 변경 가능
conststore: UserStore=useFlag("zustand")?newZustandUserStore():newReduxUserStore();
Type-driven migration (branded type)
typeUserId=string&{__brand:"UserId"};typeLegacyUserId=string&{__brand:"LegacyUserId"};functionmigrate(legacy: LegacyUserId):UserId{return`u_${legacy}`asUserId;}// 매 compiler 가 매 미migrate 사이트 catch
Dependency cruiser (architectural invariant)
// .dependency-cruiser.cjs
module.exports={forbidden:[{name:"ui-no-import-server",severity:"error",from:{path:"^src/ui"},to:{path:"^src/server"},},],};// 매 CI 에서 violation block — 매 layer 침범 방지
Goal: Move auth from monolith to service
├── Pre: extract auth interface (BLOCKED by tight coupling)
│ ├── Pre: extract user model (DONE)
│ └── Pre: remove direct DB access from auth (DONE)
└── Pre: setup auth service skeleton (DONE)
AI-assisted bulk refactor (2026)
# 매 Cursor / Claude Code 에 codemod 보다 의도 기반 refactor# 매 "convert all class components to hooks" 같은 task 는# AI 가 context 이해하며 수정 — 매 codemod 의 limit 넘음# 매 검증: dry-run + diff review + test run
매 결정 기준
변경 규모
전략
1-3 file
manual edit
10-100 file pattern
codemod (jscodeshift / ts-morph)
Architectural
strangler fig + feature flag
Cross-cutting (TS migration)
incremental + branded types
Monorepo split
Nx / Turborepo migration
기본값: incremental + feature flag + CI invariant. Big-bang rewrite 의 X.