
원문 참고 : https://react.dev/reference/react/Suspense
<Suspense> Reference<Suspense>을 사용하면 children 로딩이 완료될 때까지 fallback을 표시할 수 있습니다.
<Suspense fallback={<Loading />}>
<SomeComponent />
</Suspense>
애플리케이션의 모든 부분을 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 컴포넌트를 활성화합니다. 여기에는 다음이 포함된다:
Suspense는 Effect 또는 이벤트 핸들러 내부에서 데이터를 가져올 때를 감지하지 못합니다.
위의 Albums 컴포넌트에 데이터를 로드하는 정확한 방법은 프레임워크에 따라 다릅니다. Suspense 지원 프레임워크를 사용하면 해당 데이터 가져오기 문서에서 자세한 내용을 확인할 수 있습니다.
의견이 제시된 프레임워크 사용 없이는 Suspense 지원 데이터 가져오기는 아직 지원되지 않습니다. Suspense 지원 데이터 소스를 구현하기 위한 요구 사항은 불안정하고 문서화되지 않았습니다. Suspense와 데이터 소스를 통합하기 위한 공식 API는 리액트의 향후 버전에서 공개될 예정입니다.
기본적으로 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>
</>
);
}
컴포넌트가 중단되면 가장 가까운 부모 Suspense 컴포넌트가 fallback을 표시합니다. 이것을 이용하면 여러 Suspense 컴포넌트를 중첩하여 로딩 시퀀스를 생성할 수도 있습니다. 각 Suspense 경계의 fallback은 다음 레벨의 콘텐츠를 사용할 수 있게 되면 채워집니다. 예를 들어 앨범 목록에 고유한 fallback을 지정할 수 있습니다:
<Suspense fallback={<BigSpinner />}>
<Biography />
<Suspense fallback={<AlbumsGlimmer />}>
<Panel>
<Albums />
</Panel>
</Suspense>
</Suspense>
이렇게 변경하면 Biography를 표시하는 것은 Albums이 로드 되는 것을 "wait"할 필요가 없습니다.
순서는 다음과 같습니다:
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까지 연관이 되어있습니다. 리액트 개발자라면 이 정도는 알고 있어야겠죠?