React vs Angular

huni_·2022년 7월 1일
0

전반적 성능

먼저 짚고 넘어가야 할 부분이 있습니다. 아직도 많은 분들이 Angular는 느리다는 인식을 갖고 계신 것 같은데요. 그런데 속도 문제는 AnuglarJS(Angular1)에는 해당할 수 있지만, Angular(Angular2+)에는 해당하지 않습니다. 즉, Angular(Angular2+)는 React에 크게 뒤지지 않는 성능을 자랑합니다.
위 차트는 Lighthouse Audit으로 측정한 프론트 프레임워크 성능을 나타낸 것인데요. AngularJS의 성능은 꽤 좋지 않은 것으로 측정되었지만, Angular의 성능은 React + Redux 보다 더 좋다는 것을 확인할 수 있습니다([그림 2]). 물론 Angular에 NGXS 같은 전역 상태 관리 라이브러리를 추가하여 측정하였다면 React + Redux와 거의 비슷할 것으로 예상됩니다.
위 차트는 Chrome network tab에서 확인한 전송 크기를 나타낸 것입니다. 전송 크기는 프레임워크 크기와 빌드 도구가 얼마나 더 작게 번들링하는지에 따라 달라집니다. 다들 예상하다시피 AngularJS의 전송 크기는 큰 편에 속하며 Angular는 React + Redux 보다 작은 전송 크기를 보여주고 있습니다([그림 3]).

스토리북 사용성

스토리북(Storybook)은 프론트엔드 개발자가 아니라면 조금 생소할 수 있는 도구인데요. 간략하게 설명하자면 UI 컴포넌트를 독립적인 환경에서 실행하여 컴포넌트 단위로 공유할 수 있고 컴포넌트에 대한 문서화와 UI 테스팅까지 제공하는 오픈소스 도구입니다. 이를 통해 클라이언트를 실행하지 않고 작업하고 있는 마크업 UI를 확인할 수 있어서 마크업 개발자에게 상당히 유용한 도구라고 할 수 있습니다.
만약 Angular가 이전 AngularJS의 성능이었다면 React와 비교하지 않았을 것입니다. 그래도 순수 React와 Angular의 성능을 비교하면 React가 조금 더 유리할 것으로 예상되지만, 현재 성능만으로 React를 선택할 만큼 큰 차이를 보여주고 있지 않다고 생각합니다. 
 
그런데 React와 Angular는 스토리북을 사용하는 방법에서 조금 차이가 있습니다. 여기서 Angular의 모듈 의존성이 단점으로 드러났는데요. 간단한 Angular 예제 코드를 통해 살펴보도록 하겠습니다.

위 코드는 Angular에서 LNB 컴포넌트의 스토리북 코드를 간단하게 작성한 것입니다([예시 1]). 해당 컴포넌트에 종속되는 모듈과 자식 컴포넌트들을 위와 같이 명시적으로 추가해주어야 비로소 하나의 컴포넌트 스토리를 작성할 수 있습니다. 
모든 컴포넌트에 대응할 수 있는 moduleMetadata를 만들어 분리하는 것도 하나의 방법이지만 이 또한 유지보수 비용이 발생하게 되며 각 스토리에 불필요한 모듈들이 추가되어 스토리북 실행 시간이 증가하게 됩니다. 다음은 위와 동일한 역할을 수행하는 React 예제 코드를 살펴보도록 하겠습니다.

위 코드는 React에서 LNB 컴포넌트의 스토리북 코드로,  [예시 1]의 Angular보다 코드가 간결한 것을 볼 수 있습니다. 종속된 모듈이나 자식 컴포넌트들은 해당 컴포넌트에 이미 포함되어 있으므로 스토리북 코드에서 따로 선언할 필요 없이 LNB 컴포넌트만 Import하여 사용하면 됩니다.
프로젝트 전체 구조에서 Angular의 모듈 의존성은 명시적으로 연결고리를 나타내는 것 같아 신뢰도를 높일 수 있는 느낌을 받았지만, 컴포넌트 단위로 UI 확인이 목적인 스토리북과는 다소 어울리지 않다는 생각이 들었습니다. 따라서 스토리북 사용 측면에서는 React가 더 유리하다고 결론내렸습니다.

