코드 분할하기 with Suspense, lazy

코드 분할하기

브라우저에서 앱의 모든 코드를 한꺼번에 적재하지 않고 필요할 때 덩어리로 코드를 적재하는 코드 분할(Code Spliting) 기술을 사용하면 적재할 코드의 양을 관리할 수 있다.

  • 트리 셰이킹 과정을 거쳐도, 앱이 무거워질수록 번들을 최대한 작게 만들어도 여전히 로드 시간이 길어질 수 있다.

    • 트리 셰이킹 과정으로 중복 코드를 피하고 사용하지 않는 코드를 제거

  • 앱의 일부가 사용되지 않을 가능성이 높거나 아주 무거운 컴포넌트를 포함하는 경우, 초기 번들의 크기를 줄여 사용자가 상호작용을 시작할 때만 추가 번들을 적재하는 쪽으로 최적화 가능

  • 즉, 실제로 필요할 때 일부 컴포넌트를 동적으로 가져오는 기법

정적 Import를 사용하면 빌드 시 번들러가 코드 검사 후 파일 경로를 따라서 앱이 실제로 사용하는 모든 코드를 포함하는 파일인 번들을 생성한다.

초기 사용자 상호작용에 참여하지 않는 컴포넌트 최적화

lazy 메서드와 Suspense 컴포넌트를 사용해 아래 네가지 작업을 실행

  • 컴포넌트를 렌더링하려 시도 할 때만 코드를 적재

  • 컴포넌트 적재 중에 플레이스홀더를 표시

  • 앱의 나머지 부분을 계속 렌더링

  • 컴포넌트 코드가 적재된 후 플레이스홀더를 해당 컴포넌트로 대체

import 함수로 코드 동적 임포트 with Vanila JS

import 함수로 사용자의 인터렉션 이후에 코드를 동적으로 적재

  • 임포트 함수는 익스포트한 모듈로 해소되는 프로미스를 반환한다.

  • 모듈이 적재된 다음에 작업을 수행하기 위해 프로미스의 then 메서드를 호출함

  • then 대신 async/await 구문 사용 가능

  • 디폴트 익스포트는 default 프로퍼티로 할당됨

  • 구조 분해 사용 가능

lazy와 Suspense를 사용해 동적으로 컴포넌트 임포트

리엑트를 사용하는 경우 상태 갱신에만 집중하고, 리엑트가 DOM을 관리하게 해야 한다.

lazy 함수

React.lazy 를 사용해 컴포넌트가 처음 렌더링될 때 컴포넌트를 적재하라.

  • 렌더링할 컴포넌트가 아직 준비되지 않았을 때 리엑트가 무엇을 해야할지를 선언적으로 알려줘야 한다.

    • lazy 함수를 사용해 컴포넌트를 지연 컴포넌트로 변환하기

    • Suspense 컴포넌트를 사용해 폴백 컨텐츠 지정하기

    • 지연 적재와 Suspense가 어떻게 함께 작동하는지 이해하기

    • 경로에 따라 앱 분할하기

  • lazy에게 프로미스를 반환하는 함수를 전달

  • lazy로 불러온 컴포넌트는 반드시 default export로 만들어져야 한다?

  • 사용하는 컴포넌트에서는 반드시 Suspense로 감싸야한다.

    • lazy 컴포넌트가 적재될 때까지 렌더링할 내용을 리엑트에게 알려주어야 한다.

    • Suspense는 아직 적재되지 않은 컴포넌트가 던지는 보류 중인 프로미스를 잡아낸다.

  • mock Component

Suspense

컴포넌트를 적재하려면 시간이 걸리는데 그동안 사용자에게 컴포넌트를 적재하고 있음을 알려주기 위한 인디케이터가 필요

  • 자신의 모든 자손 컴포넌트가 제데로 UI를 반환할 때 까지 표시할 내용을 지정하기 위해 fallback 프로퍼티 사용

  • 즉, 자식 컴포넌트 중 어느 하나라도 적재중인 경우 폴백 UI를 표시

lazy와 Suspense가 어떻게 함께 작동하는지 이해하기

  • 리액트가 지연 컴포넌트를 첫 렌더링하려고 할 때, 컴포넌트는 초기화되지 않았지만 모듈을 적재하기 위해 리액트가 호출할 수 있는 함수(프로미스를 반환하는 함수)가 존재한다.

  • 프로미스는 컴포넌트를 default 프로퍼티로 제공하는 모듈로 해소되어야만 한다.

  • 해소된 후 지연 컴포넌트의 상태를 resolved로 설정하고 렌더링할 준비가 된 컴포넌트를 반환한다.

  • else 절에는 상위 컴포넌트의 Suspense 컴포넌트와 통신하는 핵심 코드가 포함되어있음

    • 즉, 프로미스가 해소되지 않으면 리액트가 프로미스를 마치 예외처럼 throw한다.

    • 서스펜스는 던져진 프로미스를 catch하면서 폴백 UI를 렌더링하게 되어있다.

    • 단, 네트워크 오류등으로 프로미스가 거부되었을 때는 서스펜스가 처리하는게 아닌 에러바운더리가 처리

Error boundary

리액트는 자식 컴포넌트에서 발생하는 오류를 잡아내는 컴포넌트를 따로 제공하지 않음

But 클래스 컴포넌트가 오류를 잡아서 보고하고 싶을 때 구현할 수 있는 몇 가지 생명주기 메서드를 제공

  • 클래스 컴포넌트로 이런 메서드를 하나 이상 구현하면, 그 컴포넌트는 오류 경계를 설정한 것으로 간주됨

    • 오류 경계를 설정하면 오류 발생 시 앱을 언마운트하는 대신 폴백 UI를 표시

Last updated