Server Component vs Client Component


✨ Server Component vs Client Component

👉🏻 Rendering

  • jsx로 작성된 React component를 동적으로 화면 UI를 생성하고 업데이트 하는 과정

👉🏻 CSR (Client Side Rendering)

  • 모든 HTML, CSS 및 JavaScript 파일이 브라우저로 다운로드되어 클라이언트 측에서 UI를 동적으로 생성.
  • 초기 로딩 속도를 희생하고, 동적으로 콘텐츠를 업데이트하고 사용자 경험을 향상시키는 데 중점을 둠.

👉🏻 SSR (Server Side Rendering)

  • 서버 측에서 UI를 생성하는 방법. SSR에서는 서버에서 초기 HTML을 렌더링한 후에 이를 클라이언트로 전송하여 화면을 보여준다.
  • 초기 로딩 속도를 개선하고 SEO를 향상시키는 장점이 있으나, 서버 부하와 성능 이슈를 고려해야 한다.

React 18, Next.js 13부터 Server Component가 도입, 지원된다.

server component, client component 두 가지 형식으로 컴포넌트를 만들 수 있다.

✅ Server Component

  • next.js 에서는 /app 하위에 컴포넌트를 만들면, 디폴트로 server component이다.
  • server단에서 렌더링 되므로, client단의 코드는 사용이 불가능하다.
    • event listener (onClick, onChange 등)
    • React Hooks (useState, useEffect 등)
    • Browser API (webStorage 등)
  • server component는 client component를 포함할 수 있다.
  • 불필요한 dependency를 client에 전송할 필요가 없다.

✅ Client Component

  • 컴포넌트 최상단에 'use client' 를 추가해주면 된다.
  • client단 에서만 rendering 되는게 아닌, backend에서 정적 HTML로 render되고, frontend에서 hydrate 및 interactive 된다.

hydration: 정적 html을 로드하고나서, js, react를 적용해 interactive한 요소들로 채워지는 과정

Next.js 공식문서에서 권고하는 server component를 사용해야하는 경우

  • Fetch data
  • Access Backend Resources(directly)
  • Keep sensitive information on the server (access tokens, API keys, etc)
  • Keep large dependencies on the server / Reduce client-side JavaScript

✨ Client Component에 포함되는 자식 컴포넌트들은 모두 Client Component 일까?

정답부터 말하자면 ❌틀렸다❌

🔴 client component 내부에서 server component를 import 할 수 없다.

1'use client'
2 
3// You cannot import a Server Component into a Client Component.
4import ServerComponent from './Server-Component'
5 
6export default function ClientComponent({
7  children,
8}: {
9  children: React.ReactNode
10}) {
11  const [count, setCount] = useState(0)
12 
13  return (
14    <>
15      <button onClick={() => setCount(count + 1)}>{count}</button>
16 
17      <ServerComponent />
18    </>
19  )
20}

🟢 client component에 chidren prop으로 전달되는 server component는 여전히 server component이다.

1'use client'
2 
3import { useState } from 'react'
4 
5export default function ClientComponent({
6  children,
7}: {
8  children: React.ReactNode
9}) {
10  const [count, setCount] = useState(0)
11 
12  return (
13    <>
14      <button onClick={() => setCount(count + 1)}>{count}</button>
15      {children}
16    </>
17  )
18}
1// This pattern works:
2// You can pass a Server Component as a child or prop of a
3// Client Component.
4import ClientComponent from './client-component'
5import ServerComponent from './server-component'
6 
7// Pages in Next.js are Server Components by default
8export default function Page() {
9  return (
10    <ClientComponent>
11      <ServerComponent />
12    </ClientComponent>
13  )
14}

이 경우 server component와 client component는 decoupled 되고, 독립적으로 rendering 된다.

출처 : next.js 공식문서