codinghatso

Learn Next.js 제 9장 : Streaming 본문

WEB/Next.js

Learn Next.js 제 9장 : Streaming

hatso 2025. 3. 10. 19:16

-ai를 사용해 개념정리 했음을 공지합니다.-

 

스트리밍 (Streaming)

스트리밍이란 컴포넌트들을 각각의 덩어리(Chunks)로 묶어 분류하여 병렬처리하는 방식이다.

 

일반적으로 서스펜스와 데이터 가져오기 작업 시 좋은 관행으로 "데이터 가져오기를 필요한 구성 요소로 이동"을 말할 수 있다.

데이터를 필요한 구성 요소로 이동시키면 더 세분화된 서스펜스 경계를 만들 수 있습니다. 이를 통해 특정 구성 요소를 스트리밍 하고 UI가 차단되는 것을 방지할 수 있다.

 

Next.js 에서는 loading.tsx라는 특별한 파일을 생성할 수 있습니다. 이 예약된 파일은 페이지를 로딩하는 동안 사용자에게 보여줄 화면을 정의할 수 있습니다.

참고로 정적인 UI 이 과정에서는 SideNav 같은 요소는 즉시 표시됩니다.


📌 루트 스켈레톤 버그 수정 작업 (() 폴더로 옮기는 작업) 이해하기

Next.js에서 루트 스켈레톤 버그를 수정하는 과정은, 레이아웃 및 페이지가 로딩될 때 Suspense fallback이 정상적으로 작동하도록 하기 위한 작업이에요.

이 과정에서 **"특정 컴포넌트를 () 폴더로 옮기는 작업"**을 했을 텐데,
이것이 Next.js의 레이아웃 및 Suspense 동작 방식과 관련이 있어요.


✅ 문제: 루트에서 Suspense가 동작하지 않는 버그

Next.js에서는 페이지(page.tsx), 레이아웃(layout.tsx), 그리고 **Suspense를 적용한 fallback(스켈레톤 컴포넌트)**가 함께 있을 때,
루트 레이아웃에서 Suspense가 제대로 적용되지 않는 버그가 존재해요.

즉, 루트에서 Suspense를 사용할 경우, fallback이 적용되지 않고 전체 페이지가 차단(blocking)될 수 있음.


✅ 해결 방법: () 폴더로 파일을 옮기는 이유

Next.js에서는 ()로 감싼 폴더를 **"그룹 폴더 (Grouping Folder)"**라고 해요.
이것을 사용하면 라우팅에는 영향을 주지 않으면서, 특정 컴포넌트나 레이아웃을 분리할 수 있어요.

📌 해결 방법 요약

  1. () 폴더를 만들어서, 기존 layout.tsx를 루트에서 분리.
  2. layout.tsx 안에서 Suspense를 적용하면, fallback이 정상적으로 작동.

✅ 예제 코드: Before & After

🚨 버그가 있는 기존 구조

/app
  ├── layout.tsx    # 여기에 Suspense 적용 → 정상 작동 X (버그 발생)
  ├── page.tsx
  ├── ui/
  ├── ui/skeletons.tsx

이렇게 루트(layout.tsx)에서 Suspense를 사용하면, fallback이 정상적으로 동작하지 않을 수 있음.


버그 수정 후 (() 폴더 활용)

/app
  ├── (dashboard)/  # () 폴더를 사용하여 그룹화
  │   ├── layout.tsx  # layout을 별도로 분리하여 Suspense 적용
  │   ├── page.tsx
  │   ├── ui/
  │   ├── ui/skeletons.tsx
  ├── layout.tsx  # 루트에서 layout을 제거

이제 (dashboard)/layout.tsx에서 Suspense가 올바르게 작동하면서,
페이지 로딩 시 스켈레톤 UI가 정상적으로 표시될 수 있음.


✅ 결론

버그 원인: 루트(layout.tsx)에서 Suspense가 올바르게 동작하지 않는 문제
해결 방법: 레이아웃을 () 폴더로 이동하여 그룹화 → Suspense가 정상 작동
이점: 라우팅 경로에 영향을 주지 않으면서, Suspense를 활용할 수 있음

즉, **"()` 폴더로 옮기는 작업"**은 Next.js의 라우팅 구조를 변경하지 않고, Suspense를 올바르게 작동시키기 위한 Next.js의 패턴이에요. 🚀


📌 Suspense 태그와 fallback의 역할

Next.js에서 Suspense는 비동기 컴포넌트가 데이터를 가져오는 동안 "대체 UI"를 표시하는 기능을 제공합니다.


✅ Suspense 태그의 역할

<Suspense fallback={<RevenueChartSkeleton />}>
  <RevenueChart />
</Suspense>

이 코드는 RevenueChart 컴포넌트가 데이터를 불러오는 동안 RevenueChartSkeleton을 표시하는 역할을 합니다.

  • RevenueChart는 비동기 컴포넌트이므로 데이터 로딩 시간이 필요할 수 있음.
  • Suspense를 사용하면 로딩이 끝날 때까지 대체 UI(fallback)를 보여줌.
  • 로딩이 끝나면 RevenueChartSkeleton이 사라지고 RevenueChart가 렌더링됨.

✅ fallback의 의미

<Suspense fallback={<RevenueChartSkeleton />}>

여기서 fallback은 비동기 데이터 로딩 중에 보여줄 대체 UI입니다.
즉, RevenueChart가 데이터를 다 가져올 때까지 RevenueChartSkeleton을 보여주는 역할을 합니다.


✅ Suspense가 필요한 이유

  1. UX 개선:
    • 사용자가 빈 화면을 보는 것이 아니라 스켈레톤 로딩 화면을 볼 수 있어 더 좋은 경험 제공.
  2. 비동기 데이터 처리 최적화:
    • RevenueChart가 데이터를 다 받을 때까지 기다리지 않고, 먼저 fallback UI를 렌더링.
  3. Next.js의 Streaming과 결합 가능:
    • Suspense는 Next.js의 스트리밍(Streaming) 기능과 함께 사용되어 서버에서 데이터를 준비되는 대로 점진적으로 표시할 수 있음.

✅ 결론

✔ Suspense는 비동기 컴포넌트의 로딩이 끝날 때까지 fallback UI를 표시
✔ fallback은 **대체 UI(보통 스켈레톤 로딩 화면)**을 의미
✔ 데이터를 가져오는 동안 사용자에게 로딩 UI를 먼저 보여줘서 더 부드러운 UX 제공

이제 Suspense를 이해했으니, Next.js에서 비동기 데이터 페칭을 최적화하는 데 활용할 수 있어요! 🚀


Suspense 패턴을 사용법은 @/app/ui/skeleton.tsx 파일에 skeleton UI를 구현해서 사용자가 로딩 중에 볼 화면을 설계하고 지정할 수 있다.

import { Suspense } from 'react';
import { 
  RevenueChartSkeleton,
  LatestInvoicesSkeleton,
  CardsSkeleton,
} from '@/app/ui/skeletons';

 

 

위 과정들을 통해 스트리밍을 적용시켰으며, 최종적으로 새로고침을 통해 로드하는 속도가 빨라짐을 확인할 수 있었습니다.

스트리밍 적용 결과



Comments