React : 코드 스플리팅(code-splitting)

김대은·2022년 7월 28일
0

코드 스플리팅 ?

< Router vs component centric code splitting >

앱의 규모가 커짐에 따라 Bundling 되어 제공되는 파일의 사이즈도 커지게 됨으로써 앱의 로딩 속도가 느려지게 된다. 이러한 문제를 해결하기 위해 Code Splitting을 적용하여 현재 필요한 모듈만 로딩(lazy-load) 되도록 하여 성능을 향상시킬 수 있다.

Dynamic Import

첫 번째 방법은 코드 비동기 로딩이다.
이 방식은 필요한 부분에서 파일을 import 함으로써 필요한 순간에 코드를 불러오게 한다.

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}>code-splitting</p>
            </header>
        </div>
    );
}

export default App

code-splitting이라는 글자(p 태그)를 글릭하면 onClick 함수가 실행되고,
onClick은 notify() 함수를 불러오는 역할을 합니다.
그런데 이렇게 작성하면, 이미 notify()가 선언되어 있어서, 누르기 전에도 notify() 함수 코드가 로드되어있는 상태입니다.
이런 상태가 사용하지 않는데 코드를 불러온 불필요한 사례입니다.

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}>code-splitting</p>
            </header>
        </div>
    );
}

export default App;

함수 처럼 사용한 import 구문은 Promise를 반환합니다.
이렇게하면 onClick 함수가 실행 될때, notify함수를 import 하여 그때부터 로드됩니다.

React.Lazy,Suspense

  • React.Lazy 는 컴포넌트를 렌더링할 때 비동기적으로 로딩하게 해주는 함수입니다.
    다음과 같이 사용합니다.

    React.lazy=(() => 컴포넌트);
  • Suspense 는 코드 스플리팅 되어 로딩되지않은 컴포넌트를 로딩하게 만들어주는 컴포넌트입니다.
    또한 옵션으로, 로딩이 끝나지 않았을때 보여줄 ui를따로 구성할 수도 있습니다.
    fallback은 로딩 중일때 보여줄 ui의 코드를 넣는 공간입니다.
    Suspense컴포넌트 사이에 로딩하고자 하는 컴포넌트를 삽입하면 됩니다.

    import React,{Suspense} from 'react';
    <Suspense fallback={fallback 코드}>
    </Suspense>

    위 두가지를 이용한 코드입니다.

    
    import './App.css';
    import React, {useState, Suspense} from 'react';
    
    const SplitMe = React.lazy(() => import('./SplitMe'));
    
    const 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}>code splitting</p>
                 <Suspense fallback={<div>로딩중...</div>}>
                     {visible && <SplitMe/>}
                 </Suspense>
             </header>
         </div>
     );
    }
    
    export default App;
    

    Loadabl Components 라이브러리

    이 라이브러리는 코드 스프리팅을 편하게 도와주는 동시에 다른 것들과는 달리
    SSR을 가능하게 해줍니다.
    리액트의 공식 문서에서도 서버 사이드 렌더링을 할 경우 이 라이브러리를 사용하도록 권고하고 있습니다

    npm i @loadable/component

    사용법 자체는 Reat.Lazy 에서 Suspense가 빠진 형태와 유사합니다.

      import logo from './logo.svg';
     import './App.css';
     import React, {useState, Suspense} from 'react';
     import loadable from '@loadable/component';
    
     const SplitMe = loadable(() => import('./SplitMe'));
    
     const 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}>code splitting</p>
                     {visible && <SplitMe/>}
                 </header>
             </div>
         );
     }
    
     export default App;

    Suspense 컴포넌트의 fallback 처럼 로딩중에 보여주고 싶은 UI가 있다면 loadable을 다음과 같이 사용해줍니다.

    //변경 전
    const SplitMe = loadable(() => import('./SplitMe'));
    
    //변경 후
    const SplitMe = loadable(() => import('./SplitMe'), {
     fallback: <div>로딩중...</div>
    });
    

preload

마지막으로 더 좋은 UX를 제공하는 preload방식도 알아보겠습니다.
여태까진 클릭을 하면 로딩이 시작되었는데,
이 방식은 클릭 하기 전에 컴포넌트에 마우스가 올라가는 순간 부터 로딩이 시작됩니다.
마우스 오버 이벤트를 등록하면 이를 가능하게합니다.

   import logo from './logo.svg';
   import './App.css';
   import React, {useState, Suspense} from 'react';
   import loadable from '@loadable/component';

   const SplitMe = loadable(() => import('./SplitMe'));

   const 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}>code splitting</p>
                   {visible && <SplitMe/>}
               </header>
           </div>
       );
   }

   export default App;

참조
https://velog.io/@velopert/react-code-splitting

profile
매일 1% 이상 씩 성장하기

0개의 댓글