- 서버 컴포넌트(RSC)란?
RSC를 이용해서, 선택적으로 서버에 캐시되고 렌더링되는 UI를 만들 수 있다.
Next.js에서는 렌더링 작업이 라우트 세그먼트(route segments)별로 나뉘어 스트리밍과 부분 렌더링이 가능하다.
또한, Next.js에서 서버 렌더링 전략은 Static Rendering, Dynamic Rendering, Streaming이 있다.
- Route Segment : URL의 각 경로의 각 부분을 의미한다. /product/[id] ⇒ product와 [id] 각각이 Route Segment이다.
- 부분 렌더링 : next.js는 Route Segment 단위로 렌더링 작업을 분리한다. ⇒ 헤더 따로, 내용 따로 렌더링
- 스트리밍 : 페이지의 일부가 준비된 즉시, 브라우저로 전송해서 렌더링 하는 것
- 서버 렌더링의 장점
- Data Fetching
RSC는 data fetching을 data source와 가까운 서버에서 할 수 있도록 한다.
이것을 통해, 렌더링을 위한 필요한 시간이 단축되고,
클라이언트가 보내야할 요청이 줄어듦으로써, 웹페이지 성능을 향상 시킬 수 있다. - Security
RSC를 사용하면, tokens이나 API키 같은 민감 데이터와 로직을 서버에만 둘 수 있다. - Caching
서버에서 렌더링하는 것을 통해, 결과는 cache되고 전유저에 걸친, 후속 요청에 재사용될 수 있다.
이를 통해, 각 요청에서 수행되는 렌더링과 데이터 패칭의 양을 줄여, 페이지 성능을 향상 시킬 수 있다. - Performance
RSC는 기본 성능을 최적화시킬 수 있는 추가적인 툴을 제공한다.
예를 들어, 전체적으로 Client Component로 구성된 프로젝트에서,
상호작용이 필요없는 부분을 RSC로 바꾸면, Client Side에서 사용할 Javascript의 양이 줄어들게 된다.
이를 통해, 인터넷 속도가 느리거나, 성능이 낮은 기기를 사용하는 사용자들에게 도움이 될 수 있다.
브라우저에서 다운로드, 파싱, 실행해야할 Javascript 코드가 줄어들기 때문이다. - Initial Page Load and First Contentful Paint
서버에서 HTML을 생성하여, 사용자가 즉시 페이지를 볼 수 있도록 만들 수 있다.
이렇게 하면, 클라이언트는 자바스크립트를 다운로드하고, 파싱하고, 실행하기 위해 기다릴 필요가 없어진다. - Search Engine Optimization and Social Network Shareability
서버에서 생성된 HTML은 검색엔진bot이 색인을 위해 사용할 수 있다.
또한, SNS bot이 meta 정보를 가져와서, 미리보기 카드를 만드는 것에 도움을 줄 수 있다.
즉 SEO에 도움을 준다. - Streaming
RSC는 렌더링 작업을 chunk단위로 나누고, 스트리밍할 수 있게 해준다.
이를 통해 사용자는 페이지의 전체가 렌더링되기를 기다리지 않고,페이지의 부분을 먼저 확인할 수 있게 된다.
- Data Fetching
- 서버 컴포넌트를 Next.js에서 사용하는 법
기본적으로 Next.js는 Server Component를 사용하기 때문에 Server component를 사용하기 위해 설정해야 할 것은 없다. Client Component를 사용하고 싶다면, 선택적으로 사용할 수 있다. - 어떻게 Server Components가 렌더링되는가?
- 서버에서는 Next.js가 React의 API를 사용해 렌더링 작업을 제어한다.
이 과정에서 렌더링 작업을 라우트 세그먼트(route segments)와 Suspense 경계를 기준으로 청크(chunk) 단위로 나눈다. - 각 청크는 다음 두 단계로 렌더링된다:
- React가 Server Components를 React Server Component Payload(RSC Payload)라는 특별한 데이터 형식으로 직렬화한다.
- Next.js가 RSC Payload와 Client Component JavaScript 지침(JavaScript instructions)을 사용해 서버에서 HTML을 생성한다.
- 클라이언트에서는 다음 작업이 이루어진다:
- 서버에서 생성된 HTML은 초기 페이지 로드 시 빠르고 상호작용 없는 프리뷰를 즉시 보여주는 데 사용된다.
- RSC Payload를 이용해 클라이언트와 서버의 컴포넌트 트리를 동기화하고 DOM을 업데이트한다.
- JavaScript 지침을 활용해 Client Components를 하이드레이션(hydration)하여 애플리케이션에 상호작용 기능을 추가한다.
- 서버에서는 Next.js가 React의 API를 사용해 렌더링 작업을 제어한다.
- RSC Payload란 무엇인가?
- RSC Payload는 렌더링된 React Server Components 트리를 압축된 바이너리 형식으로 표현한 데이터다.
이 데이터는 클라이언트에서 React가 브라우저의 DOM을 업데이트하는 데 사용된다. - RSC Payload에는 다음 내용이 포함된다:
- Server Components의 렌더링 결과
- Client Components가 렌더링될 위치를 나타내는 플레이스홀더(Placeholders)와 관련된 JavaScript 파일 참조 정보
- 서버 컴포넌트에서 클라이언트 컴포넌트로 전달되는 모든 props
- Static Rendering (Default)
라우트들은 빌드 타임에 렌더링되거나, 데이터 재검증 이후 백그라운드에서 렌더링된다.
렌더링된 결과는 캐시되어 CDN(Content Delivery Network)으로 푸시된다.
이 최적화를 통해 렌더링 작업 결과를 여러 사용자와 서버 요청 간에 공유할 수 있다.서버 렌더링 전략
Static Rendering은 특정 사용자에게 개인화되지 않은 데이터로, 빌드 타임에 알 수 있는 데이터를 사용하는 경우 유용하다. 예를 들어, 정적인 블로그 게시물이나 제품 상세 페이지 등이 해당된다. - Dynamic Rendering
Dynamic Rendering에서는 라우트가 사용자 요청 시점에 맞춰 렌더링된다.
Dynamic Rendering은 라우트에 쿠키, URL의 검색 매개변수(search params) 등 사용자에 맞춰 개인화된 데이터가 포함되거나, 요청 시점에만 알 수 있는 정보를 처리할 때, 유용하다. - Dynamic Routes with Cached Data
대부분의 웹사이트는 라우트가 완전히 정적이거나 완전히 동적인 경우가 드물다.
예를 들어, 전자상거래 페이지에서는 일정 주기로 재검증되는 캐시된 제품 데이터를 사용하는 동시에, 캐시되지 않은 개인화된 고객 정보를 처리해야 할 수도 있다.
Next.js에서는 캐시된 데이터와 캐시되지 않은 데이터를 동시에 사용하는 Dynamic Rendering 라우트를 설정할 수 있다.
이것이 가능한 이유는 RSC Payload와 데이터가 각각 독립적으로 캐시되기 때문이다.
이를 통해, 모든 데이터를 요청 시점에 가져와야 하는 것에 대한 성능 부담을 덜면서도 선택적으로 Dynamic Rendering을 사용할 수 있다. - Dynamic Rendering으로 전환하기
렌더링 중 { cache: 'no-store' } 옵션이 포함된 Dynamic API나 fetch 요청이 감지되면, Next.js는 전체 라우트를 Dynamic Rendering으로 전환한다.
아래는 Dynamic API와 데이터 캐싱이 라우트 렌더링 방식(Static 또는 Dynamic)에 미치는 영향을 나타낸 표다.
아래 표에서 라우트가 완전히 정적 렌더링되려면, 모든 데이터가 캐시되어야 한다.
그러나 Dynamic Rendering 라우트에서는 캐시된 데이터와 캐시되지 않은 데이터를 함께 사용할 수 있다.
- 개발자 관점에서의 선택
개발자는 Static과 Dynamic 렌더링 중 하나를 선택할 필요가 없다. Next.js가 사용된 기능과 API에 따라 자동으로 가장 적합한 렌더링 전략을 결정해준다. (bulid 시점에 pre-fetch를 할 지? 런타임 시점에 pre-fetch를 할지 Next.js가 결정)
대신, 언제 데이터를 캐시할지, 어떤 데이터를 재검증(revalidate)할지, 그리고 UI의 어떤 부분을 스트리밍할지를 결정하면 된다. - Dynamic APIs
Dynamic API는 요청 시점에만 알 수 있는 정보에 의존한다.
다음 API를 사용하는 경우, 개발자의 의도를 기반으로 전체 라우트에 대해 Dynamic Rendering이 적용된다:- cookies: 요청의 쿠키 정보
- headers: 요청 헤더 정보
- connection: 요청과 연결된 클라이언트 정보
- draftMode: 초안 모드 활성화 여부
- searchParams prop: URL의 검색 매개변수
- unstable_noStore: 데이터 캐싱을 방지하는 옵션
- Streaming
Streaming은 서버에서 UI를 점진적으로 렌더링할 수 있도록 도와준다.
렌더링 작업은 청크(chunk) 단위로 나뉘며, 각 청크가 준비되면 클라이언트로 스트리밍된다.
이를 통해 사용자는 모든 콘텐츠가 렌더링되기 전에 페이지의 일부를 먼저 확인할 수 있다.
Streaming은 Next.js의 App Router에 기본적으로 내장되어 있으며, 초기 페이지 로딩 성능을 향상시킬 뿐만 아니라, 느린 데이터 패칭으로 인해 전체 라우트 렌더링이 지연되는 문제를 해결한다.
Streaming 기반의 라우트를 구현하려면 loading.js와 React의 Suspense 컴포넌트를 활용하면 된다
- RSC Payload는 렌더링된 React Server Components 트리를 압축된 바이너리 형식으로 표현한 데이터다.
참조한 글
- https://nextjs.org/docs/app/building-your-application/rendering/server-components
'Web Development > Next.js' 카테고리의 다른 글
React를 쓰면서도 몰랐던 선언형 프로그래밍 이야기 (0) | 2025.03.23 |
---|---|
[Next.js] Next.js 라우팅 방식의 장점과 다른 방식들과의 차이점 (0) | 2024.12.22 |
[Next.js] 왜 우리는 Next.js를 사용하게 되었을까? (1) | 2024.12.22 |
[Next.js] 클라이언트 컴포넌트 (공식 문서 따라가기) (4) | 2024.12.14 |
[Web] 서버 컴포넌트 (1) | 2024.06.07 |