- loading.js 특수 파일은 React Suspense를 사용하여 의미 있는 로딩 UI를 만드는 데 도움이 됩니다. 이 규칙을 사용하면 경로 세그먼트의 콘텐츠가 로드되는 동안 서버에서 즉시 로드 상태(스피너 또는 스켈레톤 ui)를 표시할 수 있습니다. 렌더링이 완료되면 새 콘텐츠가 자동으로 교체됩니다.
즉시 로딩 상태 (Instant Loading States)
- 즉시 로딩 상태는 탐색 시 즉시 표시되는 대체 UI입니다. (스피너 또는 스켈레톤 ui)
- 사용자는 앱이 응답하고 있음을 이해하고 더 나은 사용자 경험을 제공할 수 있습니다.
- 폴더 안에 loading.js 파일을 추가하여 로드 상태를 만듭니다.
export default function Loading() {
return <LoadingSkeleton />
}
- 같은 폴더안에 있는 page.js와 children들을 Suspense로 자동적으로 래핑합니다.
- 알아두면 좋은 점
- 서버 중심 라우팅을 사용하더라도 탐색은 즉각적입니다.
- 탐색은 중단 가능합니다. 즉, 경로를 변경할 때 다른 경로로 이동하기 전에 경로의 콘텐츠가 완전히 로드될 때까지 기다릴 필요가 없습니다.
- 새 경로 세그먼트가 로드되는 동안 공유 레이아웃은 대화형으로 유지됩니다.
Suspense를 이용한 Streaming
- loading.js 외에도 자체 UI 컴포넌트에 대한 Suspense Boundaries를 수동으로 생성할 수도 있습니다.
- 앱 라우터는 Node.js 및 Edge 런타임 모두에 대해 Suspense를 사용한 스트리밍을 지원합니다.
Streaming이란?
- React 및 Next.js에서 스트리밍이 작동하는 방식을 배우려면 SSR과 그 제한 사항을 이해하는 것이 도움이 됩니다.
- SSR을 사용하면 사용자가 페이지를 보고 상호 작용하기 전에 완료해야 하는 일련의 단계가 있습니다.
- 먼저, 특정 페이지의 모든 데이터를 서버에서 가져옵니다.
- 그런 다음 서버는 페이지의 HTML을 렌더링합니다.
- 페이지의 HTML, CSS 및 JavaScript가 클라이언트로 전송됩니다.
- 비대화형 사용자 인터페이스는 생성된 HTML 및 CSS를 사용하여 표시됩니다.
- 마지막으로 React는 사용자 인터페이스를 대화형으로 만들기 위해 하이드레이션을 진행합니다.
- 이러한 단계는 순차적이며 차단됩니다. 즉, 모든 데이터를 가져온 후에만 서버가 페이지의 HTML을 렌더링할 수 있습니다.
- 그리고 클라이언트에서 React는 페이지의 모든 컴포넌트에 대한 코드가 다운로드된 후에만 UI를 하이드레이션할 수 있습니다.
- React 및 Next.js를 사용한 SSR은 사용자에게 비대화형 페이지를 가능한 한 빨리 표시하여 인지된 로딩 성능을 향상시키는 데 도움이 됩니다.
- 그러나 페이지가 사용자에게 표시되기 전에 서버에서 모든 데이터 가져오기가 완료되어야 하므로 여전히 속도가 느릴 수 있습니다.
- 스트리밍을 사용하면 페이지의 HTML을 더 작은 청크로 나누고 점진적으로 해당 청크를 서버에서 클라이언트로 보낼 수 있습니다. (먼저 온 데이터는 먼저 보낸다)
- 이를 통해 UI가 렌더링되기 전에 모든 데이터가 로드될 때까지 기다리지 않고 페이지의 일부를 더 빨리 표시할 수 있습니다.
- 스트리밍은 각 컴포넌트가 하나의 덩어리로 간주될 수 있기 때문에 React의 컴포넌트 모델과 잘 작동합니다.
- 우선 순위가 더 높거나(예: 제품 정보) 데이터에 의존하지 않는 구성 요소(예: 레이아웃)가 먼저 전송될 수 있으며 React는 더 일찍 수화를 시작할 수 있습니다.
- 우선 순위가 낮은 구성 요소(예: 리뷰, 관련 제품)는 해당 데이터를 가져온 후 동일한 서버 요청으로 보낼 수 있습니다.
- 스트리밍은 TTFB(Time To First Byte)를 줄일 수 있으므로 긴 데이터 요청으로 인해 페이지 렌더링이 차단되는 것을 방지하려는 경우 특히 유용합니다.
- 첫 번째 콘텐츠가 포함된 페인트(FCP).과 TTI(Time to Interactive)를 개선하는 데 도움이 됩니다.
Example
<Suspense>
로 비동기 작업(데이터 가져오기)을 수행하는 컴포넌트를 래핑하고 해당 작업이 진행되는 동안 대체 UI를 표시한 다음 작업이 완료되면 컴포넌트를 교체하는 방식으로 작동
import { Suspense } from 'react'
import { PostFeed, Weather } from './Components'
export default function Posts() {
return (
<section>
<Suspense fallback={<p>Loading feed...</p>}>
<PostFeed />
</Suspense>
<Suspense fallback={<p>Loading weather...</p>}>
<Weather />
</Suspense>
</section>
)
}
- Suspense를 사용하면 다음과 같은 이점을 얻을 수 있습니다.
- 스트리밍 서버 렌더링 - 서버에서 클라이언트로 HTML을 점진적으로 렌더링합니다.
- 선택적 수화 - React는 사용자 상호 작용을 기반으로 어떤 컴포넌트를 먼저 대화식으로 만들 것인지 우선 순위를 정합니다.
SEO
- Next.js는 UI를 클라이언트로 스트리밍하기 전에 generateMetadata 내부에서 데이터를 가져오기가 완료될 때까지 기다립니다. 이렇게 하면 스트리밍된 응답의 첫 번째 부분에
<head>
태그가 포함됩니다.
- 스트리밍은 서버에서 렌더링되므로 SEO에 영향을 주지 않습니다.
상태 코드
- 스트리밍할 때 요청이 성공했음을 알리기 위해 200 상태 코드가 반환됩니다.
- 예를 들어 redirect 또는 notFound를 사용할 때 서버는 스트리밍된 콘텐츠 자체 내에서 클라이언트에 오류나 문제를 계속 전달할 수 있습니다.
- 응답 헤더가 이미 클라이언트에 전송되었으므로 응답의 상태 코드를 업데이트할 수 없습니다. 이는 SEO에 영향을 미치지 않습니다.
Reference