우리는 Angular 18 앱을 React 20으로 재작성하고 Developer Velocity를 40% 증가시켰습니다
Source: Dev.to
왜 우리는 Angular 18에서 마이그레이션했는가
우리의 Angular 18 애플리케이션은 400개가 넘는 컴포넌트로 성장했으며, 상태 관리를 위해 NgRx와 커스텀 RxJS 연산자를 사용하고, 복잡한 의존성 주입 트리를 가지고 있었습니다. Angular은 초기에는 잘 작동했지만, 몇 가지 확장성 문제에 직면했습니다:
- 전체 프로덕션 빌드 시간이 8분 이상으로 급증하여 CI/CD 파이프라인과 개발자 피드백 루프가 느려졌습니다.
- 신규 입사자는 Angular의 의견이 강한 구조, RxJS 반응형 패턴, Ivy 컴파일러 특성에 익숙해지는 데 3주 이상이 걸렸습니다.
- 메인 엔트리 포인트의 번들 크기가 2.1 MB에 달해, 네트워크가 느린 사용자에게 초기 로드 시간이 길어졌습니다.
- 커스텀 디렉티브와 파이프 유지보수가 병목 현상이 되었으며, Angular 내부 API와의 강한 결합도가 문제였습니다.
우리는 Angular 19로 업그레이드하는 것을 포함한 여러 옵션을 검토했지만, 궁극적으로 React 20을 선택했습니다. React는 유연하고 의견이 강하지 않은 구조, 성숙한 생태계, 그리고 동시 렌더링, 서버 컴포넌트, 향상된 Suspense 지원과 같은 새로운 기능을 제공하기 때문입니다.
Source: …
우리의 마이그레이션 프로세스
우리는 앱의 높은 결합도로 인해 점진적인 마이크로‑프런트엔드 도입이 위험하다고 판단하여, 단계적인 전체 재작성 방식을 선택했습니다. 6개월 일정은 세 단계로 나뉘었습니다.
Phase 1: 감사 및 계획 (4주)
- 400개가 넘는 Angular 컴포넌트를 React 대응 컴포넌트와 매핑했습니다.
- 상태 관리 흐름을 문서화하고, React로 포팅해야 할 12개의 커스텀 Angular 디렉티브를 식별했습니다.
- 두 스택 모두 TypeScript strict mode를 표준으로 채택하여 타입 마이그레이션 작업을 최소화했습니다.
- 지원 라이브러리를 선정했습니다: Redux Toolkit(NgRx 대체), React Router 7(라우팅), React Testing Library(단위 테스트).
Phase 2: 핵심 구축 및 병행 개발 (16주)
- 디자인 시스템, 인증 흐름, 대시보드 프레임워크 등 핵심 컴포넌트의 React 대응 버전을 먼저 구축했습니다.
- 커스텀 codemod를 사용해 **60 %**의 단순 Angular 컴포넌트를 자동으로 React로 변환한 뒤, 복잡한 로직은 수동으로 포팅했습니다.
- Angular 앱은 유지보수 모드로 유지했으며, 새로운 기능은 React에서 feature flag를 통해 구축해 진행 중인 작업에 영향을 주지 않았습니다.
Phase 3: 전환 및 검증 (4주)
- 두 앱에 대해 병행 로드 테스트를 수행하고, React 빌드에서 14개의 주요 버그를 수정했습니다.
- 가중 트래픽 전환(10 % → 50 % → 100 %)을 수행해 다운타임 없이 전환을 완료했습니다.
- 전환 후 2주 동안 Angular 코드베이스를 읽기 전용 모드로 유지했지만, 실제로는 사용되지 않았습니다.
주요 결과
우리는 세 가지 핵심 지표인 스프린트당 완료된 스토리 포인트, PR 사이클 타임, 그리고 빌드 타임을 사용해 개발자 생산성을 측정했습니다. React 20을 3개월 동안 운영한 결과는 다음과 같습니다:
- 개발자 생산성 40 % 증가: 12명의 엔지니어 팀이 스프린트당 85스토리 포인트에서 119스토리 포인트로 늘어났습니다.
- PR 사이클 타임이 3.2일에서 1.4일로 단축되었습니다. 이는 더 간단한 컴포넌트 로직과 빠른 테스트 실행 덕분입니다.
- 전체 프로덕션 빌드 시간이 8.1분에서 2.3분으로 감소했으며, 이는 71 % 감소에 해당합니다.
- 신입 사원 온보딩 시간이 3주에서 1주로 단축되었습니다. React의 더 단순한 사고 모델과 방대한 커뮤니티 리소스가 온보딩을 용이하게 했습니다.
- 메인 번들 크기가 32 % 감소해 1.4 MB가 되었으며, 전 세계 사용자 기반의 초기 로드 시간이 27 % 감소했습니다.
배운 교훈
- Define clear success metrics upfront – 리팩터링을 속도와 성능 목표에 연결함으로써 이해관계자의 동의를 확보하고 팀을 정렬시켰다.
- React 20’s Server Components delivered unexpected wins – 정적 페이지의 60 %에 대해 클라이언트 측 렌더링을 제거하여 SEO를 개선하고 클라이언트 측 JS 로드를 감소시켰다.
- Don’t underestimate state‑management migration – 복잡한 RxJS 옵저버블 체인 때문에 NgRx 흐름을 Redux Toolkit으로 포팅하는 데 예상보다 3배 더 오래 걸렸다.
- Concurrent rendering improved UX for heavy interactions – 10k+ 행을 가진 데이터 테이블이 이제 메인 스레드를 차단하지 않고 렌더링되어, Angular 빌드에서 흔히 겪던 문제점을 해결했다.
결론
리팩터링은 큰 투자였지만, 40 % 속도 향상이 이미 4개월 만에 개발 시간을 회수했습니다. 우리 팀은 직무 만족도가 높아졌으며, 기능을 더 빠르게 배포하고 사용자에게는 더 빠르고 안정적인 앱을 제공하고 있습니다. 만약 여러분의 팀이 Angular에서 비슷한 확장성 문제에 직면하고 있다면, React 20은 평가해볼 만한 매력적인 대안입니다.