[React]React에서의 코드 분할(React.lazy(), Suspense)

도시·2022년 9월 7일
0

React

목록 보기
11/11
post-custom-banner

코드 분할(Code Spliting)

✍ React에서 코드 분할이란?

React는 SPA(Single-Page-Application)로, 사용하지 않는 모든 컴포넌트까지 한 번에 불러오기 때문에 첫 화면이 렌더링 될때까지의 시간이 오래걸린다. 이는 사용자 경험 측면에서 좋지 않으므로, 사용하지 않는 컴포넌트는 나중에 불러오고 필요한 코드만 불러오기 위해 코드 분할(Code Spliting)을 도입하여 번들을 나누는 기술이다.

대부분 React 앱들은 Webpack, Rollup과 같은 툴로 번들링(Bundling)을 하여 HTML 웹 페이지에 JavaScript를 쉽게 추가하였다. JavaScript 코드를 최소한의 수준으로 작성하던 과거에는 이렇게 해도 무리가 없었다. 그러나 점점 모던 웹으로 발전하면서 DOM을 다루는 정도가 정교해지고 엔진이 해석해야하는 코드 양이 많아지게 되자, "번들을 나눈 뒤 필요한 코드만 불러오면 어떨까?"하는 아이디어를 통해 코드 분할을 하기 시작했다.

코드 분할은 런타임 시 여러 번들을 동적으로 만들고 불러오는 것이다. 이 기능은 Webpack, Rollup 등의 번들러에서 지원하고 있다.

✍ React에서 코드 분할하는 방법

그 전까지는 코드 파일의 가장 최상위에서 import 지시자를 사용해 사용하고자 하는 라이브러리 및 파일을 불러오는 방법을 사용했다.

  • Static Import(정적 불러오기)
/* 기존에는 파일의 최상위에서 import로 라이브러리 및 파일을 불러옴. */
import moduleA from "library";

form.addEventListener("submit", e => {
  e.preventDefault();
  someFunction();
});

const someFunction = () => {
  /* 코드 중간에서 불러온 파일을 사용. */
}

코드 분할하고 싶으면 아래와 같이 dynamic import(동적 불러오기)를 사용하면 된다.

  • Dynamic Import(동적 불러오기)
form.addEventListener("submit", e => {
  e.preventDefault();
  /* 동적 불러오기는 코드 중간에서 import 지시자로 불러올 수 있다. */
  import('library.moduleA')
    .then(module => module.default)
    .then(someFunction())
    .catch(handleError());
});

const someFunction = () => {
  /* 여기서 moduleA 사용. */
}

✍ React.lazy()

  • React.lazy 함수를 사용하면 dynamic import를 사용해 쉽게 코드를 분할할 수 있다.
  • React는 SPA(Single-Page-Application)이므로 한 번에 사용하지 않는 컴포넌트까지 불러오는 단점이 있기 때문에, React.lazy 함수를 통해 컴포넌트를 동적으로 import하여 사용하면 렌더링 지연시간을 어느정도 줄일 수 있게 된다.
import Component from './Component';

/* React.lazy로 dynamic import를 감싼다. */
const Component = React.lazy(() => import('./Component'));

✍ React.Suspense

  • Router로 분기가 나누어진 컴포넌트들을 lazy를 통해 import하면 해당 path로 이동할때 컴포넌트를 불러오게 된다. 이 과정에서 로딩하는 시간이 생기게 된다.
  • Suspense는 아직 렌더링이 준비되지 않은 컴포넌트가 있을 때 로딩 화면을 보여주고, 로딩이 완료되면 렌더링이 준비된 컴포넌트를 보여준다.
/* suspense 기능을 사용하기 위해 import. */
import { Suspense } from 'react';

const OtherComponent = React.lazy(() => import('./OtherComponent'));
const AnotherComponent = React.lazy(() => import('./AnotherComponent'));

function MyComponent() {
  return (
    <div>
	  {/* React.lazy로 감싼 컴포넌트를 Suspense 컴포넌트의 하위에 렌더링한다. */}
      <Suspense fallback={<div>Loading...</div>}>
	  {/* Suspense 컴포넌트 하위에 여러 개의 lazy 컴포넌트를 렌더링시킬 수 있다. */}
      <OtherComponent />
	    <AnotherComponent />
      </Suspense>
    </div>
  );
}

React.lazy와 Suspense의 적용

코드 분할을 도입할 위치는 웹 페이지를 불러오고 진입하는 단계인 Route에 이 두 기능을 적용하는 것이 좋다.

import { Suspense, lazy } from 'react';
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';

const Home = lazy(() => import('./routes/Home'));
const About = lazy(() => import('./routes/About'));

const App = () => (
  <Router>
    <Suspense fallback={<div>Loading...</div>}>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/about" element={<About />} />
      </Routes>
    </Suspense>
  </Router>
);

참고자료

profile
UI·UX Designer/Frontend Dev
post-custom-banner

0개의 댓글