[NextJS] Learn 8장 - 정적 및 동적 렌더링

알찬코·2024년 1월 19일

NextJS

목록 보기
9/20
post-thumbnail

이전 장에서는 대시보드 개요 페이지에 대한 데이터를 가져왔습니다. 그러나 현재 설정의 두 가지 제한 사항에 대해 간략하게 논의했습니다.

  1. 데이터 요청으로 인해 의도하지 않은 폭포가 생성됩니다.
  2. 대시보드는 정적이므로 데이터 업데이트가 애플리케이션에 반영되지 않습니다.

  • 정적 렌더링이 무엇이며 애플리케이션 성능을 어떻게 향상시킬 수 있는지 알아보세요.
  • 동적 렌더링이란 무엇이며 언제 사용해야 할까요?
  • 대시보드를 동적으로 만드는 다양한 접근 방식.
  • 느린 데이터 가져오기를 시뮬레이션하여 무슨 일이 일어나는지 확인하세요.

1. 정적 렌더링이란 무엇입니까?

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

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

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

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

정적 렌더링의 반대는 동적 렌더링입니다.

🔍 퀴즈

  • 정적 렌더링이 대시보드 앱에 적합하지 않은 이유는 무엇입니까?
    a. 웹사이트 속도를 느리게 만들기 때문에
    b. 서버 부하가 늘어나기 때문에
    c. 응용 프로그램은 최신 데이터 변경 사항을 반영하지 않기 때문에
    d. 콘텐츠 전송 네트워크가 필요하기 때문에

2. 동적 렌더링이란 무엇입니까?

동적 렌더링을 사용하면 요청 시 (사용자가 페이지를 방문할 때) 각 사용자의 콘텐츠가 서버에서 렌더링됩니다. 동적 렌더링에는 몇 가지 이점이 있습니다.

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

📖 퀴즈

  • 요청 시에만 알 수 있는 정보에는 어떤 것이 있나요?
    a. 데이터베이스 스키마
    b. URL 경로
    c. 쿠키 및 URL 검색 매개변수

3. 대시보드를 동적으로 만들기

기본적으로 @vercel/postgres는 자체 캐싱 의미 체계를 설정하지 않습니다. 이를 통해 프레임워크는 자체 정적 및 동적 동작을 설정할 수 있습니다.

서버 구성 요소 내부에서 호출되는 Next.js API unstable_noStore나 데이터 가져오기 기능을 사용하여 정적 렌더링을 거부할 수 있습니다. 이것을 추가해 보겠습니다.

data.ts에서, next/cache로부터 unstable_noStore를 가져오고, 데이터 가져오기 함수의 최상위에 호출합니다.

// ...
import { unstable_noStore as noStore } from 'next/cache'; // noStore 불러오기
 
export async function fetchRevenue() {
  // 응답이 캐시되지 않도록 하려면 여기에 noStore()를 추가합니다.
  // 이 값은 fetch(..., {cache: 'no-store'})와 같습니다.
  noStore(); // 호출하기
 
  // ...
}
 
export async function fetchLatestInvoices() {
  noStore(); // 호출하기
  // ...
}
 
export async function fetchCardData() {
  noStore(); // 호출하기
  // ...
}
 
export async function fetchFilteredInvoices(
  query: string,
  currentPage: number,
) {
  noStore(); // 호출하기
  // ...
}
 
export async function fetchInvoicesPages(query: string) {
  noStore(); // 호출하기
  // ...
}
 
export async function fetchFilteredCustomers(query: string) {
  noStore(); // 호출하기
  // ...
}
 
export async function fetchInvoiceById(query: string) {
  noStore(); // 호출하기
  // ...
}

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

4. 느린 데이터 가져오기 시뮬레이션

대시보드를 동적으로 만드는 것이 좋은 첫 번째 단계입니다. 그러나... 이전 장에서 언급한 한 가지 문제가 여전히 남아 있습니다. 하나의 데이터 요청이 다른 모든 데이터 요청보다 느리면 어떻게 되나요?

느린 데이터 가져오기를 시뮬레이션해 보겠습니다. data.ts 파일에서 .console.logsetTimeoutfetchRevenue() 내부의 주석 처리를 제거합니다.

export async function fetchRevenue() {
  try {
    // 데모 목적으로 응답을 인위적으로 지연합니다.
    // 프로덕션에서 이 작업을 수행하지 마세요 :)
    console.log('Fetching revenue data...'); // 콘솔 찍기
    await new Promise((resolve) => setTimeout(resolve, 3000)); // 느린 데이터 가져오기
 
    const data = await sql<Revenue>`SELECT * FROM revenue`;
 
    console.log('Data fetch completed after 3 seconds.'); // 콘솔 찍기
 
    return data.rows;
  } catch (error) {
    console.error('Database Error:', error);
    throw new Error('Failed to fetch revenue data.');
  }
}

이제 http://localhost:3000/dashboard/ 를 엽니다.새 탭에서 페이지를 로드하는 데 시간이 얼마나 오래 걸리는지 확인하세요. 터미널에는 다음 메시지도 표시됩니다.

Fetching revenue data...
Data fetch completed after 3 seconds.

여기서는 느린 데이터 가져오기를 시뮬레이션하기 위해 인위적인 3초 지연을 추가했습니다. 그 결과 이제 데이터를 가져오는 동안 전체 페이지가 차단됩니다.

개발자가 해결해야 하는 공통 과제는 다음과 같습니다.

동적 렌더링을 사용하면 애플리케이션 속도는 가장 느린 데이터를 가져오는 속도만큼만 빨라집니다.

📖 참고자료

Chapter 8. Static and Dynamic Rendering

0개의 댓글