Angular 프로젝트에서 React로 점진적 마이그레이션 시작

배경

3년 전 Angular 1.5로 개발된 어드민 대시보드의 유지보수가 한계에 다다랐다. 컴포넌트 구조도 복잡하고, Two-way binding으로 인한 성능 이슈도 잦았다. 팀 내에서 Angular 2로 갈지 React로 갈지 논의 끝에 React를 선택했다.

마이그레이션 전략

전체를 한 번에 재작성할 수는 없어서 점진적 마이그레이션 방식을 택했다.

  1. 새로운 기능은 React로 개발
  2. 기존 Angular 앱 내부에 React 컴포넌트 마운트
  3. 점진적으로 레거시 교체
// Angular directive로 React 컴포넌트 래핑
angular.module('app').directive('reactWidget', function() {
  return {
    restrict: 'E',
    scope: {
      data: '='
    },
    link: function(scope, element) {
      const container = element[0];
      
      function render() {
        ReactDOM.render(
          React.createElement(Widget, { data: scope.data }),
          container
        );
      }
      
      scope.$watch('data', render);
      render();
      
      scope.$on('$destroy', function() {
        ReactDOM.unmountComponentAtNode(container);
      });
    }
  };
});

겪은 문제들

빌드 설정
Angular는 Gulp 기반, React는 Webpack을 쓰고 싶었다. 결국 Webpack 2로 통합했는데 기존 빌드 프로세스와 충돌이 많았다.

상태 관리
Angular의 $scope와 React의 state를 어떻게 연결할지 고민이 컸다. 일단은 directive의 scope.$watch로 단방향 데이터 흐름만 만들었다.

팀 온보딩
팀원 절반이 Angular만 써봤기 때문에 React 학습 곡선이 있었다. JSX 문법에 거부감을 보이는 사람도 있었다.

현재 상태

신규 통계 대시보드 페이지를 React로 작성해서 배포했다. Angular 라우터에서 해당 경로만 React로 렌더링되도록 구성했다. 아직 Redux 같은 상태관리 라이브러리는 도입하지 않았고, 컴포넌트 props로만 데이터를 전달하고 있다.

앞으로 몇 개월간 점진적으로 교체해 나갈 예정이다.