5년 된 프로젝트를 새로 만들기로 한 이유 #1
이 시리즈는 2024년에 있었던 일을 기점으로 회고한 기록입니다.
레거시의 현실
사내 프로젝트가 벌써 5년이 넘었습니다. 그 사이에 팀원도 바뀌고, 기능도 계속 붙었는데, 구조는 처음 만들 때 그대로였어요.
저는 서비스에 중간에 합류하게 된 사람이고 내부에서도 여러 프로젝트가 있지만 특히 메인이 되는 이 프로젝트는 경악스러웠습니다. 백엔드에 있어야 할법한 모델 정제 로직이 프론트에서 raw 값을 받아 정제하는 것이 절반이며..
빌드 체계도 낡았고, "곧 대규모 신규 피쳐가 들어올 예정이니까 그때 같이 개선하자"는 말이 반복되면서 최소한의 유지보수와 작은 피쳐만 진행하다 시간만 흘렀습니다. 리뉴얼 타이밍을 계속 미루다 보니 부채는 더 쌓이고, 손대기는 더 어려워지는 악순환이었어요.
특히 Vue가 .NET 서버에서 서버사이드한 부분이 거의 없이 서브되고 있었습니다. 빌드 속도도 느리고 클라우드 프론트 같은 CDN 을 타지 않을 이유가 전혀 없었어요.
거기에 더해서 정리하자면...
- 디자인 시스템이라는 개념 자체가 없었습니다. Element UI를 그대로 가져다 쓰면서 커스텀 스타일을 덮어씌운 형태. 컴포넌트 재사용 체계가 없으니 같은 UI가 화면마다 조금씩 다르게 구현되어 있었어요.
- SPA 경험이 없던 시절에 만든 프로젝트를 계속 이어온 거라, 라우팅 구조도 비즈니스 로직 분리도 초기 설계 그대로였습니다.
- 비즈니스 로직이 컴포넌트에 혼재. API 호출, 데이터 가공, 상태 관리, UI 렌더링이 하나의
.vue파일에 수백 줄씩 들어있었어요. 어디를 고치면 어디가 깨지는지 예측이 안 되는 상태.
점진적 개선은 왜 안 됐는가
처음엔 당연히 조금씩 고치자를 시도했습니다.
구조적으로 불가능했어요. .NET 구조에서는 빌드 파이프라인을 분리할 수가 없었고, Vue 2에서 3으로의 점진적 마이그레이션은 Composition API 도입만으로도 기존 mixin/옵션 기반 코드 전체를 건드려야 했습니다. Element UI도 Vue 3 호환 버전(Element Plus)으로 바꾸려면 API가 달라서 결국 전부 수정해야 하고..
한 군데를 고치면 연쇄적으로 다른 곳이 깨지는 구조에서, 점진적 개선은 사실상 전체를 고치는데 더 오래 걸리는 방법이었습니다.
전면 리뉴얼 결정
우리에게 주어진 시간은 약 6개월. 이때 전면 리뉴얼하고 화면도, API도, 구조도 전부 새로.
왜 이렇게 결정 했을까
- 기존 서비스의 기능 범위가 명확했습니다. 이미 돌아가는 제품이 있으니 뭘 만들어야 하는지는 정해져 있었어요. 기획 단계가 짧아도 됐습니다.
- 백엔드 API도 동시에 리뉴얼. 프론트만 새로 만드는 게 아니라 API 스펙도 같이 정리하는 거라, 레거시 API에 맞추느라 프론트에서 억지로 가공하던 로직도 없앨 수 있었습니다. 백엔드도 문제는 심각했어요 C# 기반 프레임워크 위에서 돌아가는 서비스는 인력이 순환되면서 숙련된 사람을 찾기도 어려웠습니다.
아키텍처 결정: 왜 MFA(Micro Frontend Architecture)인가
새로 만들면서 가장 먼저 정한 건 프론트를 어떤 아키텍쳐로 가져갈 것인지에 대한 고민 해결이었습니다.
모놀리식 SPA를 다시 만들면 결국 같은 문제가 반복될 거라고 봤어요. 기능이 추가될수록 빌드가 느려지고, 한 팀이 고친 게 다른 팀에 영향을 주고, 배포 단위가 전체가 되는 문제.
MFA(Module Federation 기반)를 선택한 이유?
- 독립 배포 -> 각 도메인(모듈)을 독립적으로 빌드하고 배포할 수 있어야 했습니다. 프론트가 백엔드 릴리즈에 종속되는 건 다시는 안 하고 싶었어요.
- 점진적 교체도 노려볼 순 있음 -> 수 개월 내 모든 화면을 한 번에 전환하는 게 아니라, 모듈 단위로 하나씩 새 버전으로 교체할 수 있는 구조. 기존 서비스 운영하면서 병행하려면 이게 필수였습니다.
- 관심사 분리에도 유리 -> 모듈 간 경계가 물리적으로 나뉘어 있으니, 비즈니스 로직이 다른 도메인으로 흘러가는 걸 구조적으로 막을 수 있었습니다.
6개월 로드맵
대략 이렇게 나눴습니다:
1~2개월: 인프라 세팅
- 모노레포 구조 설계 (패키지 분리 기준 확정)
- 빌드 파이프라인 구축 (Module Federation 설정)
- 디자인 시스템 기초 작업 (토큰 정의, 프리미티브 컴포넌트)
- 공통 모듈 (인증, 라우팅, API 클라이언트)
3~5개월: 화면 구현
- 도메인별로 우선순위 매겨서 순차 구현
- 기존 서비스와 병행 운영 (새 모듈 준비되면 하나씩 전환)
6개월: 전환 완료 + 안정화
- 기존 서비스 트래픽을 새 서비스로 이관
- 레거시 코드 제거
운영 병행: 현실적인 문제들
새로 만드는 동안 기존 서비스는 어떡하지?가 가장 큰 리스크였습니다.
원칙은 기존 서비스에 신규 기능은 안 넣는다, 버그 핫픽스만 한다.
이게 가능했던 건 사업 쪽과 합의가 있었기 때문입니다. 6개월 뒤에 훨씬 나은 제품이 나온다는 걸 설득했고, 그 기간 동안 신규 기능 요청은 새 프로젝트에 반영하기로 했어요.
물론 현실은 완벽하지 않았습니다. 긴급 요청이 들어오면 레거시에도 손대야 했고, 그때마다 이걸 레거시에 넣을까 새 프로젝트에 넣을까를 판단해야 했어요.
돌이켜보면
정말 너무 아쉬웠던 건 개인적으로는 이왕 새로 만드는 거 React로 전환하고 싶었습니다. Vue 3 자체에 문제가 있는 건 아닙니다. Composition API도 좋고, 프레임워크로서 부족한 건 없어요. 다만 React는 점유율이 높은 만큼 스택을 이해하는 사람이 압도적으로 많고, 라이브러리 선택지도 넓고, 채용할 때도 유리합니다. 팀이 커질 때를 생각하면 React가 장기적으로 나았다고 봤어요.
하지만 Vue 2 → Vue 3는 같은 프레임워크니까 러닝커브가 낮고, React로 가면 6개월 안에 못 끝날 수 있다는 내부 반대가 있었고, 뒤집지 못했습니다. 혼자 개발하는 것이 아니라 조직의 여론도 중요하다고 생각했고 특히, 타임라인을 지키는 게 더 중요했으니까요. 틀린 판단은 아니었지만, 아쉬움은 남습니다.
React 로 한다고 시간이 더 많이 걸렸을까요?