Code Splitting

박기찬·2023년 6월 25일
1

Web tech

목록 보기
1/9
post-thumbnail

코드 스플리팅(Code Splitting) 은 프론트엔드 애플리케이션의 번들을 작은 조각으로 분할하여 필요한 부분만 로드하는 최적화 기법입니다. 이를 통해 초기 로딩 속도를 개선하고 사용자 경험을 향상시킬 수 있습니다.


일반적으로 웹 애플리케이션은 모든 자원(JavaScript, CSS, 이미지 등)을 하나의 번들로 묶어서 로드합니다. 그러나 애플리케이션이 커지면 번들의 크기가 증가하고, 초기 로딩 시간이 늘어나는 문제가 발생할 수 있습니다. 이때 코드 스플리팅을 적용하여 애플리케이션을 더 작은 번들로 분할하면, 사용자는 필요한 부분만 로드하고 시작할 수 있습니다.

코드 스플리팅을 구현하는 방법은 프레임워크나 라이브러리마다 다를 수 있지만, 대부분의 프론트엔드 프레임워크는 동적 임포트(Dynamic Import)나 코드 분할 도구를 제공합니다.

애플리케이션 복잡화나 유지 관리에 의해 CSS와 JavaScript 파일이나 번들이 커지며, 특히 포함하고 있는 서드파티 라이브러리 개수, 용량이 클수록 커집니다. 큰 파일을 다운로드하지 않도록 스크립트를 작게 여러 파일로 분할할 수 있습니다. 그렇게하면 화면 로딩할 때 필요한 기능은 바로 다운로드할 수 있으며, 추가 스크립트는 화면이나 애플리케이션 상호 작용시에 지연 로딩해서 기능 향상할 수 있습니다. 코드 총량은 같지만(아마 파일 숫자나 용량은 늘어납니다.), 초기 로딩에 필요한 코드는 적어집니다. - Mdn web docs


동적 임포트 (Dynamic Import)

동적 임포트(Dynamic Import)는 ECMAScript 모듈 시스템의 기능으로, 필요한 모듈이 실제로 사용될 때까지 로드되지 않는 기법입니다. 이를 통해 애플리케이션의 일부를 나중에 필요한 시점에 로드하여 초기 로딩 속도를 개선할 수 있습니다.

동적 임포트는 import() 함수를 사용하여 구현할 수 있습니다. import() 함수는 Promise()를 반환하며, 이를 통해 동적으로 필요한 모듈을 로드하고 해당 모듈을 사용하는 코드를 실행할 수 있습니다.

import('./module').then((module) => {
  // use module
});

예를 들어, 특정 버튼을 클릭하면 해당 모듈을 실행하는 코드가 있다고 가정해보겠습니다.

function App() {
    const handleClick = () => {
        import('./clickEventModule').then(result => result.default());
    };

    return (
        <div className="App">
            <header className="header">
                <button onClick={handleClick}>click btn</p>
            </header>
        </div>
    );
}

이 경우, 버튼을 클릭하면 필요로 하는 모듈을 불러오게
됩니다.

동적 임포트는 여러 가지 상황에서 유용하게 활용될 수 있습니다.

  • 라우팅된 페이지 로드 - 사용자가 특정 페이지로 이동했을 때 해당 페이지의 번들을 동적으로 로드하여 필요한 시점에 렌더링하는 방식입니다. 이를 통해 초기 로딩 속도를 개선할 수 있습니다.

  • 컴포넌트 지연 로드 - 애플리케이션의 초기 로딩 시점에는 필요하지 않은 컴포넌트를 동적으로 로드하여 필요한 시점에만 렌더링하도록 할 수 있습니다. 이는 애플리케이션의 초기 번들 크기를 줄이고 성능을 향상시킵니다.

  • 조건부 모듈 로드 - 특정 조건에 따라 모듈을 로드할 수 있습니다. 사용자의 행동에 따라 다른 기능을 제공하는 경우에 동적 임포트를 활용하여 필요한 모듈을 동적으로 로드할 수 있습니다.


