2022년 마지막 프로젝트의 회고 3 — React Context, next/dynamic

React Context와 Next.js Dynamic Import를 사용해 상태와 로딩을 다룬 프로젝트 회고.

React, Next.js, Frontend

React Context
주요 상태 관리 라이브러리의 다운로드 수 비교 by npm trends
주요 상태 관리 라이브러리의 다운로드 수 비교 by npm trends

일반적으로 React 애플리케이션에서 데이터는 props를 통해 부모 컴포넌트에서 자식 컴포넌트로, 쉽게 하향식으로 전달되곤 한다. 그런데 애플리케이션의 컴포넌트가 복잡하고 계층들이 두터워지면, 명시적으로 이 props를 계속해서 넘겨주는 과정은 번거롭고 코드의 가독성도 손상시킬 수 있다.

이를 위해서 등장한 것이 상태 관리 라이브러리라는 도구들이다. Redux, Mobx, Recoil, Zustand, Jotai 등 세세한 기능은 조금 다르지만, 다들 각자의 강력한 기능을 기반으로 채택되고 있다. 하지만 서드 파티 라이브러리 외에도, React에서도 자체적으로 이러한 상태 관리 기능을 제공한다.

Context - React

이것이 어떤 건지 인지하고는 있었으나, 실제로 프로젝트에 기능적으로 사용해 본 것은 이번이 처음이다. 뭔가 대단한 활용도를 갖게끔 설계한 건 아니지만, 처음 써 본 느낌은 생각했던 것보다 괜찮다는 것이었다.

이전에, Redux를 배울 때 바닐라 자바스크립트 — 사실 타입스크립트 연습을 겸하기 위해 타입스크립트로 작성했었다 — 환경에서 작성해 본 적이 있고, React-redux 또한 React 애플리케이션 환경에서 연습해 본 적이 있다. React Context를 이용해 스토어와 액션을 설계하는 보일러 플레이트 코드를 짜면서, 이전의 Redux와 굉장히 흡사하다고 느꼈다.

하지만 보기 좋게 잘 작성된 리액트 공식 기술 문서와 Redux 보다 비교적 간단한 구조로 인해 Recoil을 처음 배울 때만큼이나 괜찮다고 느꼈다.

이에 더해 Redux, Recoil 등의 상태 관리를 위한 서드 파티 라이브러리를 쓰지 않아 번들링 크기를 줄일 수 있다는 점이 나에게는 긍정적인 요인으로 다가왔고, 모달과 같은 선택적인 인터페이스를 쉽게 보여줄 수 있다는 점 또한 좋았다. 심지어, 라이트 모드와 다크 모드의 테마 전환도 쉽게 전역적으로 관리할 수 있을 것 같다.

물론 이 React Context도 장점만 있는 것은 아니었고, 자주 새로 고치거나, 변경되는 데이터의 스토어로는 적합하지 않고, 복잡한 프론트엔드 애플리케이션의 경우엔 Redux가 더 나을 것이라고 한다.

import dynamic from “next/dynamic”
Photo by James Wiseman on Unsplash
Photo by James Wiseman on Unsplash

Next.js의 엄청난 기능들 중에, Dynamic Import라는 기능이 있다. 이 함수를 통해 불러오는 컴포넌트 혹은 라이브러리는 초기에 클라이언트가 다운로드하게 되는 자바스크립트 번들 파일에 포함되지 않고 사용될 때만 가져오고 번들 파일에 포함되므로, 초기 렌더링을 위한 자바스크립트 다운로드의 코스트를 줄여 성능 향상을 기대할 수 있다. React.lazy처럼, Lazy Loading을 지원하는 것이다.

const ComponentName = dynamic(
  () => import(
    '../components/componentName',
    { /* options */ }
  )
);

기본적인 사용법은 위와 같은데, dynamic의 import 함수 내에 두 번째 파라미터로 여러 가지 옵션의 객체를 받고, 이 객체의 옵션 중에서, loading과 ssr 이 있다.

loading 옵션은 loading: () => <span>Loading…</span>과 같은 문법으로 JSX 요소를 할당해서 사용하는데, React.Suspense의 fallback 속성에 할당하는 로딩 컴포넌트처럼, loading 속성에 지정한 컴포넌트는 해당하는 Dynamic Import를 한 컴포넌트의 서스펜스가 해결되기 전에 먼저 렌더링 되어 보이게 되고, 서스펜스가 해결되고 난 뒤에 해당 컴포넌트가 렌더링 된다.

ssr 옵션은 boolean 타입으로 지정할 수 있는데, false로 지정한 경우, 클라이언트 측에서 해당 컴포넌트를 동적으로 로드하게끔, 서버 렌더링을 방지할 수 있다. 이번 프로젝트에선 활용하지 않았지만, 공식 기술 문서에 따르면 외부 dependency나 컴포넌트가 window 같은 브라우저 API에 의존하는 경우 유용하다고 한다.

실제로, 아토믹 디자인(Atomic Design)을 적용하기 전에, React.lazy와 React.Suspense를 적용하기 위해서 컴포넌트와 페이지들의 대규모 리팩터링이 필요했지만, 아토믹 디자인을 적용하고, Dynamic Import를 이용해서 정말 간단하게 두 기능을 손쉽게 이용할 수 있었다.

References

jotai vs mobx vs recoil vs redux vs zustand | npm trends

React Context vs Redux: Which one is the right winner for professional frontend development

React State Management Libraries: Which one?

Advanced Features: Dynamic Import | Next.js


원문: Medium