jtwjs Dev Wiki
  • DEV_ROAD
    • 💪🏻 생존하기
    • Week 1
      • 개발 환경 세팅
      • 타입스크립트
      • 리엑트
      • Testing Library
      • Parcel & ESLint
    • Week 2
      • JSX
      • Virtual DOM
    • Week 3
      • React Component
      • React State
    • Week 4
      • Express
      • Fetch API & CORS
      • React Hook
      • useRef & Custom Hook
    • Week 5
      • TDD
      • React Testing Library
      • MSW
      • Playwrite
      • Snapshot
    • Week 6
      • Separtion of Concerns
      • Principle
      • DI, (Dependency Injection)
      • Reflect-metadata
      • TSyringe
      • External Store
      • Follow Redux
      • usestore-ts
      • useSyncExternalStore
    • Week 7
      • Routing
      • Routes
      • Router
      • Navigation
    • Week 8
      • Design System
      • Style Basics
      • CSS-in-JS
      • Styled-Components
      • Global Style & Theme
    • Week 9
      • 개발하기 전 준비
      • 상품 목록 페이지
      • 상품 상세 페이지
      • 장바구니 페이지
    • Week 10
      • 로그인
      • 로그아웃
      • 회원가입
      • 주문 목록 & 주문 상세
    • Week 11
      • 배송 정보 입력
      • 포트원 결제 요청
      • 배송 및 결제 정보 전달
    • Week 12
      • 관리자 웹사이트개발시작
  • DEV_NOTE
    • TypeScript
      • 기본적 문법
        • Enum
        • 다형성
          • Untitled
        • 구조적 타이핑
        • 제너릭 타입
        • 컨디셔널 타입
        • 함수 메서드 타이핑
        • infer로 타입스크립트의 추론 직접 활용
        • 재귀 타입
        • 템플릿 리터럴 타입
        • 추가적인 타입 검사 satisfies 연산자
        • 타입스크립트 건망증
        • 원시 자료형에도 브랜딩 기법 사용 가능
        • 타입 좁히기
        • 유용한 타입 만들기
        • 데코레이터 함수
        • 앰비언트 선언도 선언 병합이 된다.
        • 앰비언트 선언도 선언병합이 된다.
    • Testing
      • Unit Testing
      • 단위 테스트의 두 분파
      • 좋은 단위 테스트를 구성하는 4대 요소
      • 테스트 대역과 식별할 수 있는 동작
      • 단위 테스트 스타일
      • 가치 있는 단위 테스트를 위한 리팩토링
      • 통합 테스트
      • Cross Browsing Testing
      • 기능 테스트 종류
      • React Testing Pattern
      • 프론트엔드 테스트 입문
        • 테스트 범위
        • 단위 테스트 검증
        • Mock
        • UI 컴포넌트 테스트
        • 테스트 커버리지
        • 웹 통합 테스트
        • MSW
        • 스토리북
        • 시각적 회귀 테스트
        • E2E 테스트
        • Github Actions 설정
        • 깃허브 액션에서 E2E
      • 시프트 레프트
        • 테스트 기본중의 기본
        • 단위 테스트
        • 코드 복잡도
        • 리팩터링
        • 코드 리뷰
        • 통합 테스트 패턴
        • 시스템 테스트의 자동화
        • 탐색적 테스트
      • Test Tip
      • vitest
      • playwright
      • Test Data Generator
      • MSW
    • Algorithm
      • coding test
      • Data Structure
    • Next.js
      • Data Fetching
      • Hydration
      • Next 13
      • Optimization
      • Next 15
    • Tailwind
      • Tailwind CSS
      • Theme
      • Directives
      • Tool
      • Design System
    • Storybook
      • Storybook
      • CSF3
      • CDD
      • Headless Component
    • Funtional Programming
      • 함수형 프로그래밍
      • 참조 투명성
      • 부수효과
      • 함수 합성
      • 제너릭 타입 활용하기
      • 암묵적 입출력
      • 액션과 계산, 데이터
      • 계층형 설계
      • 호출 그래프
      • 함수형 설계
      • 불변성
      • 일급 함수
      • 함수형 도구
    • Git
      • Github Actions
      • Conflict
      • Branch 전략
    • Contents Format
      • Audio
    • 3D Graphic
      • 3D keyword
      • Three.js
      • Geometry
      • Material
      • Light
      • Camera
      • Decal
      • Rotation
      • Text
      • Shadow
      • Fog
      • Post Processing
      • Animation
      • Math
        • Vector Space
        • 벡터의 연산
        • 회전 계산
      • 3D 컨텐츠가 만들어지는 과정
      • R3F
      • Env
      • Scene
      • Transform
      • R3F
      • Interaction & Raycast
      • Rendering Algorithnm
      • Blender
      • Blender
    • Accessibility
      • 접근성이란
    • Interactive Web
      • Parallax
      • Canvas
      • requestAnimationFrame
      • Effect
      • HSL
      • React.js + Canvas
      • Matter.js
    • AWS
      • DevOps
      • Amplify
      • S3
      • 클라우드 컴퓨팅
        • 온프레미스와 클라우드
        • 클라우드 도입효과
        • 클라우드 컴퓨팅의 범위
        • 컴퓨팅 옵션
          • EC2 - Virtual Machin
          • ECS, EKS - Container
          • Lambda - Serverless
        • 네트워크 가상화
        • 스토리지
        • 데이터베이스
        • 데이터 수집
        • 머신 러닝 영역
        • IoT 영역
        • 블록체인 영역
      • 클라우드 아키텍처 설계
    • Network
      • Web Server & WAS
    • System Design
      • System Design
      • Component
      • 의존성을 배제한 개발
      • Error Handling
      • Architecture
        • 모노로틱 아키텍처
        • Clean Architecture
        • Layered Architecture
        • 이벤트 기반 아키텍처
      • 상황을 파악하는 메타인지
      • 중복 문제 해결하기
      • Monorepo Arhitecture
        • 모노레포 운영과 트러블슈팅
        • Module Federation
      • 코드 병목지점
      • API 대응
      • 공통 코드
      • Infra 구축
      • 모듈 기반의 개발 방식
      • Design System
        • 최소 수준의 아키텍처 설정
        • 더 효율적인 디자인시스템 만들기
        • 디자인 시스템과 UI 라이브러리 목적
        • 디자인 토큰
      • 효율적인 업무
        • 업무 프로세스 병목 파악
      • Clean Code
      • Design Pattern
        • CQRS Pattern
        • Strangler Fig Pattern
        • 데코레이터 패턴
        • 커맨드 패턴
        • 전략 패턴
        • 옵저버 패턴
      • A/B 테스팅
      • 대규모 리엑트 웹앱 개발
        • 복잡성 관리
        • 모듈성
        • 성능
        • 디자인 시스템
        • 데이터 패칭
        • 상태 관리
        • 국제화
        • 코드 조직화하기
        • 개인화 A/B 테스팅
        • 확장 가능한 웹 아키텍처
        • 테스팅
        • 툴링
        • 기술적 마이그레이션
        • 타입스크립트
        • 라우팅
        • 사용자 중심 API 디자인
        • 리액트 미래
    • Performance
      • React DevTools
      • Component 최적화
      • Page Load
      • API
    • MFA
      • MSA
      • MFA 도입하기
      • Monorepo
        • Monorepo Tool
        • Yarn Berry Workspace
        • Turborepo
      • MFA Composition
      • SPA 통합
      • Design System
      • Package Manager
        • Yarn
        • pnpm
      • Transpiler & Bundler
        • Babel
        • Rollup
        • esbuild
        • swc
        • Webpack
        • Vite
      • 분해와 통합을 위한 여러 기술 비교
    • State Management
      • Zustand
    • React v18
      • Automatic batching
      • Suspense
      • Transition
    • SEO
      • Search Engine Optimization
      • Open Graph Element
      • Metadata
    • FE Develop
      • Scrubbing
      • Clipboard
    • Refactoring
      • 리팩토링 깊게 들여다보기
      • 긴 코드 조각내기
      • 타입 코드 처리하기
      • 유사한 코드 융합하기
      • 데이터 보호
      • 코드 추가 및 제거
    • OAuth 2.0
    • Analytics
      • Mixpanel
    • ETC
      • VSCode
    • React Hook In Action
      • useContext & Provider
      • 커스텀 훅
      • 코드 분할하기 with Suspense, lazy
      • Suspense와 이미지 적재하기
      • useTransition, uesDeferredValue
      • SuspenseList