유닛 테스팅의 용이성

유닛 테스팅(Unit Testing)을 위한 테스트 코드를 작성하는 방법은 스토리북과 비슷한 맥락입니다. Angular의 경우 의존하는 모듈 및 자식 컴포넌트들을 명시해야 하는 반면, React는 해당 컴포넌트만 Import하여 사용하면 됩니다. CLI를 통해 컴포넌트를 생성할 때 자동으로 만들어지는 테스트 코드를 살펴보도록 하겠습니다.

위 코드는 Angular에서 자동 생성된 테스트 코드에서 필요 모듈들을 묶어 놓은 requiredModules를 추가한 모습입니다([예시 3]). requiredModules는 모든 컴포넌트에 대응할 수 있도록 모듈들을 묶어놓았기 때문에 테스트할 때 불필요한 모듈도 포함되어 있을 수 있고,  따라서 그만큼 유닛 테스팅 시간이 길어지게 됩니다. 사실 스토리북의 실행 시간은 그다지 중요하게 느껴지지 않았지만, 유닛 테스팅 시간이 길어지는 것은 조금 부담으로 느껴졌습니다.

위 코드는 React에서 자동 생성된 테스트 코드입니다([예시 4]). Angular와 달리 따로 코드를 추가하지 않아도 테스트를 통과하는 것을 볼 수 있습니다. 해당 컴포넌트만 선언하면 되기 때문에 Angular보다 테스팅 시간도 비교적 짧았습니다. Angular는 모듈 의존성 때문에 독립적인 환경을 구축해야 하는 스토리북이나 유닛 테스팅에서 불리한 것을 볼 수 있었습니다. 저는 이러한 Angular의 모듈 의존성 때문에 React에 더 매력을 느꼈던 것 같습니다.

마크업 개발자와의 협업

마크업 개발자와의 협업도 반드시 고려해야 할 사항이었습니다. Angular에서는 일반적으로 HTML, SCSS, TS 파일을 따로 분리하여 컴포넌트를 개발합니다. 반면 React는 JSX 문법과 Styled Components 라이브러리를 사용하여 오직 Javascript만으로 컴포넌트를 개발하는 것이 대세가 되어가고 있습니다. 따라서 상대적으로 Angular가 마크업 개발자와 협업하기에는 더 유리하다고 생각하였고, 이는 Angular의 장점임에 틀림이 없습니다.
하지만 React에서 이 부분만 보완한다면 선택의 고민을 끝낼 수 있을 것 같다는 생각이 들었습니다. 그래서 저는 고민 끝에 React에서 VAC(View Asset Component)라는 패턴을 적용하게 되었습니다. VAC(View Asset Component)는 다소 생소할 수 있는 개념이지만 매우 간단한 패턴입니다.

HTML과 거의 유사한 뷰(View) 컴포넌트와 비즈니스 로직(Business Logic)만 담고 있는 컴포넌트를 만드는 것으로 역할을 완전히 분리하는 것입니다. 흔히 알고 있는 Presentational 컴포넌트와 Container 컴포넌트 관계처럼 보이지만 VAC 패턴에서는 모든 컴포넌트를 뷰 파일과 로직 파일로 분리한다는 것이 특징입니다. 다음은 VAC 패턴을 적용한 간단한 예시입니다.



위와 같이 모든 컴포넌트는 뷰 컴포넌트와 비즈니스 로직 컴포넌트 쌍으로 존재하게 됩니다. 이로써 React에서도 마크업 개발자는 HTML을 개발하듯이 뷰에 집중할 수 있고 프론트엔드 개발자는 비즈니스 로직에 집중할 수 있습니다.

profile
FrontEnd Developer

0개의 댓글