스트리밍이란?
스트리밍은 서버에서 클라이언트로 대용량 데이터를 전송할 때, 데이터를 작은 조각으로 나누어 순차적으로 전송하는 기술이다.
데이터 크기가 크거나 서버에서 데이터 준비에 시간이 많이 소요될 때 유용하다.
작동 원리
- 서버에서 데이터를 여러 조각으로 분할
- 준비된 데이터 조각을 순차적으로 클라이언트에 전송
- 클라이언트는 전체 데이터를 기다리지 않고 받은 조각부터 처리
장점
- 사용자 경험 향상: 긴 로딩 시간 없이 콘텐츠를 점진적으로 표시
- 리소스 효율성: 서버와 클라이언트의 메모리 사용 최적화
- 반응성 개선: 부분적인 데이터로도 사용자 상호작용 가능
Next.js의 HTML 스트리밍
Next.js는 자체적으로 HTML 페이지를 스트리밍하는 기능을 제공한다.
특징
- 컴포넌트 단위의 스트리밍: 개별 컴포넌트를 독립적으로 스트리밍
- 우선순위 렌더링: 간단한 컴포넌트를 먼저 표시하고, 복잡한 컴포넌트는 후순위로 처리
작동 방식
- 빠르게 렌더링되는 간단한 컴포넌트를 먼저 화면에 표시
- 데이터 페칭이 필요한 복잡한 컴포넌트는 대체 UI(예: 로딩 상태)를 먼저 표시
- 서버에서 복잡한 컴포넌트의 렌더링이 완료되면, 해당 내용을 클라이언트에 전송하여 업데이트
활용 사례
- 동적 페이지(Dynamic Pages): 데이터 의존성이 높은 페이지에서 자주 활용
- 대시보드: 여러 독립적인 데이터 섹션을 가진 페이지
- 콘텐츠 중심 페이지: 텍스트 콘텐츠는 빠르게 로드하고, 이미지나 상호작용 요소는 후순위로 로드
페이지 스트리밍 적용
loading.tsx
페이지 디렉토리에 loading.tsx 파일을 생성하여 로딩 상태를 쉽게 구현할 수 있다.
export default function Loading() {
return <div>로딩중...</div>;
};
loading.tsx파일을 생성하면 Next.js가 자동으로 이를 인식- 페이지 로딩 중에는
loading.tsx의 내용이 표시됨 - 페이지 컨텐츠가 준비되면 자동으로 로딩 상태가 실제 컨텐츠로 대체됨
주의사항
1. 적용 범위
loading.tsx파일은 해당 파일이 위치한 디렉토리뿐만 아니라 그 하위 경로의 모든 페이지 컴포넌트에 영향을 미친다.
즉, 레이아웃 파일과 유사하게 해당 경로 아래의 모든 비동기 페이지 컴포넌트에 스트리밍이 적용된다.
2. 비동기 컴포넌트 제한
loading.tsx가 스트리밍을 적용하는 대상은 async가 붙은 비동기 페이지 컴포넌트에 한정된다.
즉, 동기적으로 동작하는 페이지 컴포넌트가 있는 위치에는 loading.tsx를 생성해도 스트리밍이 적용되지 않는다.
3. 페이지 컴포넌트 전용
loading.tsx는 오직 페이지 컴포넌트에만 스트리밍을 적용할 수 있다. 일반 컴포넌트나 레이아웃 컴포넌트에는 직접적으로 적용되지 않는다.
4. 쿼리 스트링 변경 미반응
loading.tsx파일로 설정된 스트리밍은 브라우저에서 쿼리 스트링이 변경될 때 트리거되지 않는다.
즉, 같은 페이지 내에서 쿼리 파라미터만 변경되는 경우, 로딩 상태가 다시 표시되지 않는다.
컴포넌트 스트리밍 적용
Suspense
Suspense로 감싼 컴포넌트는 Next.js 서버에서 사전 렌더링 진행시, 해당 컴포넌트의 비동기 작업이 종료될때까지 미완성 상태로 대체 UI를 보여준다.
import { Suspense } from "react";
export default function Component() {
return (
<div>
<Suspense fallback={<div>로딩중...</div>}>
<AsyncComponent />
</Suspense>
</div>
);
};
- 대체 UI는
fallbackprop에 넘겨주면 된다.
key prop을 이용한 로딩 상태 재설정
Suspense컴포넌트에 key prop을 전달하여 키 값이 변화할 때마다 다시 로딩 상태로 돌아가도록 설정할 수 있다.
<Suspense key={someValue} fallback={<div>로딩중...</div>}>
<AsyncComponent />
</Suspense>
기본적으로 리액트의 Suspense컴포넌트는 최초 로딩 완료 후 내부 컨텐츠가 변경되어도 다시 로딩 상태로 돌아가지 않는다. key prop을 변경하면 리액트는 이를 새로운 컴포넌트로 인식하여 로딩 상태를 다시 표시한다.
이 방식은 리액트의 key 처리 매커니즘을 활용한 일종의 트릭이다.
다중 비동기 컴포넌트 스트리밍
Suspense 컴포넌트를 사용하면 하나의 페이지 내에서 여러 비동기 컴포넌트를 동시에 스트리밍하고, 완료되는 순서대로 각각 렌더링할 수 있다.
async function RecoBooks() {
// 추천 도서목록 요청을 3초 지연시키는 로직
}
async function AllBooks() {
// 모든 도서목록 요청을 1.5초 지연시키는 로직
}
export default function Home() {
return (
<>
<Suspense fallback={<div>도서를 불러오는 중입니다...</div>}>
<RecoBooks /> // 3초가 되어서야 렌더링 됨
</Suspense>
<Suspense fallback={<div>도서를 불러오는 중입니다...</div>}>
<AllBooks /> // 1.5초 뒤 먼저 화면에 렌더링 됨
</Suspense>
</Suspense>
</>
);
};
위와 같은 장점으로, loading파일을 이용하는 방식에 비해 더 많은 곳에 범용적으로 사용할 수 있기 때문에 많은 사람들이 더 선호하고 있다.
'Frontend > Next.js' 카테고리의 다른 글
| 서버 액션 (Server Action) (0) | 2025.11.13 |
|---|---|
| Next.js 앱 라우터의 에러 핸들링 (0) | 2025.11.13 |
| 라우트 세그먼트 옵션과 클라이언트 라우터 캐시 (0) | 2025.11.13 |
| 풀 라우트 캐시 (Full Route Cache) (0) | 2025.11.13 |
| 데이터 캐시와 리퀘스트 메모이제이션 (0) | 2025.11.13 |
