리액트 레퍼런스 - Suspense

기운찬곰·2023년 9월 27일
post-thumbnail

원문 참고 : https://react.dev/reference/react/Suspense

<Suspense> Reference

<Suspense>을 사용하면 children 로딩이 완료될 때까지 fallback을 표시할 수 있습니다.

<Suspense fallback={<Loading />}>
  <SomeComponent />
</Suspense>

Props

  • children : 렌더링하려는 실제 UI입니다. 렌더링 중에 children이 suspends(일시 중지)되면, Suspense boundary가 fallback으로 렌더링을 전환합니다.
  • fallback : 로딩이 완료되지 않은 경우 실제 UI 대신 렌더링할 대체 UI입니다. 유효한 React 노드는 허용되지만 실제로는 로딩 스피너 또는 스켈레톤(skeleton)과 같은 가벼운 placeholder 뷰 입니다. Suspense는 children이 정지하면 자동으로 fallback으로 전환되고, 데이터가 준비되면 다시 children으로 전환합니다. 렌더링하는 동안 fallback이 중지되면 가장 가까운 부모 Suspense boundary를 활성화합니다.

Caveats

  • React은 처음 마운트하기 전에 일시 중단된 렌더링의 상태를 보존하지 않습니다. 컴포넌트가 로드되면 React는 중단된 트리를 처음부터 다시 렌더링합니다.
  • Suspense가 트리에 대한 콘텐츠를 표시하고 있었지만 다시 일시 중단된 경우에는, startTransition이나 derferedValue 사용으로 인해 발생한 업데이트가 아니라면 fallback이 다시 표시됩니다.
  • 다시 일시 중단되었기 때문에 React가 이미 표시된 내용을 숨겨야 하는 경우, 컨텐츠 트리의 layout Effects가 clean up 됩니다. 컨텐츠가 다시 표시될 준비가 되면 React는 layout Effects를 다시 시작합니다. 이렇게 하면 DOM 레이아웃을 측정하는 Effects가 내용이 숨겨진 상태에서 이 작업을 수행하지 않습니다.
  • 리액트에는 Suspense와 통합된 Streaming Server Rendering 및 Selective Hydration과 같은 내부적인 최적화 기능이 포함됩니다. 아키텍처 개요를 읽고 기술 강의를 시청하여 자세한 내용을 알아보십시오.

Usage

Displaying a fallback while content is loading

애플리케이션의 모든 부분을 Suspense 경계로 래핑할 수 있습니다:

<Suspense fallback={<Loading />}>
  <Albums />
</Suspense>

React는 children에게 필요한 모든 코드와 데이터가 로드될 때까지 loading fallback을 표시합니다.

아래 예제에서는 앨범 목록을 가져오는 동안 Albums 컴포넌트가 일시 중단됩니다. 렌더링할 준비가 될 때까지 리액트는 위에서 가장 가까운 Suspense 경계를 전환하여 폴백(Loading) 컴포넌트를 표시합니다. 그런 다음 데이터가 로드되면 React는 Loading fallback을 숨기고 Albums 컴포넌트를 데이터와 함께 렌더링합니다.

import { Suspense } from 'react';
import Albums from './Albums.js';

export default function ArtistPage({ artist }) {
  return (
    <>
      <h1>{artist.name}</h1>
      <Suspense fallback={<Loading />}>
        <Albums artistId={artist.id} />
      </Suspense>
    </>
  );
}

function Loading() {
  return <h2>🌀 Loading...</h2>;
}

Suspense 지원 데이터 소스만 Suspense 컴포넌트를 활성화합니다. 여기에는 다음이 포함된다:

  • Relay 및 Next.js와 같은 Suspense 지원 프레임워크를 사용한 Data fetching
  • lazy를 사용한 Lazy-loading 컴포넌트 코드

Suspense는 Effect 또는 이벤트 핸들러 내부에서 데이터를 가져올 때를 감지하지 못합니다.

위의 Albums 컴포넌트에 데이터를 로드하는 정확한 방법은 프레임워크에 따라 다릅니다. Suspense 지원 프레임워크를 사용하면 해당 데이터 가져오기 문서에서 자세한 내용을 확인할 수 있습니다.

의견이 제시된 프레임워크 사용 없이는 Suspense 지원 데이터 가져오기는 아직 지원되지 않습니다. Suspense 지원 데이터 소스를 구현하기 위한 요구 사항은 불안정하고 문서화되지 않았습니다. Suspense와 데이터 소스를 통합하기 위한 공식 API는 리액트의 향후 버전에서 공개될 예정입니다.

Revealing content together at once

기본적으로 Suspense 안의 트리 전체는 하나의 단위로 취급됩니다. 예를 들어, 이러한 컴포넌트 중 하나만 일부 데이터 대기를 중지하더라도, 해당 컴포넌트 모두가 로드 표시기로 대체됩니다:

<Suspense fallback={<Loading />}>
  <Biography />
  <Panel>
    <Albums />
  </Panel>