React.Lazy, Suspense


React에서는 코드 스플리팅을 더욱 쉽게 구현할 수 있도록 React.Lazy와 Suspense라는 기능을 제공합니다. 리액트 V16.6부터 추가된 기능입니다. 이를 활용하면 기존 방식보다 더 쉽게 동적으로 컴포넌트를 로드하고 로딩 상태를 처리할 수 있습니다.


React.Lazy

React.Lazy는 동적으로 컴포넌트를 로드하기 위한 React의 레이지 로딩 기능입니다. 컴포넌트를 필요한 시점에 로드할 수 있으며, 필요한 모듈을 자동으로 분리하여 별도의 번들로 생성합니다.

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

위의 예시에서 'thisComponent'는 동적으로 로드되는 컴포넌트입니다. import() 함수를 사용하여 필요한 모듈을 비동기적으로 로드하고, React.lazy() 함수로 렌더링 할 컴포넌트를 생성합니다.

Suspense

Suspense는 React.Lazy와 함께 사용되는 기능으로, 로딩 상태를 처리하기 위한 컴포넌트입니다. Suspense 컴포넌트는 로딩 중인 동안 특정한 UI를 렌더링할 수 있어, 사용자 친화적인 환경을 구성할수 있게 도와줍니다.

다음은 React.lazy와 Suspense를 활용하는 방식입니다.

먼저, React.lazy와 함께 동적으로 로드할 개별적인 자바스크립트 파일로 생성된 컴포넌트를 생성합니다.

// NeedComponent.js

import React from 'react';

const NeedComponent = () => {
  return <div>need Component</div>;
};

export default NeedComponent;

그 후, React.lazy와 함께 React.Suspense 컴포넌트를 사용하여 동적으로 컴포넌트를 로드하고 로딩 상태를 처리합니다.

import React, { lazy, Suspense } from 'react';

const LazyComponent = lazy(() => import('./NeedComponent'));

const App = () => {
  return (
    <div>
      <Suspense fallback={<div>Loading...</div>}>
        <LazyComponent />
      </Suspense>
    </div>
  );
};

export default App;

위의 예시에서 Suspense 컴포넌트의 fallback 속성을 사용하여 로딩 중에 보여줄 대체 컨텐츠를 설정합니다. 대체 컨텐츠는 JSX 문법으로 작성합니다.

Suspense 컴포넌트로 감싼 LazyComponent 컴포넌트를 렌더링하는 시점에서 해당 컴포넌트가 비동기적으로 로드됩니다. 로드되기 전에는 fallback에 설정한 로딩 메시지가 보여지며, 로드가 완료되면 실제 컴포넌트가 렌더링됩니다.

이처럼, React.Suspense 컴포넌트를 사용하면 코드 스플리팅된 컴포넌트의 로딩 상태를 처리할 수 있습니다.
이를 통해 초기 로딩 속도를 개선하고 필요한 컴포넌트만 로드하여 자원을 효율적으로 관리할 수 있습니다.



앞선 방법을 통해 코드 스플리팅을 통해 필요한 코드만 로드하고 초기 로딩 속도를 개선함으로써 사용자 경험을 향상시킬 수 있습니다. 그러나 코드 스플리팅을 적용할 때는 애플리케이션 구조와 사용 패턴을 고려하여 적절한 분할 전략을 수립해야 합니다. 일부 자원이 반복적으로 사용되는 경우 캐싱 효과가 떨어질 수 있으므로, 적절한 분할 단위를 설정하는 것이 중요합니다.

해당 파트는 웹팩과 번들링에 관한 상세한 개념 정리가 필요해보입니다.




https://ko.legacy.reactjs.org/docs/code-splitting.html
https://webpack.js.org/
https://developer.mozilla.org/en-US/docs/Glossary/Code_splitting

profile
프론트엔드 개발자 🧑

0개의 댓글