본문 바로가기
Archive

React 번들링과 Lazy Loading

by livemehere 2022. 6. 30.

리액트를 개발할때는 webpack과 같은 번들링 툴을 이용하여 번들 된 파일을 웹페이지에 포함하여 한번에 전체 앱을 로드하여 개발합니다.

 

예를 들어 app.js 라는 파일에 math.js 의 함수, 변수들을 import 해서 사용하면 최종적으로 두번째 코드블럭 처럼 하나의 파일에 합쳐지는 것이죠.

// app.js
import { add } from './math.js';

console.log(add(16, 26));
function add(a, b) {
  return a + b;
}

console.log(add(16, 26));

실제로는 이렇게 번들링되지 않고, 좀더 압축된 형태, 원하는 ES 문법 버전으로 바꿀 수 있습니다.

규모가 커진다면..

번들링은 여러 파일을 하나로 합쳐주지만, 앱이 커진다면 번들된 파일도 그만큼 커지게 됩니다.

실수로 규모가 엄청나게 큰 서드파티 라이브러리를 추가한다면 앱의 로드시간이 길어지게 되겠죠.

 

번들이 거대해지는 것을 방지하기 위해서 webpack 과 같은 번들러가 지원하는 "코드 분할"을 사용합니다.

코드 분할은 런타임에 여러 번들을 동적으로 만들고 불러오는 기능입니다.

 

그러면 사용자가 필요한 페이지에서 필요한 만큼의 코드만 불러와 번들링하기 때문에 필요하지 않은 코드들은 불러오지 않으며 앱의 초기화 로딩에 필요한 비용을 줄일 수 있습니다.

React.lazy

React.lazy 함수를 사용하면 동적 import를 사용해서 컴포넌트를 렌더링 할 수 있습니다.

// before
import lazyComponent from 'lazyComponent';

// after
const lazyComponent = React.lazy(()=> import('./lazyComponent'));

React.lazy(callback);

이 함수는 동적 import()를 호출하는 callback 함수를 인자로 가집니다.

import() 함수는 Promise를 리턴하며(ES11 에 추가된 문법), lazy의 인자로 받는 callback 함수가 그것을 Component의 형태로 변경하고 lazy함수는 컴포넌트를 반환합니다.

 

Suspense

이렇게 불러온 컴포넌트는 반드시 <Suspense> 컴포넌트의 하위에서 렌더링 되어야 합니다.

또한 Suspense의 props 로 fallback에 컴포넌트를 넣어줄 수 있는데 이는 컴포넌트가 loading 되기 전에 보여줄 예비 컨텐츠입니다.

 <div>
  <Suspense fallback={<div>Loading...</div>}>
    <OtherComponent />
  </Suspense>
</div>

Suspense의 자식 요소로 여러개의 Lazy 컴포넌트를 감쌀 수 있습니다.

또한 네트워크 장애가 발생했을 경우에 에러바운더리를 통해 사용자에게 알릴 수 있습니다

  <div>
    <MyErrorBoundary>
      <Suspense fallback={<div>Loading...</div>}>
        <section>
          <OtherComponent />
          <AnotherComponent />
        </section>
      </Suspense>
    </MyErrorBoundary>
  </div>

페이지별 Lazy 로딩하기

import React, { Suspense } from "react";
import { BrowserRouter, Link, Route, Routes } from "react-router-dom";

const Home = React.lazy(() => import("./components/Home"));
const About = React.lazy(() => import("./components/About"));

function App() {
  return (
    <>
      <BrowserRouter>
        <Suspense>
          <Routes>
            <Route path="/" element={<Home />} />
            <Route path="/about" element={<About />} />
          </Routes>
        </Suspense>
      </BrowserRouter>
    </>
  );
}

export default App;

 

반응형