Dynamic Import

Static Import의 채팅 앱 예제에서는 네 가지 주요 컴포넌트들이 있다: UserInfo, ChatList, ChatInput, EmojiPicker. 그러나 페이지가 처음 로드될 때에는 이 중에 세가지 컴포넌트만 있어도 된다: UserInfo, ChatList, ChatInput. EmojiPicker 는 직접적으로 보여지지 않고, 사용자가 이모지 버튼을 눌러을 때만 보여주면 된다. 따라서 EmojiPicker를 초기 번들에 포함하여 불필요하게 로딩 타임을 증가시킬 필요가 없다.

이를 위해 EmojiPicker를 동적으로 포함시킬 수 있다. 정적으로 포함시키는 대신 이모지 버튼을 눌러 화면에 보여져야 할 때 다운로드 받도록 하는것이다. React의 Suspense를 사용하면 이것을 쉽게 처리할 수 있다. React.Suspense는 동적으로 로드되어야 하는 컴포넌트를 받고 App 컴포넌트가 컨텐츠를 렌더링 할 때 EmojiPicker 를 가져오는것을 일시적으로 중단하도록 하여 빠르게 화면을 그릴 수 있다. 사용자가 이모지 버튼을 클릭하면 EmoiPicker 컴포넌트가 렌더링된다. 이 때 EmojiPicker컴포넌트는 원래 렌더링 되어야 하는 EmojiPicker 모듈을 prop으로 받은 Suspense 컴포넌트를 렌더링한다. Suspense컴포넌트는 동적으로 렌더링 될 컴포넌트가 로딩중일 때 렌더링 될 컴포넌트를 받는다.

이로써 EmojiPicker 가 불필요하게 초기 번들에 포함되는 것을 막고 별도의 번들에 포함시켜 초기에 로딩해야 하는 스크립트의 사이즈를 줄일 수 있게 된다.

초기에 로딩되는 번들 사이즈가 작으면 앱이 더 빨리 로드된다. 사용자가 빈 화면에서 기다리는 시간이 줄어든다. fallback컴포넌트는 사용자에게 앱이 멈춘게 아니라 추가적인 모듈이 처리되고 실행되기까지 조금만 기다리면 된 다는 것을 인지시킨다.

Asset                             Size         Chunks            Chunk Names
emoji-picker.bundle.js           1.48 KiB      1    [emitted]    emoji-picker
main.bundle.js                   1.33 MiB      main [emitted]    main
vendors~emoji-picker.bundle.js   171 KiB       2    [emitted]    vendors~emoji-picker

이전 예제에서 초기 번들의 크기가 1.5Mib였던 것에 비해 EmojiPicker를 동적 로딩 처리하여 1.33Mib로 줄어들게 되었다.

아래 예제에서 콘솔을 확인해 보면 이모지 버튼을 누르기 전 까지 EmojiPicker를 불러오지 않는 것을 알 수 있다.

이 앱을 빌드해보면 웹팩이 번들을 여러 개 만드는것을 알 수 있다.

EmojiPicker를 동적 로딩 처리하여 초기에 로드되는 번들의 크기를 1.5Mib에서 1.33Mib 로 줄였다. EmojiPicker를 쓰기까지 사용자는 조금의 시간을 더 기다려야 하긴 하지만 사용자가 앱을 더 빨리 보고 인터렉션 할 수 있게 개선하여 사용자 경험을 향상시켰다.

Loadable Components

서버사이드 렌더링은 아직 React의 Suspense를 지원하지 않고 있다. 이것이 지원되기까지는 [loadable-components](https://loadable-components.com/docs/getting-started/)라이브러리를 사용할 수 있다. SSR앱에서도 사용 가능하다.

React의 Suspense와 유사하게 EmojiPicker모듈은 요청될 때 import되어야 하므로 loadable 컴포넌트에 지연로딩될 모듈로써 전달할 수 있다. 모듈이 로드되기 전 까지는 fallback컴포넌트를 렌더할 수 있다.

loadable-components는 SSR환경에서 React.Suspense의 좋은 대안이지만 CSR에서 모듈을 동적 로드하기 위해서도 사용할 수 있다.