(번역)React로 돌아가기

강엽이·2023년 11월 26일
13
post-thumbnail

원문: https://daily.dev/blog/moving-back-to-react

daily.dev는 개발 이슈를 해결하고 성능을 향상시키기 위해 프런트엔드 프레임워크를 Preact에서 React로 전환했습니다. 팀 해커톤에서 실행된 이 전환은 충분한 계획, 테스트 및 코드베이스 수정이 동반되었습니다. 이러한 전환을 통해 Next.js와의 호환성이 향상되고 개발 경험이 향상되었으며 향후 기술 발전을 위한 플랫폼을 준비할 수 있었습니다.

얼마 전까지만 해도 daily.dev의 내부에서 실행되던 프런트엔드 프레임워크는 Preact였습니다. 서버 사이드 렌더링, 라우팅 및 데이터 페칭과 같은 핵심 기능을 위해 선택한 프레임워크인 Next.js와 함께 사용하고 있었습니다. Preact를 선택한 주된 이유 중 하나는 작은 Preact 라이브러리 사이즈와 Next.js와의 호환성 때문이었으며 당시에는 논리적인 선택이었습니다. 하지만 최근 자바스크립트 프런트엔드 프레임워크의 발전과 몇 가지 장기적인 문제로 인해 상황이 바뀌었고, 결국 React로 전환하기로 결정했습니다. 이 글은 우리가 어떻게 그리고 왜 그렇게 했는지에 대한 내용을 소개합니다.

설정

Preact를 사용하면서 호환성 레이어 및 Next.js Preact 플러그인을 통해 Next.js와 일반적인 React 기능이 작동하도록 했습니다. 패키지 관리자를 통해 별칭을 지정하여 React를 Preact 라이브러리로 대체했습니다. 또한 많은 Next.js 기능을 지원하는 Vercel을 호스팅 플랫폼으로 사용했습니다. 저희는 Next.js와 Vercel에 관련된 기능을 많이 사용하기 때문에 Next.js 프레임워크의 최신 버전을 유지하고 더 나은 DX(개발 경험)를 갖고자 했습니다.

문제

웹 기술이 발전함에 따라 자바스크립트와 React 프레임워크 세계는 끊임없이 변화하고 있습니다. 프로젝트를 건강하게 유지하고 새로운 기술을 수용하기 위해서는 이러한 변화를 따라잡는 것이 중요합니다. 우리는 이를 염두에 두고, Preact 설정이 Next.js와 함께 작동하도록 유지하는 데 필요한 많은 해결책을 발견했습니다. 앱이 프로덕션 모에는 정상적으로 실행되지만 개발 모드에서는 몇 가지 문제가 있다는 것을 발견했습니다.

  • 핫 리로딩
  • 에러 핸들링
  • 전반적으로 느린 환경 및 렌더링

마지막 문제는 특히 더 심각했는데, 개발 모드에서 Preact를 사용하는 것은 예상보다 훨씬 느렸습니다. 그 결과 브라우저 탭이 계속 멈추고 코드베이스가 변경되면 핫 리로드도 매우 느려졌습니다. 단순한 컴포넌트든 복잡한 페이지든 상관없이 앱의 모든 부분에서 이 문제가 발생했습니다. 모든 종류의 개발 작업에서 속도가 느려지는게 가장 큰 문제였습니다.

문제를 해결하기 위해 가장 먼저 한 일은 Preact 및 Next.js용 호환성 플러그인을 비활성화하는 것이었습니다. 이는 성능 문제에는 도움이 되었지만, 핫 리로딩이 더 이상 앱에서 작동하지 않는 결과를 초래했습니다. 위의 "수정(fix)" 이외에도 추가적인 디버깅을 시도한 후에 언급된 호환성 플러그인을 다시 활성화 했습니다. 하지만 사용자 지정 설정 및 여러 재정의에 의해 동작하는 부분이 너무 많았기 때문에, 성능 문제가 존재하는 느린 개발 환경이 아니고서는 작동시킬 수 없었습니다.

