레거시 전략적 리팩터링: Big Bang 금지, 스트랭글러 패턴, 기능 플래그로 단계적 교체

레거시리팩터링스트랭글러기능플래그마이그레이션아키텍처

레거시 코드 앞에서 흔히 하는 실수는 **“다음 분기에 새 것으로 갈아탄다”**는 선언이다. 현실에서는 데이터·고객·운영이 기존 시스템에 묶여 있어, 한 번에 교체하는 Big Bang은 계획만큼 가지 않는 경우가 많다.

2026년에도 통하는 방법은 작게 나누고, 새 경로를 옆에 두고, 트래픽·기능을 조금씩 옮기는 것이다. 이 글은 스트랭글러(Strangler Fig) 패턴기능 플래그(Feature Flag) 를 중심으로, 레거시를 전략적으로 줄이는 순서를 정리한다.


왜 Big Bang이 위험한가

  • 동시에 바꿔야 할 것이 너무 많다: 스키마, API, 권한, 배치, 모니터링, 고객 지원 스크립트.
  • 버그가 나도 어느 층에서 터졌는지 찾기 어렵다.
  • 롤백이 **“전부 되돌리기”**가 되어 비용이 크다.

그래서 목표는 “완벽한 신규 시스템”이 아니라 리스크를 통제한 상태에서 레거시 비중을 줄이는 것이다.


스트랭글러 패턴: 새 싹을 틔우고 옮긴다

스트랭글러는 기존 시스템을 한 번에 대체하지 않고, 새 구현을 옆에 두었다가 점점 비중을 옮기는 방식이다.

전형적인 자리잡기

  1. 진입점(Facade) 하나를 둔다: HTTP 게이트웨이, BFF, 라우터, 메시지 컨슈머 등.
  2. 새 구현은 처음에는 일부 요청만 처리한다. (나머지는 기존으로 프록시)
  3. 검증이 쌓이면 경로를 하나씩 새 쪽으로 돌린다.
  4. 기존 코드 경로가 더 이상 호출되지 않으면 제거한다.

프론트엔드에서

  • 라우트 단위로 새 페이지/새 번들을 붙이고, URL 또는 플래그로 나눈다.
  • 마이크로 프론트엔드가 아니어도, 서브 경로 /v2/... 처럼 경계를 두기 쉽다.

백엔드에서

  • 어댑터로 외부 계약(REST/gRPC)을 유지한 채 내부만 갈아끼운다.
  • 동일 입력에 대해 구/신 구현 결과를 비교(shadow read, dark launch)할 수 있으면 더 안전하다.

기능 플래그: 배포와 출시를 분리한다

기능 플래그는 “코드는 프로덕션에 올렸지만 특정 사용자에게만 켠다”는 방식이다. 레거시 교체에 쓰면:

  • 롤백이 코드 되돌리기가 아니라 플래그 끄기가 될 수 있다.
  • 카나리(1% → 10% → 50%)로 새 경로를 검증한다.
  • 팀·테넌트·지역 단위로 켜고 끌 수 있다.

플래그 종류를 나누면 관리가 쉽다

  • 릴리스 플래그: 배포 후 안정화되면 제거한다.
  • 운영 플래그: 장기간 켜 둘 수도 있다. (권한, 과금 플랜 등)

레거시 교체가 끝나면 플래그와 분기를 반드시 청소하지 않으면, 다음 세대에게 또 다른 레거시가 된다.


단계적 교체 체크리스트

  1. 관측: 기존 경로의 에러율·지연·비즈니스 지표를 먼저 잡는다.
  2. 동일 계약: 바깥에서 보이는 API/화면 계약을 유지하거나, 버전을 명시한다.
  3. 데이터 이중 쓰기/읽기 전환: 한 번에 스키마를 갈아끼우기보다 마이그레이션 단계를 문서화한다.
  4. 가장 위험한 부분부터가 아니라 가장 자주 바뀌는 부분 또는 격리하기 쉬운 부분부터 자주 옮긴다. (팀 상황에 따라 선택)
  5. 제거: 새 경로만 남았을 때 구 코드·플래그·데드 코드를 삭제한다.

팀 문화 쪽 한 줄

리팩터링은 코드만의 문제가 아니다. PM·운영·CS와 “무엇을 언제 사용자에게 보여줄지”가 같이 가야 한다. 기능 플래그는 그 공동 언어 역할을 할 수 있다.


정리

  • Big Bang 대신 스트랭글러로 새 구현을 옆에 키우고, 트래픽과 책임을 옮긴다.
  • 기능 플래그로 배포 리스크를 줄이고, 단계적으로 검증한다.
  • 끝나면 플래그와 분기를 지우는 것까지가 한 사이클이다.

레거시는 하루아침에 사라지지 않는다. 대신 매 스프린트 조금씩 줄일 수 있게 만드는 것이 전략적 리팩터링이다.

궁금한 점이 있으신가요?

협업·의뢰는 아래로, 가벼운 소통은 인스타그램 @bluefox._.hi도 환영이에요.