본문 바로가기
개발/Next.js

React Server Component

by 안뇽! 2023. 10. 12.
반응형

React Server Component

Next app-router에서 app 폴더에 컴포넌트를 만들면 자동으로 서버 컴포넌트(이하 RSC)로 만들어진다.

그런데 SSR과 RSC는 어떤 차이일까?

 

SSR

일단 SSR은 다음과 같다. (이미지에 DOM이라고 적었는데 document로 정정)

SSR

먼저 서버에서 document를 렌더링하고, JS 번들을 다운받아 hydration이 이루어진다.

그 후 data fetching을 한다. fetching 중에는 loading UI가 나타나고, fetching이 완료되면 나머지 content들이 paint된다.

 

네트워크탭에서는 다음과 같이 확인할 수 있다.

Data fetching을 렌더링 전에 수행하는 방법

그럼.. 만약 data fetching을 서버에서 미리 한 후에 컴포넌트를 만들 수 있지 않을까?

다음과 같이.

RSC

이러한 아키텍처는 사실 Next app-router이전 page-router에서 getServerSideProps나 getStaticProps로 구현할 수 있다.

export default function Homepage({ data }) {
  return (
    <>
      {data.map((item) => (
          <p>{item.description}</p>
      ))}
    </>
  );
}

export async function getServerSideProps() {
  const data = await db.query(link, 'SELECT * FROM products');
  return {
    props: { data },
  };
}

위 코드에서 getServerSideProps는 클라이언트에서 작동하지 않기 때문에 JS bundle에 포함되지 않는다.

 

그러나 이러한 방법은 

  1. 최상단 경로에서만 작동한다. 모든 depth에서 getServerSideProps를 이용하는것은 곤란하다.
  2. Next.js, Getsby, Remix등 data fetching을 server에서 미리 하는 방식이 다 다르고 표준이 없다.

Next app-router에서 실행되는 React server component

Next app-router의 app 폴더에서 만들어지는 컴포넌트는 기본으로 RSC이다.

만약 미리 data fetching을 하고 싶다면 getServerSideProps를 이용하지 말고 비동기 컴포넌트를 작성하면 된다.

async function Homepage() {
  // fetch는 next에서 browser의 fetch를 본따서 만든 api이다.
  // https://nextjs.org/docs/app/api-reference/functions/fetch
  const data = await fetch('https://...',{ next : { revalidate:300 }});
  return (
    <>
      {data.map((item) => (
          <p key={item.title}>{item.description}</p>
      ))}
    </>
  );
}
export default Homepage;

 

RSC의 핵심은 리렌더링 되지 않고 UI 생성을 위해 서버에서 맨 처음 한번만 렌더링된다는 것이다.

 

때문에 useEffect, useState등의 훅을 RSC에서는 사용할 수 없다.

리액트 훅은 Client Component에서 사용할 수 있다.

React Client Component

React Client Component는 평소 리액트에서 사용하는 컴포넌트다.

app 폴더에서 생성되는 모든 컴포넌트는 RSC이기 때문에 react hook을 사용할 수 있는 client component를 만들고 싶으면 'use client'를 명시해주어야 한다.

'use client';

import React from 'react';

function Counter() {
  const [count, setCount] = React.useState(0);
  return (
    <button onClick={() => setCount(count + 1)}>
      Current value: {count}
    </button>
  );
}
export default Counter;

 

'use client' 를 명시하는 것은 이 파일이 클라이언트 구성요소이며 JS 번들에 포함되어야 함을 리액트에 알리는 방법이다.

 

Component Tree

https://velog.io/@timosean/Server-component-vs.-Client-Component

root(보통 app.tsx)에서 시작해서 트리구조로 컴포넌트들이 생성된다.

Next app-router에서는 이 컴포넌트 트리를 root부터 실행하며 직렬화된 json 형태로 재구성한다.

 

이때 client component는 next 서버에서 해석하지 않고 placeholder로 대신한 후 다음단계로 넘어간다.

 

그렇기 때문에 client component안에서는 server component를 사용하면 안된다.

next 서버에서 client component를 해석하지 않기 때문에, 그 안에 있는 server component도 해석하지 않게 된다.

 

Client Component 내부에 Server Componet를 작성해야 할 때

그렇다면 어떻게 작성해야 할까?

children을 이용해야 한다.

function ParentClientComponent({children}) {
	...
  return <div onChange={...}>{children}</div>;
}

function ChildServerComponent() {
	...
  return <div>server component</div>;
}

function ContainerServerComponent() {
  return <ParentClientComponent>
			<ChildServerComponent/>
	</ParentClientComponent>;
}

 

쉽게 생각하면, children으로 ChildServerComponent를 넣어주면 ParentClientComponent에 가려지지 않고, Next 서버에 함께 전달된다. 그래서 ContainerServerComponent를 해석할 때, ParentClientComponent의 children인 ChildServerComponent도 해석할 수 있다.

 

 


참고

https://velog.io/@2ast/React-%EC%84%9C%EB%B2%84-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8React-Server-Component%EC%97%90-%EB%8C%80%ED%95%9C-%EA%B3%A0%EC%B0%B0

 

Next) 서버 컴포넌트(React Server Component)에 대한 고찰

이번에 회사에서 신규 웹 프로젝트를 진행하기로 결정했는데, 정말 뜬금 없게도 앱 개발자인 내가 이 프로젝트를 리드하게 되었다. 사실 억지로 떠맡게 된 것은 아니고, 새로운 웹 기술 스택을

velog.io

https://velog.io/@timosean/Server-component-vs.-Client-Component

 

Server component vs. Client Component

Next.js 13버전을 사용하면서 Server Component와 Client Component의 존재에 대해서 알게 되었고, 대충 개념은 이해한 것 같지만 뭔가 애매해서 Next.js의 공식문서 등을 참고해서 다시 한국어를 섞어서 정리

velog.io

https://www.joshwcomeau.com/react/server-components/

 

Making Sense of React Server Components

This year, the React team unveiled something they've been quietly researching for years: an official way to run React components exclusively on the server. This is a significant paradigm shift, and it's caused a whole lot of confusion in the React communit

www.joshwcomeau.com

 

반응형