### 참고문헌
- React : [# React Server Components](https://react.dev/reference/rsc/server-components)
- Nextjs : [# Server Components](https://nextjs.org/docs/app/building-your-application/rendering/server-components)
## React Server Component(React 문서)
- React Server Component(이하 RSC)는 클라이언트와 SSR이 분리된 환경에서 빌드 직전 미리 렌더되는 컴포넌트이다.
- Server component는 빌드 직전 코딩된 템플릿을 이용하여 client side 코드를 자동 생성해내는 기능이라 봐야 할 듯 하다. SSR과는 완전 다른 개념이다.
- React 19버전부터 정식 지원되지만 Nextjs를 사용하면 RSC를 이용할 수 있다.
### Server가 없는 경우
- 일반 텍스트파일을 불러와 컴포넌트에 채워넣는 형식이 있을 것이다. 이런 경우는 서버가 없다고 봐야할 것이다.
- server component는 이러한 경우 빌드시 로직을 수행한 후 그 결과를 컴포넌트에 미리 지정된 위치에 변환해둔다.
- marked, sanitize-html 등의 라이브러리를 이용할 수 있다.
### Server가 있는 경우
- 백엔드 api를 콜하는 로직이 수행될 수 있다. 이러한 경우에도 Server가 없는 경우와 동일하게 동작한다.
- 빌드시 api 콜한 결과가 컴포넌트에 지정된 위치에 변환되어 들어가게 된다.
[!NOTE] SSR과 다를 바가 없는 것 같은데요.
여기까지만 내용을 본다면 SSR과 별반 다를게 없어 보인다. 다음의 두 가지를 더 살펴보자
[!NOTE] Server Component용 directive는 없습니다.
"use server"는 Server Action을 사용하기 위한 directive이다. directive가 없으면 Server Component로 동작한다.
### 상호작용성interactivity를 server component에 추가하기
- Notes 는 서버 컴포넌트이면 컴포넌트 내에서 useState를 사용하는 Expandable 컴포넌트를 import하고 있다.
```
// Server Component
import Expandable from './Expandable';
async function Notes() {
const notes = await db.notes.getAll();
return (
<div>
{notes.map(note => (
<Expandable key={note.id}>
<p note={note} />
</Expandable>
))}
</div>
)
}
```
- useState는 client 즉, 브라우저에서 동작하므로 sever component에서는 사용할 수 없는 기능이다. 따라서 "use client" directive를 추가하여 server component가 아님을 표시해주어야 한다.(기억하자. default는 server component이다.)
```
// Client Component
"use client"
export default function Expandable({children}) {
const [expanded, setExpanded] = useState(false);
return (
<div>
<button
onClick={() => setExpanded(!expanded)}
>
Toggle
</button>
{expanded && children}
</div>
)
}
```
- 빌드 결과
```
<head>
<!-- the bundle for Client Components -->
<script src="bundle.js" />
</head>
<body>
<div>
<Expandable key={1}>
<p>this is the first note</p>
</Expandable>
<Expandable key={2}>
<p>this is the second note</p>
</Expandable>
<!--...-->
</div>
</body>
```
### 비동기 처리하기
- async를 사용하면 `<Suspense>`를 사용하여 데이터가 로딩 중임을 표시할 수 있다.
```
// Server Component
import db from './database';
async function Page({id}) {
// Will suspend the Server Component.
const note = await db.notes.get(id);
// NOTE: not awaited, will start here and await on the client.
const commentsPromise = db.comments.get(note.id);
return (
<div>
{note}
<Suspense fallback={<p>Loading Comments...</p>}>
<Comments commentsPromise={commentsPromise} />
</Suspense>
</div>
);
}
```
- await 는 "use client"를 지원하지 않으므로 `use()`를 사용하였다.
```
// Client Component
"use client";
import {use} from 'react';
function Comments({commentsPromise}) {
// NOTE: this will resume the promise from the server.
// It will suspend until the data is available.
const comments = use(commentsPromise);
return comments.map(commment => <p>{comment}</p>);
}
```
## RSC (Nextjs 문서)
- RSC를 사용하면 서버에서 렌더링하고 선택적으로 캐시할 수 있는 UI를 작성할 수 있다.
- App Router를 사용하면 Server Component와 같은 최신의 기능을 사용할 수 있다. 스트리밍 및 부분 렌더링을 활성화하기 위해 경로 세그먼트별로 추가 분할되며 3가지 서버 렌더링 전략이 있다.
- Static Rendering
- Dynamic Rendering
- Streaming
### Server Rendering의 이점
- Data Fetching
- Security
- Caching
- Performance
- Initial Page Load and First Contentful Paint
- Search Engine Optimization and Social Network Shareablility
- Streaming
### Next.js에서 Server Component 사용하기
- 기본적으로 server component로 동작하므로 별다른 설정이 필요없지만 클라이언트 컴포넌트를 사용하려면 'use client' directive가 필요하다.
### Next.js에서 Sever Component가 렌더되는 방법
- React의 RSC api를 이용하여 렌더링을 조정한다.(React 문서 참고)
- 렌더링은 경로 세그먼트와 Suspense 경계를 기준으로 분할되어 동작한다.
- chunk파일은
- RSC payload 형태로 렌더링 하고 payload와 client component를 html로 최종 렌더링한다.
- 클라이언트에서
- 초기 로드시 html을 즉시 보여준다.
- payload는 클라이언트 및 서버 구성 요소 트리를 조정하고 DOM을 업데이트하는 데 사용된다.
- JavaScript 지침은 클라이언트 구성 요소를 하이드레이션하고 애플리케이션을 대화형으로 만드는 데 사용된다.
### Static Rendering 전략 (default)
- 정적 렌더링을 사용하면 경로가 빌드 시 렌더링되거나 데이터 재검증 후 백그라운드에서 렌더링된다
- 정적 렌더링은 경로에 사용자에게 개인화되지 않은 데이터가 있고 정적 블로그 게시물이나 제품 페이지와 같이 빌드 시 알 수 있는 데이터가 있는 경우 유용하다
### Dynamic Rendering 전략
- 동적 렌더링을 사용하면 request마다 각 사용자에 대한 경로가 렌더링됩니다
- 동적 렌더링은 경로에 사용자에게 맞춤화된 데이터가 있거나 쿠키나 URL의 검색 매개변수와 같이 요청 시에만 알 수 있는 정보가 있는 경우 유용하다
- Nextjs는 동적렌터링을 알아서 처리해주지만 특정 데이터를 캐시하거나 재검증할 시기를 선택하고 UI의 일부를 스트리밍하도록 선택할 수도 있습니다.
- 동적 기능은 사용자 쿠키, 현재 요청 헤더 또는 URL의 검색 매개변수와 같이 요청 시에만 알 수 있는 정보에 의존한다
- cookies()
- headers()
- searchParams
### Streaming 전략
- 스트리밍을 사용하면 서버에서 UI를 점진적으로 렌더링할 수 있다. 작업은 여러 단위로 분할되어 클라이언트로 스트리밍되므로 사용자는 전체 콘텐츠의 렌더링이 완료되기 전에 페이지의 일부를 즉시 볼 수 있다.
- App router는 기본적으로 streaming 전략을 사용한다.
- React Suspense, loading.js을 사용하여 경로 세그먼트 스트리밍을 시작할 수 있다.
댓글
댓글 쓰기