본문 바로가기

HTML + JAVASCRIPT + CSS/ReactJS+AngularJS +VueJS

ReactJS code split

728x90

ReactJS code split

13.code split from Daniel Lim


code split

리액트 프로젝트를 완성하여 사용자에게 제공할 때는 빌드 작업을 거쳐서 배포 합니다.
빌드 작업을 통해 프로젝트에서 사용되는 자바스크립트 파일 안에서 불필요한 주석, 경고 메시지, 공백 등을 제거하여 파일 크기를 최소화하고 브라우저에서 JSX문법이나 다른 최신 자바스크립트 문법이 원활하게 실행되도록 코드의 트랜스파일 작업도 합니다.
이런 작업은 웹팩(webpack)이라는 도구를 사용합니다.
웹펙에서 별도의 설정을 하지 않으면 프로젝트에서 사용중인 모든 자바스크립트 파일이 하나의 파일로 합쳐지고, 모든 CSS 파일도 하나의 파일로 합처집니다.


react standard code split

Create-React-app을 이용하여 프로젝트를 생성하면 최소 두개 이상의 자바스크립트 파일이 생성됩니다.

기본 설정에는 SplitChunks라는 기능이 적용되어 node_modules에서 불러온 파일, 일정 크기 이상의 파일, 여러 파일 간의 공유돈 파일을 자동으로 따로 분리시켜서 캐싱의 효과를 제공합니다.


build 결과

/build/static/js 밑에 2.XXXX로 시작하는 파일이 포함되어 있습니다.
2로 시작하는 파일에는 React, ReactDOM 등 node_modules에서 불러온 라이브러리 관련 코드가 들어 있고, main으로 시작하는 파일에는 직접 프로젝트에 작성하는 App 같은 컴포넌트에 대한 코드가 들어있습니다.

소스 코드를 수정 후 다시 빌드를 해도 node_modules의 변경 없이 2.XXXX 파일명은 변하지 않습니다.

이렇게 파일을 분리하는 작업을 코드 스프리팅이라고 합니다.


React code split

Create-React-app으로 생성된 프로젝트에는 단순히 효율적인 캐싱 효과만 있습니다.
A, B, C로 구성되었고 A 페이지에서는 B 페이지와 C 페이지에서 사용하는 컴포넌트는 필요하지 않습니다.

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

애플리케이션의 규모가 커지면 지금 당장 필요하지 않는 컴포넌트 정보도 모두 불러서 파일 크기가 매우 커집니다.

이런 문제를 해결해 줄 수 있는 방법이 바로 코드 비동기 로딩입니다.
코드 비동기 로딩을 통해 자바스크립트 함수, 객체 혹은 컴포넌트를 처음에는 불러오지 않고 필요한 시점에 불러와서 사용할 수 있습니다.


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

일반 자바스크립트 함수를 스플리팅해본니다.

hi.js

export default () = {
  alert("hi");
}

일반 호출

import React from 'react';
import SayHi from './hi';

export default () = {
  const onClick = () => sayHi();
  return <div onClick={onClick}>HI</div>;
}

비동기 로딩

import React from 'react';

export default () => {
  const onClick = () => {
   import('./hi').then(result => result.default());
  };
  return <div onClick={onClick}>HI</div>;
}

이렇게 import를 함수로 사용하는 문법은 아직 표준 자바스크립트가 아니지만 dynamic import라는 문법입니다. 현재 웹팩에서 지원하고 있음으로 별도의 설정없이 프로젝트에 바로 사용할수 있습니다.
이렇게 불러온 모듈에서 default로 내보낸 것은 result.default로 참조해야 사용할 수 있습니다.


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

React.lazy와 Suspense 기능은 리액트 v16.6에 도입 되었습니다.

import React, { Suspense } from 'react';
const SayHi = React.lazy(() => import('./hi'));
export default () => {
  const [visible, setVisible] = React.useState(false);
  const onClick = () => setVisible(true);

  return (
    <div>
      <p onClick={onClick}>HI</p>
      <Suspense fallback={<div>loading...</div>}>
        {visible && <SayHi />}
      </Suspense>
    </div>
  );
}

Loadable Components를 통한 코드 스플리팅

Loadable Components는 코드 스플리팅을 편하게 하도록 도와주는 서드파티 라이브러리 입니다.
이 라이브러리의 장점은 서버사이느 랜더링(SRR)을 지원한다는 것입니다.
또한 랜더링 하기 전에 필요한 스프리팅된 파일을 미리 불러올 수 있는 기능도 제공합니다.

서버 사이드 랜더링이란 웹 서비스의 초기 로딩 속도 개선, 캐시 및 검색 엔진 최적화를 가능하게 해주는 기술입니다. 서버 사이드 랜더링을 사용하면 웹서비스의 초기 랜더링을 사용자의 브라우정가 아닌 서버 쪽에서 처리 합니다.

설치 & 사용 예

$ yarn add @loadable/component
or
$ npm install @loadable/component --save
import React from 'react';
import loadable from '@loadable/component';
const SayHi = loadable(() => import('./hi'));
export default () => {
  const [visible, setVisible] = React.useState(false);
  const onClick = () => setVisible(true);
  return (
    <div>
      <p onClick={onClick}>HI</p>
        {visible && <SayHi />}
    </div>
  );
}

로딩 중 다른 UI를 보여주고 싶다면 loadable를 사용하는 부분을 다음과 같이 수정합니다.

const SayHi = loadable(() => import('./hi'), {
  fallback: <div>loading...</div>
});

컴포넌트 미리 불러오기

마우스 커서를 올리기만 해도 로딩이 시작됩니다.

import React from 'react';
import loadable from '@loadable/component';
const SayHi = loadable(() => import('./hi'));

export default () => {
  const [visible, setVisible] = React.useState(false);
  const onClick = () => setVisible(true);
  const onMouseOver = () => SayHi.preload();
  return (
    <div>
      <p onClick={onClick} onMouseOver={onMouseOver}>HI</p>
        {visible && <SayHi />}
    </div>
  );
}

마치며

React.lazy / SuspeseLoadable Components의 가장 큰 차이는 서버 사이드 랜더링(SRR)입니다.

서버 사이드 랜더링을 구현할 예정이면 Loadable Components를 사용하도록 래엑트 공식 문서에도 권장하고 있습니다.