그냥 블로그

[Next.js] 정적 및 동적 렌더링 본문

프로젝트/WALFI

[Next.js] 정적 및 동적 렌더링

코딩하는 공대생 2024. 5. 22. 11:57
반응형

 

https://nextjs.org/learn/dashboard-app/static-and-dynamic-rendering

 

Learn Next.js: Static and Dynamic Rendering | Next.js

Understand how rendering works in Next.js, and make your dashboard app dynamic.

nextjs.org

 

정적 렌더링?

정적 렌더링을 사용하면 빌드 시(배포 시) 또는 재검증 중에 데이터 가져오기 및 렌더링이 서버에서 발생한다. 결과는 CDN(Content Delivery Network) 에 배포 및 캐시될 수 있습니다. 

CDN(Content Delivery Network)
 많은 장소에 걸쳐 분산된 서버들의 그룹. 서버들은 데이터의 중복 복사본들을 저장해 서버가 최종 사용자와 가장 가까운 서버를 기준으로 데이터 요청을 처리. 

Bootstrap, jQuery 같은 라이브러리들의 스타일 시트 및 JavaScript 파일(정적 에셋)을 전송하는데 사용된다. 

- CDN을 통해 라이브러리의 정적 애셋을 제공하면 라이브러리의 자체 서버 요청 부담이 줄어든다
- 대부분 CDN들은 전 세계에 서버를 갖고 있어 특정 라이브러리의 서버보다 사용자와 더 가까움.
- CDN들은 이미 적절한 캐시 설정이 되어 있어 CDN을 사용하면 자체 서버 정적 애셋을 위한 추가 설정이 필요 없다. 

 

사용자가 애플리케이션을 방문할 때마다 캐시된 결과가 제공된다. 정적 렌더링에는 몇 가지 이점이 있다. 

  • 더 빠른 웹사이트 - 사전 렌더링된 콘텐츠를 캐시하고 전 세계적으로 배포 가능. 이를 통해 전 세계 사용자가 웹사이트 콘텐츠에 더욱 빠르고 안정적으로 엑세스 가능. 
  • 서버 로드 감소 - 콘텐츠가 캐시되기 때문에 서버는 각 사용자 요청에 대한 콘텐츠 동적 생성 필요 x
  • SEO - 사전 렌더링된 콘텐츠는 페이지가 로드될 때 이미 콘텐츠를 사용할 수 있으므로 검색 엔진 크롤러가 색인 생성하기가 더 쉬움. 

정적 렌더링은 정적 블로그 게시물이나 제품 페이지와 같이 사용자 간 공유되는 데이터나 데이터가 없는 UI에 유용하다. 

 

 

동적 렌더링 ?

요청 시 (사용자가 페이지를 방문할 때) 각 사용자의 콘텐츠가 서버에서 렌더링됩니다. 

  • 실시간 데이터 - 동적 렌더링을 통해 애플리케이션은 실시간 또는 자주 업데이트되는 데이터를 표시할 수 있습니다. 이는 데이터가 자주 변경되는 애플리케이션에 이상적
  • 사용자별 콘텐츠 - 대시보드나 사용자 프로필과 같은 개인화된 콘텐츠를 제공하고 사용자 상호 작용을 기반으로 데이터를 업데이트하는 것이 더 쉬움. 
  • 요청 시간 정보 - 동적 렌더링을 사용하면 쿠키나 URL 검색 매개변수와 같이 요청 시간에만 알 수 있는 정보에 엑세스할 수 있음.

unstable_noStore  : 정적 렌더링 거부. 

 

스트리밍?

느린 데이터로 사용자 경험 개선하기

 

경로를 더 작은 "청크"로 나누고 준비가 되면 서버에서 클라이언트로 점진적으로 스트리밍할 수 있는 데이터 전송 기

 

스트리밍하면 느린 데이터 요청이 전체 페이지를 차단하는 것 방지. 사용자는 UI가 사용자에게 표시되기 전 모든 ㅔ이터가 로드될 때까지 기다리지 않고 페이지 일부를 보고 상호 작용 가능. 

 

Next.js에서 스트리밍 구현 방법

  • 페이지 수준에서 loading.tsx 파일 사용
  • 특정 구성 요소의 경우 <suspend>

loading.tsx

/app/dashboard에서 loading.tsx 새 파일 만들기.

  1. loading.tsx Suspense를 기반으로 페이지 콘텐츠가 로드되는 동안 대체 UI로 표시할 폴백 ui 생성가능하다. 
  2. <SideNav>는 정적이므로 즉시 표현된다. 동적 콘텐츠가 로드되는 동안 상호 작용이 가능하다. 
  3. 다른 페이지로 이동 전 페이지 로드가 완료될 때까지 기다릴 필요가 없다. ( 중단 가능 탐색 )
//  /app/dashboard/loading.tsx
import DashboardSkeleton from '@/app/ui/skeletons';
 
export default function Loading() {
  return <DashboardSkeleton />;
}

 

++ app 내 ()를 사용해 폴더를 생성하면 URL 경로에 포함되지 않는다. ex) (oveview)  

 

구성요소 스트리밍 (React Suspense)

 

/app/dashboard/page.tsx

import CardWrapper from '@/app/ui/dashboard/cards';
// ...
import {
  RevenueChartSkeleton,
  LatestInvoicesSkeleton,
  CardsSkeleton,
} from '@/app/ui/skeletons';
 
export default async function Page() {
  return (
    <main>
      <h1 className={`${lusitana.className} mb-4 text-xl md:text-2xl`}>
        Dashboard
      </h1>
      <div className="grid gap-6 sm:grid-cols-2 lg:grid-cols-4">
        <Suspense fallback={<CardsSkeleton />}>
          <CardWrapper />
        </Suspense>
      </div>
      // ...
    </main>
  );
}

 

/app/ui/dashboard/cards.tsx

// ...
import { fetchCardData } from '@/app/lib/data';
 
// ...
 
export default async function CardWrapper() {
  const {
    numberOfInvoices,
    numberOfCustomers,
    totalPaidInvoices,
    totalPendingInvoices,
  } = await fetchCardData();
 
  return (
    <>
      <Card title="Collected" value={totalPaidInvoices} type="collected" />
      <Card title="Pending" value={totalPendingInvoices} type="pending" />
      <Card title="Total Invoices" value={numberOfInvoices} type="invoices" />
      <Card
        title="Total Customers"
        value={numberOfCustomers}
        type="customers"
      />
    </>
  );
}

 

 

Suspense 경계를 배치할 위치 결정

 

 

Suspense 경계를 배치하는 위치는 다음 몇가지 사항을 고려

  1. 페이지가 스트리밍될 때 사용자가 페이지를 경험하기 원하는 방식
  2. 어떤 콘텐츠에 우선순위를 두고 싶은지
  3. 구성요소가 데이터 가져오기에 의존하는 경우

 

  • 전체 페이지를 스트리밍하는 loading.tsx의 경우, 구성 요소 하나가 느려지면 전체 속도가 느려진다. 
  • 모든 구성 요소를 개별적으로 스트리밍할 수도 있지만 UI가 준비되면 화면에 갑자기 나타날 수 있다. 
  • 페이지 섹션을 스트리밍해 시차 효과를 만들 수 있다. 

 

 

'프로젝트 > WALFI' 카테고리의 다른 글

메타 데이터  (0) 2024.05.29
[Next.js]  (0) 2024.05.24
[Next.js] app router + React Query  (0) 2024.05.20
[Next.js] Next.js 1 - 폴더 구조  (0) 2024.05.10
[Web] WALFI Backend 연동 (JSP, MySQL)  (0) 2024.04.16