[React다루는기술] 25. 코드 스플리팅(Code Splitting)


코드 스플리팅(Code Splitting)은 대규모 웹 애플리케이션을 개발할 때 사용되는 기술로, 애플리케이션의 코드를 여러 개의 작은 조각으로 분할하여 필요한 코드만 사용자에게 제공함으로써 초기 로딩 시간을 줄이고 성능을 향상시키는 방법이다.



1. Code Splitting

전통적으로 웹 애플리케이션은 단일 번들로 제공되었기 때문에, 사용자가 처음 애플리케이션을 로드할 때 모든 코드를 다운로드해야 한다. 이는 초기 로딩 시간을 증가시키고 사용자 경험을 저하시킬 수 있다. 코드 스플리팅은 이러한 문제를 해결하기 위해 애플리케이션을 작은 조각으로 분할하여 필요한 코드만 필요한 시점에 동적으로 로드한다.

  1. 동적 임포트(Dynamic import): ECMAScript 2015(ES6)에서 도입된 기능으로, import() 함수를 사용하여 모듈을 동적으로 로드할 수 있다. 이를 활용하여 필요한 모듈을 필요한 시점에 로드할 수 있다.

  2. Webpack 등의 번들러: 대표적인 자바스크립트 번들러인 Webpack은 코드 스플리팅을 지원한다. Webpack의 설정을 통해 여러 번들을 생성하고, 애플리케이션 실행 시점에 필요한 번들을 동적으로 로드할 수 있다.

  3. React.lazy와 Suspense: 리액트에서는 React.lazySuspense를 사용하여 컴포넌트 레이지 로딩을 구현할 수 있다. 이를 통해 사용자가 필요한 컴포넌트를 필요한 시점에 로드할 수 있다.

  4. Vue Router와 동적 라우팅: Vue.js에서는 Vue Router를 사용하여 동적 라우팅을 구현할 수 있다. 이를 활용하여 특정 라우트에 필요한 컴포넌트를 필요한 시점에 로드할 수 있다.

이러한 코드 스플리팅 기술을 활용하면 초기 로딩 시간을 줄이고 성능을 향상시킬 수 있으며, 사용자 경험을 향상시킬 수 있다.


2. Code Splitting 예제

$ yarn create react-app splitting-sample
$ yarn build

build 를 한 후에 프로젝트/build/static/ 경로를 보면 해시값 형태로 파일명들이 생성되어있는데 이를 통해 브라우저가 새로 파일을 받아야 할지 말지 알 수 있는 것이다.

SplitChunks 라는 웹팩 기능을 통해 자주 바뀌지 않는 파일들은 main.파일명 이 아닌 숫자로 시작하는 파일들이고, 코드 수정을 통한 변경 된 파일들은 main.파일명 로 시작하는 파일들이다.

이렇게 SplitChunks 로 파일을 분리하는 것은 코드 스플리팅이라고 하며, 이렇게 분리해서 SPA어플리케이션에서 페이지가 A부터 Z까지 있다고 할 때 사용자가 접속시에 A~Z 페이지의 모든 컴포넌트와 자바스크립트를 불러오지 않고 사용자가 사용하는 리소스만 사용하는 것이다.

그래서 이러한 문제를 해결해주는게 코드 스플링팅 방법 중 하나인 코드 비동기 로딩 이다. 코드 비동기 로딩을 자바스크립트, 컴포넌트, 객체 등을 필요한 시점에 불러와서 사용하는 개념이다.



2-1. 동적 임포트(Dynamic import) 비동기 로딩

아래와 같이 코드를 작성하고 빌드하면 notify 컴포넌트를 main 파일 안에 들어가게 된다.

import notify from "./notify";

function App() {
  const onClick = () => {
    notify();
  };

  return (
    <div className="App">
      <p>Code SplitChunks 샘플</p>
      <p onClick={onClick}>클릭 notify!</p>
    </div>
  );
}

export default App;


import 를 상단에서 하지 않고 import() 함수 형태로 메서드 안에서 사용하면, 파일을 따로 분리시켜서 저장하고 실제 함수가 필요한 시점에 파일을 불러와서 사용한다.

아래와 같이 import 를 함수로 사용하면 Promise 로 반환하면 동적 임포트(Dynamic import) 문법형태로 작성이 가능하다.

function App() {
  const onClick = () => {
    import("./notify").then((result) => result.default());
  };

  return (
    <div className="App">
      <p>Code SplitChunks 샘플</p>
      <p onClick={onClick}>클릭 notify!</p>
    </div>
  );
}

export default App;



2-2. React.lazy와 Suspense

리액트에서는 내장 함수인 React.lazy와 컴포넌트인 Suspense를 사용하여 컴포넌트 레이지 로딩을 구현할 수 있다. 이를 통해 사용자가 필요한 컴포넌트를 필요한 시점에 로드할 수 있다.

React.lazy 는 컴포넌트를 렌더링하는 시점에서 비동기적으로 로딩할 수 있게 해주는 유틸 함수이다.

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


Suspense 는 리액트 내장 컴포넌트로서 코드 스플리팅 된 컴포넌트를 로딩하도록 발동시킬 수 있고
로딩이 끝나지 않았을 때 보여 줄 UI를 설정할 수 있다.

import { Suspense } from "react";

<Suspense fallback={<div>loading...</div>}>
  <SplitMe/>
</Suspense>


import React, { useState, Suspense } from "react";
const SplitMe = React.lazy(() => import("./SplitMe"));

function App() {
  const [visible, setVisible] = useState(false);
  const onClick = () => {
    setVisible(true);
  };

  return (
    <div className="App">
      <p onClick={onClick}>안녕하세요!!</p>
      <Suspense fallback={<div>loading...</div>}>
        {visible && <SplitMe />}
      </Suspense>
    </div>
  );
}

export default App;



2-3. Loadable Components

Loadable Components는 리액트 애플리케이션에서 코드 스플리팅을 구현하기 위한 라이브러리 중 하나로 Loadable Components를 사용하면 리액트 컴포넌트를 동적으로 로드하여 번들을 분할할 수 있다.

Loadable Components는 로딩 중에 표시할 커스텀 로딩 컴포넌트 및 로딩 에러 처리를 제공하여 사용자 경험을 향상시키며 서버 사이드 렌더링(SSR) 지원한다.

$ yarn add @loadable/component


Loadable 함수를 사용하여 컴포넌트 동적 로드할 컴포넌트를 지정한다.

import loadable from "@loadable/component";
// const SplitMe = React.lazy(() => import("./SplitMe"));
const SplitMe = loadable(() => import("./SplitMe"));
function App() {
  const [visible, setVisible] = useState(false);
  const onClick = () => {
    setVisible(true);
  };

  return (
    <div className="App">
      <p onClick={onClick}>안녕하세요!!</p>
      <Suspense fallback={<div>loading...</div>}>
        {visible && <SplitMe />}
      </Suspense>
    </div>
  );
}




react-deal-book-img