본문 바로가기
Front-end

코드 스플리팅(Code Splitting)

by 춘_춘 2023. 12. 2.

코드 스플리팅이란?

유저가 사용하는 앱이, 전달해야하는 파일이 커지고, 유저의 브라우저가 파싱(parsing)해야하는 정보도 많아지기 때문에, 하나의 파일을 여러개로 나누고, 우선순위를 두어 순서대로 로딩하는 것입니다.

webpack, rollup, browserify와 같은 모듈 번들러를 이용하여 만들어진 하나의 번들 파일을 여러 개의 번들 파일로 나누는 것을 의미합니다. 하나의 번들 파일을 여러 개의 번들 파일로 나누는 이유는 더 빠른 속도로 화면을 로드하기 위해서 입니다.

 

Next.js 없이 React에서 코드 스플리팅


[ React.lazy ] 

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

 

[ Suspense ]

리액트 내장 컴포넌트로 코드 스플리팅 된 컴포넌트를 로딩하고, 로딩이 끝나지 않았을 때 보여줄 UI를 설정할 수 있다.

fallback이라는 props를 통해 로딩 중에 보여줄 JSX 문법을 지정할 수 있다.

 

[ React.lazy + Suspense ]

import React, { Suspense } from 'react';

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

const myComponent = {
	return (
		<Suspense fallback={<div>Loading...</div>}>
			<SomeComponent />
		</Suspense>)
}

 

코드 분할을 결정하는 요소에는 여러가지가 있으며 가장 많이 쓰는 방법 하나는 라우트 기반 분할이다. 페이지를 불러오는 시간은 페이지 전환에 어느정도 발생하며 대부분 페이지를 번에 렌더링하기 때문에 사용자가 페이지를 렌더링 하는 동안 다른 요소와 상호작용하지 않는다. React.lazy React Router 라이브러리를 사용해 라우트 기반 코드 분할을 설정하면 다음과 같이 나타낼 있다.

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

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

const myComponent = {
	return (
        <Router>
            <Suspense fallback={<div>Loading...</div>}>
             <Switch>
             	<Route exact path="/" component={SomeComponent}/>
              </Switch>
            </Suspense>
        </Router>
        )
}

 

[ Webpack: Entry Point ]

Entry Point 웹팩이 앱에서 번들링하려는 모듈의 진입 파일이다. 리액트 앱이 여러 엔트리 포인트를 설정한다면 각각의 엔트리 포인트 마다 코드 스플리팅이 가능하다.

// webpack.config.js
const path = require('path');

module.exports = {
  mode: 'development',
  entry: {
    index: './src/index.js',
    another: './src/another-module.js',
  },
  output: {
    filename: '[name].bundle.js',
    path: path.resolve(__dirname, 'dist'),
  },
};

 

위와 같이 entry 프로퍼티를 작성하면 웹팩에서 자동으로 index another 다른 chunk 관리를 해서 로딩한다. 경우 웹팩은 간의 의존성(dependency) 분리를 해서 관리하는데, 만약 같은 의존성을 여러 엔트리 포인트에서 가지고 있다면 역시 중복된 로딩이

아져 성능상에 저하를 일으킬 있으므로 중복되는 dependencies 다른 chunk 관리해 주는 것이 바람직하다.

 

Next.js로 코드 스플리팅


[ 다이나믹 라우팅 ]

url이 상황에 따라 변화는 다이나믹 라우팅 처리 또한 pages 디렉토리 하위에서 처리해주면 된다.

우선, 페이지 이동을 위해 만들어두었던 navigation 컴포넌트에 추가적인 코드를 작성해둔다.

// components/Navigation.tsx

const Navigation = () => {
  return (
    <header>
      <ul>
        // 생략...
        <li>
          <Link href="/post/first">
            <a>First Post</a>
          </Link>
        </li>
        <li>
          <Link href="/post/second">
            <a>Second Post</a>
          </Link>
        </li>
      </ul>
    </header>
  );
}

 

이제 pages 디렉토리 하위에 post라는 디렉토리를 만들고 그 하위에 [id].tsx 파일을 생성한다.

import { useRouter } from "next/router";

const Post = () => {
  const router = useRouter();
  const { id } = router.query;

  return (
    <div>
      <p>Post: {id}</p>
    </div>);
}

export default Post;

 

next.js 없이 코드 스플리팅  vs next.js로 코드 스플리팅


⇒ next를 사용하는 이유는, 코드 스플리팅 뿐만아니라, seo 검색엔진 및 아래와 같은 기능을 사용하기 위해 사용이다. 결과는 next.js로 코드 스플리팅 사용하기!

 

next.js 의 대표적인 기능

  • Hot reloading : 저장되는 코드를 자동으로 새로고침
  • Automatic routing : 따로 라우팅하지 않아도 pages 폴더에 있는 파일이 해당 파일 이름으로 라우팅됩니다.
  • single file components : 해당 컴포넌트만 스코프를 가지는 css를 style jsx를 통해 만들 수 있음.
  • server landing : 서버렌더링 한 페이지의 소스를 보면 내부에 소스가 있음
  • code splitting : 내가 원하는 페이지에서 원하는 자바스크립트와 라이브러리 렌더링 가능
  • typescirpt : 웹팩과 바벨을 수정할 필요없이 명령어만 쓰면 자동으로 타입스크립트 컴파일러가 Next.js의 타입을 가져오게 하는 next-end.d.ts 및 트랜스파일을 위한 tsconfig 생성

 

Tip: 브라우저에 쓰이지 않는 코드를 보기

Chrome Dev Tools에서 Cmd+shift+P (혹은 ctrl+shift+P)를 눌러 Coverage를 검색하고 reload를 누르면 아래와 같이 로딩 된 스크립트들을 볼 수가 있죠. 현재 페이지에 쓰이지 않아도, 파싱이 된 코드의 비율도 볼수가 있습니다.

 

 

참고자료

- https://medium.com/humanscape-tech/react에서-해보는-코드-스플리팅-code-splitting-56c9c7a1baa4

- https://devowen.com/342#Webpack%3A%20Entry%20Point-1

'Front-end' 카테고리의 다른 글

2023년 기술 블로그 회고  (1) 2024.01.01
Web Worker  (0) 2024.01.01
Redux-saga  (0) 2024.01.01
Redux vs Zustand  (0) 2023.12.13
React useCallback  (0) 2023.12.04