또한 앱 초기화 및 리렌더링 발생 시 상태 변화량과 같은 렌더링 성능도 분석하여 성능을 개선할 수 있는 몇 가지 방법을 찾았지만 주요 문제를 해결하지는 못했습니다. 결국 Preact를 사용하지 않고 Next.js의 기본 구성으로 전환해 보았습니다. 모든 재정의, 플러그인 및 사용자 정의 설정을 빠르게 제거하기로 결정했고, 이는 "동작하게 만드는" 해결책이었고, 효과가 있었습니다!

마이그레이션이 필요하다는 것을 알고 있었기 때문에 우리는 가정을 검증하기 위해 React로 개념 증명(Proof of Concept, POC)를 진행했습니다. 일부 팀원들은 새로운 기능을 개발하는 동안 개념 증명용 앱을 사용해보기도 했습니다. 피드백에 따르면 이 버전은 Preact 설정과 관련된 모든 문제를 해결했기 때문에 이제 작동할 것이라는 확신이 들었습니다! 💪

React 평가

Preact를 React로 교체하면 문제가 해결될 것이라는 것을 알고 있었지만, 한 프런트엔드 프레임워크에서 다른 프레임워크로 변경하는 것은 여전히 쉬운 일이 아니었습니다. 주요 목표는 개발 환경을 개선하여 계속해서 효율적으로 서비스를 제공할 수 있도록 하는 것이었습니다.

이러한 아키텍처 변경에는 앱의 여러 측면에 대한 전반적인 작업이 필요합니다. daily.dev 모노레포는 여러 앱(브라우저 익스텐션, 웹 앱, 모바일 PWA 앱)을 지원하기 때문에 모든 앱이 계속 작동하고 기존 기능도 지연이나 중단 시간 없이 제공할 수 있는지 확인해야 했습니다.

또한 새로운 버그나 회귀가 발생하지 않도록 확인하고 코드베이스를 깔끔하고 유지 보수하기 쉽게 유지해야 했습니다. 또한 새로운 성능 문제가 발생하지 않도록 하고 번들 크기를 가능한 한 작게 유지하고자 했습니다. 이를 염두에 두고 React로 전환할 때의 일반적인 장단점을 적어보았습니다.

장점

  • React는 Next.js와 100% 호환됩니다.
  • React를 사용하면 향후에 Next.js의 고급 기능을 활용할 수 있고, React 18과 같은 주요 버전과 새로운 훅 및 API를 따라갈 수 있게 됩니다.
  • 번들 별칭, 설정 및 재정의 없이 기본 Next.js 구성만 사용하므로 유지 보수할 설정 코드가 줄어듭니다.
  • 써드파티 라이브러리가 감소합니다.
  • 보다 일관된 API를 제공합니다. Preact는 현재 React를 지원하고 다른 프레임워크의 새로운 기능(예: 시그널)을 도입하는 중입니다. 이는 멋지긴 하지만 여러 개발 경로를 가져 복잡하게 되어버리는데, 이는 우리에게는 이상적이지 않습니다.
  • React는 VercelMeta(Facebook)와 같은 대기업의 지원을 받고 있습니다.

단점

  • 번들 크기 증가 (Preact 크기는 React보다 훨씬 작음)
  • 프로젝트에 많은 변경. 많은 곳에서 Preact와 그 라이브러리 참조하고 있음
  • 기술 부채. Preact는 React와 크게 다르지 않지만 현재 비활성화된 린트 규칙으로 전달되는 잘못된 훅 호출 및 컨텍스트 사용과 같은 패턴을 허용하지만 React에서는 앱을 중단
  • 마이그레이션 중 다른 개발 작업의 시간 할당 및 스케줄링 필요

번들 사이즈

과거에 Preact를 선택한 주된 이유 중 하나는 훨씬 더 작은 크기로 React와 동일한 기능을 담았기 때문입니다.

프로덕션 빌드의 번들 크기를 페이지 크기와 다양한 청크에 걸쳐 테스트했습니다. 또한 Next.js 빌드 산출물은 보기 좋은 개요를 제공하므로 이전과 이후를 비교하기가 쉬웠습니다. 몇 가지 주요 페이지를 살펴보겠습니다.

