스트리밍이란 서버에서 HTML 페이지를 생성하는 동안 클라이언트로 전송할 데이터의 크기가 너무 크거나 준비 시간이 오래 걸리는 경우, 데이터를 작은 조각으로 나누어 순차적으로 전송하는 기술이다.
마치 강물에 하나씩 흘려보내듯이, 클라이언트는 준비된 부분부터 받아 처리할 수 있어 더 빠른 응답이 가능하다.

빠른 페이지 로딩
페이지 콘텐츠가 더 빨리 클라이언트로 전달되기 때문에, 사용자에게 더 빠른 반응 속도를 제공합니다. 이는 특히 네트워크가 불안정하거나 서버가 부담이 클 때 유리하다.
서버 리소스 절약
스트리밍을 사용하면 서버는 전체 HTML을 한 번에 렌더링하고 전달하는 대신, 각 부분을 스트리밍하면서 렌더링하기 때문에 서버의 부하를 분산할 수 있다.
향상된 사용자 경험
사용자가 페이지의 일부 콘텐츠를 먼저 보고, 나머지 콘텐츠는 백그라운드에서 로딩되는 방식으로, 더 직관적이고 매끄러운 사용자 경험을 제공한다.
Next.js의 App Router에서는 특정 페이지에 loading.tsx를 추가하는 것만으로 자동으로 스트리밍을 활성화할 수 있다.
// search/loading.tsx
export default function Loading() {
return <div>Loading...</div>;
}
loading.tsx는 해당 페이지뿐만 아니라 경로 하위의 모든 페이지에도 적용된다. (레이아웃 파일과 유사한 동작)async) 페이지 컴포넌트에서만 스트리밍이 작동하며, 동기 페이지에는 적용되지 않는다.loading.tsx는 페이지(page.tsx)에만 적용되며, 일반 컴포넌트에는 사용할 수 없다.loading.tsx가 트리거되지 않는다.Suspense를 사용하면 page.tsx뿐만 아니라 특정 컴포넌트의 데이터가 로드될 때까지 일부 UI를 먼저 표시하고, 나머지는 준비되는 대로 점진적으로 렌더링할 수 있다.
import { Suspense } from "react";
import SlowComponent from "./slow-component";
type Props = {
searchParams: Promise<{ q?: string }>;
};
export default async function Page({ searchParams }: Props) {
return (
<Suspense
fallback={<div>Loading...</div>}
key={(await searchParams).q || ''}
>
<SlowComponent q={(await searchParams).q || ''} />
</Suspense>
);
}
이 때 Suspense의 key props에 변화를 감지할 값을 전달하면 해당 값이 변경될 때마다 컴포넌트를 다시 로드하고, 새로운 데이터가 준비될 때까지 기존 UI를 유지한다.
loading.tsx: 페이지 전체가 준비될 때까지 보여주는 기본 UI<Suspense>: 특정 데이터가 로드될 때까지 로딩 UI(fallback)를 적용loading.tsx로 감싸고, 개별 컴포넌트는 스트리밍으로 점진적 렌더링이 가능