[Next.js] Server Components

Next.js 14의 컴포넌트 유형

Next.js에서 제공하고 있는 컴포넌트는 아래와 같습니다.

  1. Server Component: 서버에서 렌더링되는 컴포넌트.
  2. Client Component: 클라이언트에서 렌더링되는 컴포넌트.
  3. Composition Component: 서버와 클라이언트 컴포넌트를 조합하여 사용하는 컴포넌트.

 

서버 렌더링의 장점

  • 데이터 요청: 서버에서 데이터를 요청하므로 렌더링에 필요한 시간을 단축 시킬 수 있음.
  • 보안: 유저 측에서 데이터에 직접 접근하는 경우에는 token이나 API 키 들을 노출 될 가능성이 있으나, 서버에서 진행하게 되면 이러한 문제를 해결할 수 있음.
  • 캐싱: 서버에서 렌더링을 진행하게 된 경우에 결과를 캐싱 해두었다가 같은 요청에는 캐싱된 데이터를 반환함으로서 성능과 효율성을 높일 수 있음.
  • 성능: 유저 컴포넌트로 모든 데이터를 생성하고자 하면, 유저 컴퓨터 성능과 브라우저에 따라 렌더링 속도가 달라질 수 있으나, 서버에서 생성을 하게 되면 이러한 문제를 완화할 수 있음.
  • 초기 반응성 (Initial Page Load 와 FCP): 유저가 처음 접근하는 페이지의 컴포넌트를 부분적으로 렌더링 하고 먼저 보여줌으로서 보다 좋은 경험을 유저에게 제공 가능.
  • 검색엔진: 서버에서 제공되는 데이터는 검색엔진에 사용이 되므로 보다 노출이 되기 좋은 환경에 있음.
  • 스트리밍: 서버 컴포넌트에서 렌더링 작업을 청크로 구분하여 스트리밍 하는 기능을 제공하여, 유저가 페이지 일부분을 보다 빨리 보게 할 수 있음.

 

❓Chunk
"Chunk"는 서버가 클라이언트에 전송하는 HTML의 일부입니다. 스트리밍 렌더링에서는 전체 페이지를 한 번에 전송하는 대신, 여러 개의 청크로 나누어 전송합니다. 각 청크는 페이지의 일부분을 포함하며, 클라이언트는 이 청크를 받아서 즉시 렌더링할 수 있습니다.

 

 

Next.js14 에서 Server Components 렌더링 방식

Next.js 14는 React의 API를 사용하여 서버 측에서 컴포넌트를 렌더링합니다. 렌더링 작업은 개별 라우트 세그먼트와 Suspense Boundary에 따라 청크로 나누어집니다.

 

서버 컴포넌트 렌더링 과정

청크 렌더링 (Chunk Rendering):

  • React는 서버에서 컴포넌트를 렌더링하면서 이를 청크 단위로 나눕니다. 이는 Suspense Boundary와 같은 요소에 따라 분리됩니다.
  • 이러한 청크는 서버에서 RSC Payload로 직렬화됩니다.

React Server Component Payload (RSC Payload):

  • React가 서버 컴포넌트를 RSC Payload로 렌더링합니다. RSC Payload는 서버 컴포넌트의 상태와 구조를 포함하는 직렬화된 데이터입니다.
  • Next.js 서버는 이 RSC Payload를 생성하는 역할을 담당합니다.

HTML 생성 (HTML Generation):

  • Next.js는 RSC Payload와 클라이언트 컴포넌트의 JavaScript 명령을 사용하여 서버 측에서 HTML을 생성합니다.
  • 이 HTML은 클라이언트에 초기 비대화형 미리보기로 전송됩니다.

 

❓React Server Component Payload (RSC Payload)
RSC Payload는 렌더링된 React Server Components 트리의 압축된 바이너리 표현입니다. 클라이언트 측에서 React가 브라우저의 DOM을 업데이트하는 데 사용됩니다. RSC Payload는 다음을 포함합니다:

  • 렌더링된 Server Components의 결과
  • Client Components가 렌더링될 자리와 자바스크립트 파일에 대한 참조
  • Server Component에서 Client Component로 전달되는 모든 props

 

 

Server Component 렌더링 전략

Next.js 에서 제공하는 렌더링 전략은 Static, Dynamic, Streaming 총 3가지로 제공이 되고 있으며, 각 특징은 아래와 같습니다.

 

정적 렌더링 (기본)

정적 렌더링을 사용하면 라우트가 빌드 시점 또는 데이터 재검증 후 백그라운드에서 렌더링됩니다. 렌더링된 결과는 캐시되며 콘텐츠 전송 네트워크(CDN)에 푸시될 수 있습니다. 이 최적화 방법은 렌더링 작업의 결과를 사용자와 서버 요청 간에 공유할 수 있게 해줍니다.

