레거시 코드 앞에서 흔히 하는 실수는 **“다음 분기에 새 것으로 갈아탄다”**는 선언이다. 현실에서는 데이터·고객·운영이 기존 시스템에 묶여 있어, 한 번에 교체하는 Big Bang은 계획만큼 가지 않는 경우가 많다.
2026년에도 통하는 방법은 작게 나누고, 새 경로를 옆에 두고, 트래픽·기능을 조금씩 옮기는 것이다. 이 글은 스트랭글러(Strangler Fig) 패턴과 기능 플래그(Feature Flag) 를 중심으로, 레거시를 전략적으로 줄이는 순서를 정리한다.
왜 Big Bang이 위험한가
- 동시에 바꿔야 할 것이 너무 많다: 스키마, API, 권한, 배치, 모니터링, 고객 지원 스크립트.
- 버그가 나도 어느 층에서 터졌는지 찾기 어렵다.
- 롤백이 **“전부 되돌리기”**가 되어 비용이 크다.
그래서 목표는 “완벽한 신규 시스템”이 아니라 리스크를 통제한 상태에서 레거시 비중을 줄이는 것이다.
스트랭글러 패턴: 새 싹을 틔우고 옮긴다
스트랭글러는 기존 시스템을 한 번에 대체하지 않고, 새 구현을 옆에 두었다가 점점 비중을 옮기는 방식이다.
전형적인 자리잡기
- 진입점(Facade) 하나를 둔다: HTTP 게이트웨이, BFF, 라우터, 메시지 컨슈머 등.
- 새 구현은 처음에는 일부 요청만 처리한다. (나머지는 기존으로 프록시)
- 검증이 쌓이면 경로를 하나씩 새 쪽으로 돌린다.
- 기존 코드 경로가 더 이상 호출되지 않으면 제거한다.
프론트엔드에서
- 라우트 단위로 새 페이지/새 번들을 붙이고, URL 또는 플래그로 나눈다.
- 마이크로 프론트엔드가 아니어도, 서브 경로
/v2/...처럼 경계를 두기 쉽다.
백엔드에서
- 어댑터로 외부 계약(REST/gRPC)을 유지한 채 내부만 갈아끼운다.
- 동일 입력에 대해 구/신 구현 결과를 비교(shadow read, dark launch)할 수 있으면 더 안전하다.
기능 플래그: 배포와 출시를 분리한다
기능 플래그는 “코드는 프로덕션에 올렸지만 특정 사용자에게만 켠다”는 방식이다. 레거시 교체에 쓰면:
- 롤백이 코드 되돌리기가 아니라 플래그 끄기가 될 수 있다.
- 카나리(1% → 10% → 50%)로 새 경로를 검증한다.
- 팀·테넌트·지역 단위로 켜고 끌 수 있다.
플래그 종류를 나누면 관리가 쉽다
- 릴리스 플래그: 배포 후 안정화되면 제거한다.
- 운영 플래그: 장기간 켜 둘 수도 있다. (권한, 과금 플랜 등)
레거시 교체가 끝나면 플래그와 분기를 반드시 청소하지 않으면, 다음 세대에게 또 다른 레거시가 된다.
단계적 교체 체크리스트
- 관측: 기존 경로의 에러율·지연·비즈니스 지표를 먼저 잡는다.
- 동일 계약: 바깥에서 보이는 API/화면 계약을 유지하거나, 버전을 명시한다.
- 데이터 이중 쓰기/읽기 전환: 한 번에 스키마를 갈아끼우기보다 마이그레이션 단계를 문서화한다.
- 가장 위험한 부분부터가 아니라 가장 자주 바뀌는 부분 또는 격리하기 쉬운 부분부터 자주 옮긴다. (팀 상황에 따라 선택)
- 제거: 새 경로만 남았을 때 구 코드·플래그·데드 코드를 삭제한다.
팀 문화 쪽 한 줄
리팩터링은 코드만의 문제가 아니다. PM·운영·CS와 “무엇을 언제 사용자에게 보여줄지”가 같이 가야 한다. 기능 플래그는 그 공동 언어 역할을 할 수 있다.
정리
- Big Bang 대신 스트랭글러로 새 구현을 옆에 키우고, 트래픽과 책임을 옮긴다.
- 기능 플래그로 배포 리스크를 줄이고, 단계적으로 검증한다.
- 끝나면 플래그와 분기를 지우는 것까지가 한 사이클이다.
레거시는 하루아침에 사라지지 않는다. 대신 매 스프린트 조금씩 줄일 수 있게 만드는 것이 전략적 리팩터링이다.