모든 페이지에서 "First Load JS"의 용량이 34KB 증가한 것을 확인할 수 있는데, 이것이 바로 우리가 측정한 React와 Preact의 정확한 차이입니다. 이는 React를 추가한 후 프레임워크 번들이 34KB 증가했고, 이 번들은 모든 페이지에서 공유되므로 모든 페이지가 동일하게 증가했기 때문입니다.

사용자가 특정 페이지에 처음 방문했을 때만 'First Load JS'가 적용되며, 그 이후에는 각각의 새 페이지 크기가 위 표의 'Size' 열과 같다는 점에 유의해야 합니다. 정확한 페이지 크기는 위의 "Size" 열에서 볼 수 있듯이 동일하게 유지되었습니다(1KB 차이 이내). 이것은 React가 번들 크기에 다른 오버헤드를 추가하지 않는다는 것을 확인시켜줍니다. 좋은 점은 프레임워크 번들은 크기를 예측할 수 있고 브라우저에서 쉽게 캐싱할 수 있으므로 그 증가를 부분적으로 완화할 수 있다는 것입니다.

이 분석 결과로 번들 크기를 최적화할 수 있는 몇 가지 지점을 파악했습니다. 마이그레이션 중에 모두 구현되지는 않았지만, 일반 프로젝트 유지 보수 계획의 일부로 추후에 해결할 수 있도록 기록해 두었습니다.

계획

위의 모든 사항을 고려하여 팀 전체가 마이그레이션을 진행하기로 결정했습니다. 당시 막 폴란드에서 열린 팀 모임에서 해커톤 프로젝트로 진행하기로 결정했습니다. 우리는 재택 근무를 하는 팀이기 때문에 이러한 모임은 모든 사람을 볼 수 있을 뿐만 아니라 직접 얼굴을 맞대고 작업을 할 수 있는 기회이며 익숙한 방식보다 더 동기화된 커뮤니케이션의 이점을 누릴 수 있습니다. 덕분에 팀 전체가 한 공간에 모여 같은 문제에 대해 함께 작업할 수 있었습니다.

모임 기간 동안에는 다른 주요 기능 배포가 없고 모든 팀원이 마이그레이션에 집중할 수 있기 때문에 완벽한 타이밍이라고 생각했습니다. 대부분의 팀원이 금요일에 귀국했기 때문에 모든 인력이 참여하면 1주일, 즉 약 4일의 근무일이 주어졌습니다. 여전히 짧은 시간이었기 때문에 모임 전에 계획을 수립하는 것이 중요했습니다. 즉, 실행할 때가 되었을 때 모두가 같은 생각을 가지고 있어야 했습니다. 우리는 마이그레이션 과정에서 주요하게 다뤄야 할 세 가지 영역을 확인했습니다.

핵심 프로젝트 변경 사항

이 변경 작업에는 Preact의 모든 재정의와 종속성을 제거하는 작업이 포함되었습니다. 각 멤버가 동일한 코드베이스에서 작업을 시작할 수 있도록 다른 작업 전에 이 작업을 수행해야 했습니다. 브라우저 익스텐션도 Preact를 사용하고, Next.js 앱과는 별도의 빌드 프로세스를 가지고 있기 때문에 동일한 작업을 수행해야 했습니다.

코드베이스 테스트

프로젝트에 많은 테스트가 있고 새로운 버그나 회귀가 발생하지 않도록 해야 했기 때문에 모든 테스트가 통과되어야 했습니다. 또한 React와 함께 작동하는 Jest의 핵심 버전도 교체해야 했습니다.

호환성(페인) 포인트

Preact 호환성 레이어를 사용하면 이미 React API를 사용하고 있는 많은 컴포넌트들이 문제 없이 React로 전환될 수 있습니다.

즉, Preact는 React에서 할 수 있는 것과 할 수 없는 것에 대해 약간 느슨합니다. 이는 더 많은 도구를 제공하기 때문에 좋지만 일반적인 개념을 깨뜨려 버그를 유발하기도 합니다. 이미 몇 가지 버그가 발견되었기 때문에 프로덕션 앱을 개선할 수 있는 기회이기도 했습니다.

