[Next.js] Static, Dynamic Rendering

·2024년 3월 25일
0

React

목록 보기
21/21
post-thumbnail

Next.js14로 블로그 만들기를 진행 중인데... 블로그 리스트를 보여주는 첫 메인 화면에서 문제가 발생했다.
분명 DB를 제대로 바라보고 있음에도 불구하고 로컬 환경에선 새로운 글을 쓰면 blogList API가 새로운 글을 바로 추가해서 같이 보여주는데, 배포 환경에선 blogList API에 새로운 글이 보이지 않았다.
API에서 ORM으로 잘못 불러오고 있나..? 라기엔 로컬에서 너무 잘불러옴^-^
고구마 천백만 개 먹고 있을 때 쯤 구글링을 해보다가 스택오버플로우에서 비슷한 증상 확인 후에 적용해보니 해결됐다... 황당
근데 저게 대체 뭔데..? 정적, 동적 렌더링... 알아보자!

Next.js app route

Next.js app route page에서 data fetching 시 별도로 캐시 설정을 하지 않더라도 기본적으로 캐시를 사용한다.
이를 통해 불필요한 데이터 패칭을 하지 않아도 되며, 서버는 이미 만들어진 파일들을 사용자에게 응답하기만 하면 되기 때문에 유저는 더 빠른 응답 속도를 기대할 수 있다.

Next.js 12의 page 디렉토리의 경우 getStaticProps를 사용하여 빌드 타임에 정적 파일들을 생성했으나, app 디렉토리에서는 특수 함수를 사용하지 않고 서버 컴포넌트 내부에서 간단하게 api를 호출하기만 해도 동작한다.
따라서 Next.js app 디렉토리의 페이지는 기본적으로 dynamic function을 사용하지 않는다면 static rendering을 채택한다.

정적 렌더링 (Static Rendering)

정적 렌더링이란?

정적 렌더링을 사용하면 빌드 시간 (배포할 때) 또는 재검증 중에 서버에서 데이터를 가져오거나 렌더링이 이루어진다.
그 후에 해당 결과를 CDN에 배포하고 캐시할 수 있다.

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

장점

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

정적 렌더링은 정적 블로그 게시물이나 제품 페이지와 같이 데이터가 없거나 사용가 잔에 공유되는 데이터가 없는 UI에 유용하다. 정기적으로 업데이트되는 개인화된 데이터가 있는 대시보드에는 적합하지 않을 수 있다.

동적 렌더링(Dynamic Rendering)

동적 렌더링이란?

동적 렌더링을 사용하면 요청 시 (사용자가 페이지를 방문할 때) 각 사용자의 컨텐츠가 서버에서 렌더링된다.

장점

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

동적 렌더링 설정하기

기본적으로 @vercel/postgres는 자체 캐싱 시멘틱을 설정하지 않는다. 따라서 프레임워크가 자체 정적 및 동적 동작을 설정할 수 있다.

서버 컴포넌트 또는 데이터 불러오기 함수 내에서 unstable_noStore라는 Next.js API를 사용하여 정적 렌더링을 사용하지 않도록 선택할 수 있다.

import { unstable_noStore as noStore } from 'next/cache';

export async function fetchRevenue() {
   // Add noStore() here to prevent the response from being cached.
  // This is equivalent to in fetch(..., {cache: 'no-store'}).
  noStore();
}

unstable_noStore는 실험적인 API이며, 향후 변경될 수 있다. 프로젝트에서 안정적인 API를 사용하려는 경우 세그먼트 구성 옵션 export const dynamic = 'force-dynamic'을 사용할 수도 있다.

느린 데이터 가져오기

동적 렌더링으로 설정할 경우, 데이터를 가져오는 동안 전체 페이지가 차단된다.
즉, 동적 렌더링을 사용하면 애플리케이션의 속도가 가장 느린 데이터를 가져오는 속도만큼만 빨라진다.

이러한 문제점은 streaming을 통해 해결할 수 있다.

streaming이란?

streaming은 경로를 더 작은 'chunks'로 나누고 준비되는 대로 서버에서 클라이언트로 점진적으로 스트리밍할 수 있는 데이터 전송 기술이다.

streaming을 사용하면 느린 데이터 요청이 전체 페이지를 차단하는 것을 방지할 수 있다. 이를 통해 사용자는 UI가 사용자에게 표시되기 전에 모든 데이터가 로드될 때까지 기다리지 않고 페이지의 일부를 보고 상호 작용할 수 있다.

streaming 구현 방법

  1. 페이지 수준에서 loading.tsx 파일 사용하기
  2. 특정 컴포넌트의 경우 <Suspense> 사용하기

1. 전체 페이지 streaming

/app/dashboard/ 폴더에서 loading.tsx 파일을 만든다.

// /app/dashboard/loading.tsx
export default function Loading() {
  return <div>Loading...</div>;
}
  • loading.tsxSuspense 위에 구축된 특별한 Next.js 파일로, 페이지 컨텐츠가 로드되는 동안 대체로 표시할 폴백 UI를 만들 수 있다.
  • 사용자는 동적 컨텐츠가 로드되는 동안 정적으로 표시되는 컴포넌트와 상호작용할 수 있다.
  • 사용자는 페이지 로딩이 완료될 때까지 기다렸다가 이동할 필요가 없다. (이를 중단형 탐색이라고 한다.)

2. 컴포넌트 streaming

Suspense를 사용하면 일부 조건이 충족될 때까지 애플리케이션의 렌더링 부분을 연기할 수 있다. Suspense에서 동적 컴포넌트를 래핑할 수 있다. 그런 다음 동적 컴포넌트가 로드되는 동안 표시할 대체 컴포넌트를 전달한다.

// /app/dashboard/page.tsx

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

export default async function Page() {
  return (
    <Suspense fallback={<RevenueChartSkeleton />}>
  		<RevenueChart />
  	</Suspense>
  );
}
// /app/ui/dashboard/revenue-chart.tsx

import { fetchRevenue } from '@/app/lib/data';

export default async function RevenueChart() {
  const revenue = await fetchRevenu();
  
  ...
}

< 참고 : https://nextjs.org/learn/dashboard-app/static-and-dynamic-rendering
https://nextjs.org/learn/dashboard-app/streaming
https://velog.io/@jay/Next.js-13-master-course-Static-Dynamic-Rendering >

profile
개발을 개발새발 열심히➰🐶

0개의 댓글