(준)공식 문서/Next.js

[ Next.js 공식 문서 ] Rendering (1) - Sever Components

Je-chan 2024. 4. 14. 02:14

 

  React 서버 컴포넌트를 사용하면 서버에서 렌더링하고 선택적으로 캐시할 수 있는 UI 를 작성할 수 있다. Next.js 에서는 경로 Segement 별로 렌더링 작업을 추가로 분할해서 Streaming 과 부분 렌더링이 가능하게 한다. 서버 렌더링에는 세 가지 전략이 있다.

 

  1. 정적 렌더링
  2. 동적 렌더링
  3. Streaming

  이 페이지에서는 서버 컴포넌트가 어떻게 작동하는지, 언제 사용하는지와 다양한 서버 렌더링 전략에 대해 설명한다. 

 

1. 서버 렌더링의 이점 

  서버 렌더링에서 렌더링 작업을 하면 여러 이점이 있다. (* 이점은 중요하니 공식문서와 다르게 소주제로 다룬다)

 

1-1) 데이터 가져오기

  서버 컴포넌트를 사용하면 데이터 소스에 더 가까운 서버로 데이터를 가져올 수 있다. 렌더링에 필요한 데이터를 가져오는 데 걸리는 시간을 줄이고, 클라이언트가 요청해야 할 요청 수를 줄여서 성능을 향상시킬 수 있다.

 

1-2) 보안

  서버 컴포넌트를 사용하면 토큰이나 API 키와 같은 민감한 데이터와 로직을 클라이언트에 노출시키지 않을 수 있다.

 

1-3) 캐싱

  서버에서 렌더링하면 결과를 캐시하고 이후 요청과 다른 사용자 간에 재사용할 수 있다. 이는 각 요청에 대한 렌더링과 데이터 가져오는 시간을 줄여서 성능을 향상시키고 비용을 절감할 수 있다.

 

1-4) 성능

  서버 컴포넌트는 기본 성능을 최적화하는 도구들을 추가적으로 제공한다. 예를 들어, 전적으로 클라이언트 컴포넌트로 구성된 앱에서 시작하는 경우, 상호 작용 하지 않는 UI 의 일부를 서버 컴포넌트로 이동하면 클라이언트 사이드의 JS 양을 줄일 수 ㅇㅆ다. 이는 인터넷 속도가 느리거나 성능이 떨어지는 기기를 사용하는 사용자에게 유리하다.

 

1-5) 데이터 가져오기

  서버 컴포넌트를 사용하면 데이터 소스에 더 가까운 서버로 데이터를 가져올 수 있다. 렌더링에 필요한 데이터를 가져오는 데 걸리는 시간을 줄이고, 클라이언트가 요청해야 할 요청 수를 줄여서 성능을 향상시킬 수 있다.

 

1-6) FCP(초기 페이지 로드와 첫 번재 콘텐츠 도달 시간)

  서버에서는 사용자가 클라이언트에서 JS 를 다운로드, 파싱, 실행하는 시간을 기다리지 않고 페이지를 즉시 볼 수 있도록 HTML 을 생성할 수 있다.

 

1-7) 검색 엔진 최적화, 소셜 네트워크 공유

  렌더링된 HTML 은 검색 엔진 봇이 페이지를 인덱싱하고 소셜 네트워크 봇이 페이지에 대한 소셜 카드 미리보기를 생성하는데 사용할 수 있다.

 

1-8) Streaming

  서버 컴포넌트는 렌더링 작업을 여러 조각으로 분할하고 준비되는 대로 클라이언트에 스트리밍할 수 있다. 이를 통해서 사용자는 전체 페이지가 서버에서 렌더링될 때까지 기다릴 필요 없이 페이지의 일부를 더 일찍 볼 수 있다.


2. Next.js 에서 서버 컴포넌트 사용하기

  기본적으로 Next.js 는 서버 컴포넌트를 사용한다. 추가 구성 없이 자동으로 서버 렌더링을 구현할 수 있으며, 필요할 때 클라이언트 컴포넌트를 사용하도록 한다.

 


3. 서버 컴포넌트는 어떻게 렌더링되는가?

  서버에서 Next.js 는 React API 를 활용해서 렌더링한다. 렌더링 작업은 개별 경로 Segement 와 Suspense Boundary 경계로 청크가 나뉜다. 각각의 청크는 두 가지 단계를 거쳐서 렌더링된다.

 

  1. React 는 서버 컴포넌트를 **React Server Component Payload(RSC Payload)** 라는 특수 데이터 형식으로 렌더링한다.
  2. Next.js 는 RSC Payload 와 클라이언트 컴포넌트 JS 지시 사항(JS instruction)을 사용해 서버에서 HTML 파일을 렌더링한다.

  그 다음, 클라이언트에서는 아래의 단계를 거친다.

 

  1. HTML 은 해당 경로에서 아무런 상호작용할 수 없지만 빠르게 보여줄 수 있는 화면을 만드는데 사용된다. 그리고 이것은 처음 페이지를 로딩할 때만 그렇다.
  2. RSC Payload 는 클라이언트 컴포넌트, 서버 컴포넌트를 조정하고 DOM 을 업데이트한다.
  3. JS 지시사항은 클라이언트 컴포넌트들을 **hydrate** 해서 애플리케이션을 상호작용되도록 한다.

 

