WEB🔨/React

리액트를 다루는 기술 요약#12

최문경 블로그 2021. 7. 11. 11:55

해당 시리즈는 제목 그대로 김민준님의 '리액트를 다루는 기술'을 요약한 글입니다.

 

목차

19장 코드 스플리팅

 

 

19장 코드 스플리팅

CRA의 기본 웹팩 설정에는 SplitChunk라는 기능이 적용되어 node_modules에서 불러온 파일, 일정 크기 이상의 파일, 여러 파일 간에 공유된 파일을 자동으로 따로 분리시켜서 캐싱의 효과를 누릴 수 있게 해줌.

 

yarn build 이후

이렇게 파일을 분리하는 작업을 코드 스플리팅이라고 함.

하지만 프로젝트에 기본 탑재된 SplitChunks기능을 통한 코드 스플리팅은 단순히 효율적인 캐싱 효과만 있음.

예를 들어 페이지 A, B, C로 구성된 SPA를 개발한다고 했을 때, 사용자가 A 페이지에 방문했다면 B, C 페이지에서 사용하는 컴포넌트 정보는 필요하지 않음. (사용자가 B 또는 C 페이지로 이동했을 때만 필요함)

 

하지만 리액트 프로젝트에 별도로 설정하지 않으면 A, B, C 컴포넌트에 대한 코드가 모두 한 파일(main)에 저장됨.

이러한 문제점을 해결해 줄 수 있는 방법이 바로 코드 비동기 로딩. 이 또한 코드 스플리팅 방법 중 하나.

 

 

자바스크립트 함수 비동기 로딩

export default function notify() {
  alert('Hello');
}
import logo from './logo.svg';
import './App.css';
import notify from './notify';

function App() {
  const onClick = () => {
    notify();
  };
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p onClick={onClick}>Hello</p>
      </header>
    </div>
  );
}

export default App;

이렇게 코드를 작성하고 빌드하면 notify 코드가 main 파일 안에 들어감.

 

하지만 다음과 같이 import 를 상단에서 하지 않고 메서드 안에서 사용하면, 파일을 따로 분리시켜서 저장함. 그래서 실제 함수가 필요한 지점에서 파일을 불러와서 함수를 사용할 수 있음.

import logo from './logo.svg';
import './App.css';

function App() {
  const onClick = () => {
    import('./notify').then((result) => result.default());
  };
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p onClick={onClick}>Hello</p>
      </header>
    </div>
  );
}

export default App;

4로 시작하는 파일이 새로 생긴 것을 볼 수 있음.

 

 

19.2 React.lazy와 Suspense를 통한 컴포넌트 코드 스플리팅

React.lazy는 컴포넌트를 렌더링하는 시점에서 비동기적으로 로딩할 수 있게 해주는 유틸 함수이고 Suspense는 코드 스플리팅된 컴포넌트를 로딩하도록 발동시킬 수 있고, 로딩이 끝나지 않았을 때 보여 줄 UI를 설정할 수 있는 리액트 내장 컴포넌트.

import React, { useState, Suspense } from 'react';
import logo from './logo.svg';
import './App.css';
const SplitMe = React.lazy(() => import('./SplitMe'));

function App() {
  const [visible, setVisible] = useState(false);
  const onClick = () => {
    setVisible(true);
  };
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p onClick={onClick}>Hello</p>
        <Suspense fallback={<div>loading...</div>}>
          {visible && <SplitMe />}
        </Suspense>
      </header>
    </div>
  );
}

export default App;

 

 

Loadable Components를 통한 코드 스플리팅

Loadable Components는 코드 스플리팅을 편하게 하도록 도와주는 서드파티 라이브러리. React.lazy와 Suspense는 서버 사이드 렌더링을 지원하지 않지만 이 라이브러리는 서버 사이드 렌더링을 지원함.

 

yarn add @loadable/component

 

import React, { useState } from 'react';
import logo from './logo.svg';
import './App.css';
import loadable from '@loadable/component';
const SplitMe = loadable(() => import('./SplitMe'), {
  fallback: <div>loading...</div>,
});

function App() {
  const [visible, setVisible] = useState(false);
  const onClick = () => {
    setVisible(true);
  };
  const onMouseOver = () => {
    SplitMe.preload();
  };
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p onClick={onClick} onMouseOver={onMouseOver}>
          Hello
        </p>
        {visible && <SplitMe />}
      </header>
    </div>
  );
}

export default App;

이렇게 코드를 쓰면 마우스 커서를 올리기만 해도 로딩이 시작되고 클릭했을 때 렌더링이 됨.

 

 

정리

서버 사이드 렌더링을 할 계획이 없다면 React.lazy와 Suspense로 구현하고, 계획이 있다면 Loadable Components를 사용해야 함. 리액트 공식 문서에서도 서버 사이드 렌더링을 할 경우 Loadable Components 라이브러리를 사용하도록 권장.