경고와 오류의 두 가지 카테고리로 구분했습니다. 경고는 대부분 잘못된 프로퍼티가 기본 DOM 요소로 전달되는 것으로, 버그로 이어지지는 않지만 브라우저 콘솔을 어지럽히고 다른 문제를 디버깅하기 어렵게 만듭니다. 오류는 대부분 React API의 잘못된 사용으로 인해 발생했으며, 버그를 유발하고 앱을 망가뜨리기도 했습니다. 렌더링 중 상태 설정, React 컴포넌트/훅 외부의 컨텍스트 접근 또는 이벤트 핸들러의 메모리 누수와 같은 것들이었습니다.

계획 단계의 결과는 다음과 같습니다.

  • 마이그레이션에 대한 모든 분석 및 컨텍스트가 포함된 DR(의사 결정 기록)
  • 모든 핵심적인 프로젝트 변경 사항이 포함된 에픽 브랜치 및 PR을 Github 리포지토리에 오픈
  • 수행해야 할 작업에 대한 명확한 지침이 포함된 작업 목록

실행

모임 주간이 다가왔고, 모두 모여 작업을 시작했습니다! ⌨️

첫째 날이 지나고 나서 모든 핵심적인 프로젝트 변경사항을 처리하고 코드베이스에서 발견된 대부분의 경고를 분류했습니다. 이는 매우 효율적이었기 때문에 계획이 결실을 맺었다는 것을 즉시 알 수 있었습니다.

둘째 날과 셋째 날도 꽤 순조롭게 진행되었습니다. 우리가 겪었던 대부분의 문제는 사실 Jest의 React 버전을 연결한 후 발견한 불안정한 테스트와 관련된 것이었습니다. 또한 몇 가지 메모리 누수와 재렌더링 문제도 React API 사용법을 조정하는 것만으로 해결할 수 있었습니다.

모임 마지막 날에는 모든 중요한 사용자 흐름이 제대로 작동하는지 확인하기 위해 앱에 대한 여러 번의 검토와 E2E(엔드투엔드) 테스트를 진행했습니다. 또한 최종 번들 크기 분석도 수행하여 불필요한 부분이 없는지 확인했습니다.

또한 각 팀원들은 에픽 브랜치의 모든 변경 사항을 최종적으로 검토했습니다. 실망하셨을 수도 있지만 금요일에 모든 것을 프로덕션에 병합하지는 못했습니다 😂. 하지만 축하할 만큼 최선을 다했습니다! 전반적으로 분위기와 성취감은 훌륭했습니다🍻. 마침내 아무 문제 없이 모임을 마친 후 다음 주에 프로덕션에 병합했습니다.

다음은?

이 마이그레이션을 시작한 이유는 몇 달 동안 새로운 기능을 개발하고 제공하는 데 방해가 되는 나쁜 개발 경험(DX)으로 인한 문제가 있었기 때문입니다 😥. 여러 방법을 시도해봤지만 가장 효과가 있었던 것은 체계, 계획 그리고 훌륭한 팀워크였습니다. ✅

React 마이그레이션은 많은 노력이 필요했지만 성공적이었으며 모든 앱의 더 좋은 미래가 가능해졌습니다! 🚀

Preact 호환성 때문에 Next.js와 같은 핵심 라이브러리를 최신 버전으로 업그레이드할 수 없었습니다. React로 전환함으로써 더 발전할 수 있게 되었고 제품을 개선할 수 있는 기능들을 추가할 수 있게 되었습니다. 🙌 React로 전환하는 동안 다른 라이브러리에 대한 대대적인 업그레이드는 이루어지지 않았지만, 앞으로의 업그레이드가 기대됩니다.

우리가 작업한 모노레포는 오픈소스로 여기에서 주요 풀 리퀘스트를 비롯한 모든 관련 풀 리퀘스트를 살펴볼 수 있습니다. 즐겨보세요! 🎉

profile
FE Engineer

0개의 댓글