정적 렌더링은 라우트의 데이터가 사용자별로 맞춤화되지 않고 빌드 시점에 알 수 있는 경우에 유용합니다. 예를 들어, 정적 블로그 게시물이나 제품 페이지 등이 이에 해당합니다.

 

동적 렌더링

동적 렌더링을 사용하면 각 사용자 요청 시점에 라우트가 렌더링됩니다.

동적 렌더링은 라우트의 데이터가 사용자 맞춤형이거나, 쿠키나 URL의 검색 매개변수와 같이 요청 시점에서만 알 수 있는 정보를 포함하는 경우에 유용합니다.

 

캐시된 데이터를 사용하는 동적 라우트

Next.js에서는 캐시된 데이터와 캐시되지 않은 데이터를 모두 포함하는 동적으로 렌더링된 라우트를 가질 수 있습니다. 이는 RSC 페이로드와 데이터가 별도로 캐시되기 때문에 가능합니다. 이로 인해 모든 데이터를 요청 시점에 가져오는 것에 대한 성능 영향을 걱정하지 않고도 동적 렌더링을 선택할 수 있습니다.

 

동적 렌더링으로 전환

렌더링 중에 동적 함수 또는 캐시되지 않은 데이터 요청이 발견되면, Next.js는 전체 라우트를 동적으로 렌더링으로 전환합니다. 다음 표는 동적 함수와 데이터 캐시가 라우트의 정적 또는 동적 렌더링 여부에 미치는 영향을 요약한 것입니다.

 

동적함수 데이터 라우트
아니오 캐시됨 정적으로 렌더링됨
캐시됨 동적으로 렌더링됨
아니오 캐시되지 않음 동적으로 렌더링됨
캐시되지 않음 동적으로 렌더링됨
 

위 표에서, 라우트가 완전히 정적이 되려면 모든 데이터가 캐시되어야 합니다. 그러나 캐시된 데이터와 캐시되지 않은 데이터 가져오기를 모두 사용하는 동적으로 렌더링된 라우트를 가질 수 있습니다.

개발자로서 정적 렌더링과 동적 렌더링 중 하나를 선택할 필요는 없습니다. Next.js는 사용된 기능과 API를 기반으로 각 라우트에 대해 최상의 렌더링 전략을 자동으로 선택합니다. 대신, 특정 데이터를 언제 캐시하거나 재검증할지, 그리고 UI의 일부를 스트리밍할지를 선택하면 됩니다.

 

동적 함수

동적 함수는 사용자의 쿠키, 현재 요청 헤더 또는 URL의 검색 매개변수와 같이 요청 시점에서만 알 수 있는 정보에 의존합니다. Next.js에서 이러한 동적 함수는 다음과 같습니다.

  • cookies() 및 headers(): 서버 컴포넌트에서 이를 사용하면 전체 라우트가 요청 시점에 동적 렌더링으로 전환됩니다.
  • searchParams: 페이지에서 searchParams 속성을 사용하면 페이지가 요청 시점에 동적 렌더링으로 전환됩니다.

이 함수들 중 하나라도 사용하면 전체 라우트가 요청 시점에 동적 렌더링으로 전환됩니다.

 

스트리밍

스트리밍은 서버에서 점진적으로 UI를 렌더링할 수 있게 해줍니다. 작업이 청크 단위로 분할되어 준비되는 대로 클라이언트로 스트리밍됩니다. 이를 통해 사용자는 전체 콘텐츠가 렌더링되기 전에 페이지의 일부를 즉시 볼 수 있습니다.

스트리밍 경로 세그먼트 설정

스트리밍 경로 세그먼트를 설정하려면 loading.js와 React Suspense를 사용하여 UI 컴포넌트를 구성할 수 있습니다. 이를 통해 데이터가 준비되는 동안 로딩 UI를 제공하고, 준비된 데이터가 있는 부분부터 점진적으로 렌더링합니다.

  • loading.js:
    • 경로 세그먼트의 로딩 상태를 처리하는 컴포넌트입니다.
    • 데이터가 준비되지 않았을 때 표시할 로딩 UI를 정의합니다.
  • React Suspense:
    • React의 Suspense를 사용하여 지연된 데이터를 처리하고, 준비된 데이터가 있을 때 UI를 렌더링합니다.
    • 로딩 중인 상태를 처리하는 로딩 UI를 제공합니다.

'Frontend > Next.js' 카테고리의 다른 글

[Next.js] Routing 2부  (0) 2024.06.22
[Next.js] Routing 1부  (0) 2024.06.22
[Next.js] Server and Client Composition Pattern  (0) 2024.06.22
[Next.js] Client Components  (0) 2024.06.22
[Next.js] 왜 두 번 렌더링 되는 것일까?  (1) 2024.02.28