</Suspense>

그런 다음, 모두 보여줄 준비가 완료되면, 한 번에 모두 함께 표시 됩니다.

아래 예제에서는 Biography 및 Albums 모두 일부 데이터를 가져옵니다. 그러나 Suspense 경계 아래에 그룹화되어 있기 때문에 이러한 컴포넌트는 항상 동시에 함께 "pop in"됩니다.

import { Suspense } from 'react';
import Albums from './Albums.js';
import Biography from './Biography.js';
import Panel from './Panel.js';

export default function ArtistPage({ artist }) {
  return (
    <>
      <h1>{artist.name}</h1>
      <Suspense fallback={<Loading />}>
        <Biography artistId={artist.id} />
        <Panel>
          <Albums artistId={artist.id} />
        </Panel>
      </Suspense>
    </>
  );
}

function Loading() {
  return <h2>🌀 Loading...</h2>;
}

데이터를 로드하는 컴포넌트가 Suspense 경계의 직접 자식일 필요는 없습니다. 예를 들어 Biography 및 Albums을 새 Details 컴포넌트로 이동할 수 있습니다. 이것은 행동을 바꾸지 않습니다. Biography와 Albums은 부모의 Suspense 경계를 같이 하기 때문에 그들의 표시는 함께 조정 됩니다.

<Suspense fallback={<Loading />}>
  <Details artistId={artist.id} />
</Suspense>

function Details({ artistId }) {
  return (
    <>
      <Biography artistId={artistId} />
      <Panel>
        <Albums artistId={artistId} />
      </Panel>
    </>
  );
}

Revealing nested content as it loads

컴포넌트가 중단되면 가장 가까운 부모 Suspense 컴포넌트가 fallback을 표시합니다. 이것을 이용하면 여러 Suspense 컴포넌트를 중첩하여 로딩 시퀀스를 생성할 수도 있습니다. 각 Suspense 경계의 fallback은 다음 레벨의 콘텐츠를 사용할 수 있게 되면 채워집니다. 예를 들어 앨범 목록에 고유한 fallback을 지정할 수 있습니다:

<Suspense fallback={<BigSpinner />}>
  <Biography />
  <Suspense fallback={<AlbumsGlimmer />}>
    <Panel>
      <Albums />
    </Panel>
  </Suspense>
</Suspense>

이렇게 변경하면 Biography를 표시하는 것은 Albums이 로드 되는 것을 "wait"할 필요가 없습니다.

순서는 다음과 같습니다:

  1. Biography가 아직 로드되지 않은 경우, 전체 컨텐츠 영역 대신 BigSpinner가 표시됩니다.
  2. Biography를 로드하면 BigSpinner가 컨텐츠로 대체됩니다.
  3. Albums가 아직 로드되지 않은 경우, Albums 및 해당 상위 Panel 대신 AlbumsGlimmer가 표시됩니다.
  4. 마지막으로 Albums loading이 완료되면 AlbumsGlimmer가 대체됩니다.
import { Suspense } from 'react';
import Albums from './Albums.js';
import Biography from './Biography.js';
import Panel from './Panel.js';

export default function ArtistPage({ artist }) {
  return (
    <>
      <h1>{artist.name}</h1>
      <Suspense fallback={<BigSpinner />}>
        <Biography artistId={artist.id} />
        <Suspense fallback={<AlbumsGlimmer />}>
          <Panel>
            <Albums artistId={artist.id} />
          </Panel>
        </Suspense>
      </Suspense>
    </>
  );
}

function BigSpinner() {
  return <h2>🌀 Loading...</h2>;
}

function AlbumsGlimmer() {
  return (
    <div className="glimmer-panel">
      <div className="glimmer-line" />
      <div className="glimmer-line" />
      <div className="glimmer-line" />
    </div>
  );
}

Suspense 경계를 사용하면 UI의 어떤 부분이 항상 동시에 함께 "pop in"되어야 하는지, 일련의 로딩 상태에서 어떤 부분이 점진적으로 더 많은 콘텐츠를 표시해야 하는지 조정할 수 있습니다. 당신은 당신의 앱 동작의 나머지에 영향을 주지 않고 트리의 어느 위치에서든 Suspense 경계를 추가, 이동, 또는 삭제할 수 있다.

모든 컴포넌트 주위에 Suspense 경계를 두지 마십시오. Suspense 경계는 사용자가 경험하기를 원하는 로딩 순서보다 세분화되어서는 안 됩니다. designer와 함께 작업하는 경우 loading 상태를 어디에 두어야 하는지 물어봅니다. 이미 설계 와이어프레임에 loading 상태를 포함시켰을 가능성이 높습니다.


마치면서

최신 리액트에서 가장 중요한 개념 중 한가지는 바로 Suspense라고 말할 수 있습니다. 내부적으로는 스트리밍 지원~부분 Suspense까지 연관이 되어있습니다. 리액트 개발자라면 이 정도는 알고 있어야겠죠?

profile
부계정

0개의 댓글