Suspense는 아직 준비되지 않은 하위 트리의 렌더를 잠시 보류(suspend)하고, 그동안 가장 가까운 경계의 fallback을 보여 주는 React의 비동기 렌더링 메커니즘이다. 로딩 상태를 컴포넌트마다 들고 있지 않고 경계에 위임한다.
<ErrorBoundary fallback={<ErrorPage />}>
<Suspense fallback={<Spinner />}>
<UserProfile /> {/* 준비 전이면 Spinner, 실패하면 ErrorPage */}
</Suspense>
</ErrorBoundary>- 원리: 데이터가 없으면 컴포넌트가 렌더 중에 Promise를 던진다(
throw promise). React는 렌더를 멈추고 가장 가까운 경계의 fallback을 그린 뒤, Promise가 끝나면 다시 렌더한다. 직접 던지지 않고 use()나 useSuspenseQuery 같은 Suspense 지원 API(Application Programming Interface)를 통해 쓴다 - 경계는 중첩된다. 영역마다 경계를 두면 각자 독립적으로 준비되는 대로 나타난다. 경계를 어디에 둘지가 곧 로딩 UX(User Experience) 설계다
- 에러 경계(Error Boundary)와 역할을 나눈다. Suspense는 던져진 Promise(로딩), Error Boundary는 던져진 Error(실패)를 처리한다
- 이미 보이는 내용이 다시 suspend될 때 fallback으로 갈아엎지 않으려면 업데이트를 transition으로 감싼다
왜 중요해졌나
React 18 이전 SSR(Server-Side Rendering)은 "모든 데이터 → 모든 HTML(HyperText Markup Language) → 모든 JS(JavaScript) → 전체 하이드레이션"이 앞 단계를 기다리는 폭포수였다. Suspense가 앱을 독립 단위로 나누면서 준비된 부분부터 HTML을 보내는 스트리밍 SSR, 경계별로 먼저 살아나는 선택적 하이드레이션, 서버 컴포넌트, 부분 사전 렌더링(PPR)이 가능해졌다. Next.js의 loading.tsx는 페이지를 Suspense로 감싸는 단축 문법이다. 그래서 Suspense는 로딩 스피너 기능이라기보다 비동기 UI의 순서를 조율하는 장치다.
출처: New Suspense SSR Architecture in React 18 · React - Suspense