Powered by GitBook
On this page
  • 코드 분할하기
  • 초기 사용자 상호작용에 참여하지 않는 컴포넌트 최적화
  • import 함수로 코드 동적 임포트 with Vanila JS
  • lazy와 Suspense를 사용해 동적으로 컴포넌트 임포트
  • lazy 함수
  • Suspense
  • lazy와 Suspense가 어떻게 함께 작동하는지 이해하기
  • Error boundary
  1. DEV_NOTE
  2. React Hook In Action

코드 분할하기 with Suspense, lazy

코드 분할하기

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// js (no react)
function handleClick() {
  import('./module') // 임포트 함수 호출
    .then((module) => { // 지역 변수에 모듈을 할당
      module.default('messagePara','hello world'); // 모듈 프로퍼티로 익스포트된 함수 호출
      moudle.sayHi('hiPara');
    })
}
  • 임포트 함수는 익스포트한 모듈로 해소되는 프로미스를 반환한다.

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

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

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

async function handleClick() {
  const module = await import(경로);
  // module 사용
}
  • 구조 분해 사용 가능

function handleClick() {
  import('./module')
    .then(({default: showmessage, sayHi}) => {
      showMessage();
      sayHi()
    })
}

async function handleClick() {
  const {default: showMessage, sayHi} = await import('./module');
}

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

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