3-1) RSC Payload

  RSC Payload 는 렌더링된 React  서버 컴포넌트 트리를 컴팩트한 이진트리로 표현한 것이다. 클라이언트에서 React 가 브라우저 DOM 을 업데이트 하는데 사용된다. RSC Payload 는 다음이 포함된다.

 

  1. 서버 컴포넌트의 렌더링 결과
  2. 클라이언트 컴포넌트가 렌더링될 위치의 placeholder 와 그 JS 파일에 대한 참조
  3. 서버 컴포넌트에서 클라이언트 컴포넌트로 전달한 모든 props

4. 서버 렌더링 전략 

  서버 렌더링 전략으로 다음의 세 가지가 있다. Static(정적), Dynamic(동적), Streaming

 

4-1) Static (기본 설정)

  정적 렌더링에서는 빌드 타임에 해당 경로를 렌더링하거나 데이터를 검증(한 후에 백그라운드에서 렌더링한다. 결과는 케시되어 CDN 으로 전송할 수 있다. 이 최적화는 사용자들과 서버 요청 간에 렌더링 결과를 공유할 수 있게 한다.

 

  정적 렌더링은 사용자마다 달라지는 데이터가 없고, 빌드 타임에 명확히 알 수 있는 데이터를 활용하는 경로에서 유용하게 사용될 수 있다. 예를 들면, 블로그 포스트다 상품 페이지 같은 것들.

 

 

4-2) Dynamic  

  동적 렌더링에서는 각 사용자의 요청에 경로를 렌더링한다. 동적 렌더링은 사용자별로 달라지는 데이터가 있는 경로 요청이나 요청한 시점에만 알 수 있는 정보(쿠키, URL 의 params)들이 포함된 경로에서 유용하게 사용할 수 있다.

 

(1) 캐싱된 데이터를 활용한 동적 렌더링

  대부분의 웹 사이트에서는 경로가 완전히 정적이거나 완전히 정적이지 않다. 예를 들어, 이커머스 페이지 중에는 매시간마다 업데이트 하는 캐싱된 상품 데이터를 사용하면서 캐시되지 않은 개인화된 데이터를 가진 것도 있을 수 있다. Next.js 에서는 캐싱하거나 캐싱하지 않은 데이터 둘 다 갖는 경로를 동적으로 렌더링할 수 있다. 이것이 가능한 이유는 RSC Payload 와 캐싱이 별도로 이뤄지는 것 덕분이다. 이런 방식으로 인해 요청 시 모든 데이터를 가져오는 성능 영향에 대한 걱정 없이 동적으로 렌더링할 수 있다.

 

(2) 동적 함수

  (* 지금 쓰는 것처럼 공식문서와 달리 동적함수 -> 동적 렌더링으로의 전환 이 순서로 읽는 것이 더 이해가 쉬워서 순서를 변경해봤다) 동적 함수는 요청하는 시점에서만 알 수 있는 정보, 예를 들어 사용자의 쿠키, 현재 요청의 헤더, URL 의 params 에 의존한다. 

 

  1. **cookies()**, **headers()**
    : 이 함수들은 서버 컴포넌트에서 사용함녀 전체 경로가 요청 시에 동적 렌더링으로 설정된다.

  2. **searchParams()**
    : 페이지에서 searchParams Prop 을 사용하면 해당 페이지는 요청 시에 동적 렌더링으로 설정된다.

  위 함수들 중 어느 하나를 사용하면 전체 경로가 요청 시에 동적으로 렌더링하는 방식을 선택하게 된다.

 

(3) 동적 렌더링으로 전환

  렌더링 중에 동적 함수나 캐시되지 않은 데이터 요청이 발견되면, Next.js 는 전체 경로를 동적으로 렌더링하도록 전환한다. 아래의 표는 동적 함수와 데이터 캐싱이 렌더링 방식에 어떻게 영향을 주는지를 보여주는 표다.

 

동적 함수 데이터 렌더링 방식
없음 캐싱됨 정적 렌더링
있음 캐싱됨 동적 렌더링
없음  캐싱되지 않음 동적 렌더링
있음 캐싱되지 않음 동적으로 렌더링

 

  위 표에서 알 수 있듯이, 모든 데이터가 캐시돼야만 정적 렌더링을 한다. 그러나 캐시된 데이터와 캐시되지 않은 데이터 가져오기를 모두 사용하는 경우에는 동적 렌더링을 한다.

 

  개발자로서 정적 렌더링할 것인지, 동적 렌더링할 것인지 선택하지 않아도 되는게, Next.js 가 사용된 기능과 API 에 따라서 각 경로별 최적의 렌더링 전략을 자동으로 선택한다. 대신에 특정 데이터를 캐시하거나 재검증 할 때를 선택하고, UI 의 일부를 Streaming 하도록 설정할  있다.

 

 

 

4-3) Streaming

 

 

  Streaming 을 활용해 서버에서 UI 를 점진적으로 렌더링할 수 있다. 작업은 여러 청크로 분할하고 준비되는 대로 클라이언트에 streaming 된다. 사용자는 전체 컨텐츠가 렌더링을 완료하기 전에 페이지의 일부를 즉시 볼 수 있게 된다.

 

 

  Streaming 은 기본적으로 Next.js 의 **App Router** 에 내장돼 있다. 이는 초기 페이지 로딩 성능과 로딩 속도가 느린 데이터를 가져오는 UI 성능을 개선하는데 도움을 준다. 예를 들면 제품 페이지 리뷰 등이 있다.

 

  loading.js 와 같이 React **Suspense** 를 활용해 경로 Segement 스트리밍을 시작할 수도 있다.


Reference

 

https://nextjs.org/docs/app/building-your-application/rendering/server-components

 

Rendering: Server Components | Next.js

Learn how you can use React Server Components to render parts of your application on the server.

nextjs.org