lazy 함수

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

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

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

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

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

    • 경로에 따라 앱 분할하기

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

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

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

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

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

const LazyComponent = lazy(() => import('./Component.tsx'));
// 아래와 같다.
// 리엑트는 처음으로 컴포넌트를 렌더링할 때 아래와 같은 promise 함수를 호출한다.
const getPromise = () => import(modulePath); // 프로미스를 반환하는 함수를 만듬
const LazyComponent = lazy(getPromise); // React.lazy에게 프로미스를 만드는 함수를 전달
  • mock Component

const module = {
  default: () => <div>Mock Component</div>
}
function getPromise() {
  return new Promise(
    (resolve) => setTimeout(() => resolve(module), 3000)
  )
}

const LazyComponent = lazy(getPromise)

const ComponentWrapper = () => {
  const [isOn, setIsOn] = useState(false);
  return isOn 
    ? (<LazyComponent />) 
    : (
      <div>
        <button onClick={() => {setIsOn(true)}}>Show Component</button>
      </div>
      )
}

Suspense

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

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

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

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

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

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

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

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

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

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

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

if (status === 'resolved') {
  return component;
} else {
  throw promise;
}

Error boundary

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

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

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

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

class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }
  
  static getDerivedStateFromError(error) { // 오류를 잡아낸 경우 새 상태를 반환
    // 다음 렌더링 시 폴백 UI를 보여주도록 상태를 갱신
    return { hasError: true };
  }
  
  componentDidCatch(error, errorInfo) { // 오류를 잡아낸 경우 로그를 남김
    // 오류 로그를 오류 보고 서비스에 전달
    logErrorToMyService(error, errorInfo);
  }
  
  render() {
    const {
      children,
      fallback = <h1>Something went wrong.</h1>
    } = this.props;
    
    return this.state.hasError ? fallback : children;
  }
}
Previous커스텀 훅NextSuspense와 이미지 적재하기

Last updated 4 months ago