Server Component vs Client Component

hyeryeonยท2024๋…„ 6์›” 17์ผ
post-thumbnail

๐ŸŽ† Server Component

์„œ๋ฒ„์—์„œ HTML์„ ๋ Œ๋”๋งํ•˜์—ฌ ๋ธŒ๋ผ์šฐ์ €์— ์‘๋‹ตํ•œ๋‹ค.
Hydration ๊ณผ์ •์€ ์—†๋‹ค.

๐ŸŽ† Client Component

์„œ๋ฒ„์—์„œ ๊ธฐ๋ณธ์ ์ธ HTML์€ ๋ Œ๋”๋”ฉํ•˜์—ฌ ๋ธŒ๋ผ์šฐ์ €์— ์‘๋‹ตํ•œ๋‹ค.
Hydration(JS Interactivity)๋งŒ ๋ธŒ๋ผ์šฐ์ €์—์„œ ์ด๋ฃจ์–ด์ง„๋‹ค.

  • ๊ธฐ๋ณธ์ ์ธ HTML์ž์ฒด๋Š” ๋ชจ๋‘ ์„œ๋ฒ„์—์„œ ๋ Œ๋”๋ง๋œ๋‹ค.
    ๋‹จ, Client Component์˜ ๊ฒฝ์šฐ์—๋งŒ ๋ธŒ๋ผ์šฐ์ €์—์„œ Hydaration ๊ณผ์ •์ด ์ง„ํ–‰๋œ๋‹ค.

Event Listener(ํด๋ฆญ ์ด๋ฒคํŠธ ๋“ฑ), Browser API(web storage ๋“ฑ), React Hooks(useState, useEffect ๋“ฑ) ๋“ฑ์€ ๋ธŒ๋ผ์šฐ์ €์—์„œ๋งŒ ์ž‘๋™ํ•˜๋Š” ํด๋ผ์ด์–ธํŠธ ๋‹จ JS์ฝ”๋“œ์ด๋ฉฐ, ๋ธŒ๋ผ์šฐ์ €์—์„œ Hydration ๊ณผ์ •์„ ๊ฑฐ์น˜๋Š” Client Component์—์„œ๋งŒ ์ •์˜๋  ์ˆ˜ ์žˆ๋‹ค.

๋”ฐ๋ผ์„œ, Server Component์—์„œ๋Š” ์‚ฌ์šฉ์ด ๋ถˆ๊ฐ€ํ•˜๋‹ค.

๋ฐ์ดํ„ฐ ํŽ˜์น˜ ๊ด€์ ์—์„œ CSR๊ณผ SSR์˜ ์ฐจ์ด์ 

๋ฐ์ดํ„ฐ ํŽ˜์นญ์„ ํ•˜๊ธฐ ์œ„ํ•ด์„ 
-> ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด์—ฌ์ฃผ๋Š” ํด๋ผ์ด์–ธํŠธ ์‚ฌ์ด๋“œ์˜ ๋ฆฌ์•กํŠธ ์•ฑ๊ณผ ์„œ๋ฒ„ ์‚ฌ์ด๋“œ REST API ์•ฑ์ด ํ•„์š”

๋ฆฌ์•กํŠธ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ํŽ˜์น˜ํ•˜๊ธฐ ์œ„ํ•ด์„ 

  • useEffect ํ›…, React-Query, SWR ๋“ฑ์„ ์‚ฌ์šฉํ•ด ๋ฐฑ์—”๋“œ๋กœ ๋„คํŠธ์›Œํฌ ์š”์ฒญ
    => ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ง‘์–ด ๋„คํŠธ์›Œํฌ๋ฅผ ํ†ตํ•ด ์ „๋‹ฌ

์œ„๋Š” ํด๋ผ์ด์–ธํŠธ ์‚ฌ์ด๋“œ ๋ Œ๋”๋ง CSR ์˜ ํŒจํ„ด์ด๋‹ค.

  • ํด๋ผ์ด์–ธํŠธ๊ฐ€ HTML ํŒŒ์ผ์„ ๋ฐ›๋Š” ์‹œ์ ์—์„œ ์‹œ์ž‘
    ์ด ํŒŒ์ผ์€ ์–ด๋–ค ์ปจํ…์ธ ๋„ ํฌํ•จํ•˜์ง€ ์•Š์œผ๋ฉฐ, ํ•˜๋‚˜ ํ˜น์€ ๊ทธ ์ด์ƒ์˜ ์Šคํฌ๋ฆฝํŠธ ํƒœ๊ทธ๋ฅผ ๊ฐ–๋Š”๋‹ค.

-> ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๋‹ค์šด๋กœ๋“œ๋˜๊ณ  ํŒŒ์‹ฑ ๋˜๋ฉด
-> ๋ฆฌ์•กํŠธ ์•ฑ์ด ์‹คํ–‰๋˜๊ณ 
-> ๋” ๋…ธ๋“œ๋ฅผ ์ƒ์„ฑํ•ด UI๋ฅผ ์ฑ„์šด๋‹ค.

์ดˆ๊ธฐ์—๋Š”, ์œ ์ €๋Š” ์–ด๋– ํ•œ ์‹ค์ œ ๋ฐ์ดํ„ฐ๋„ ๊ฐ–์ง€ ๋ชปํ•˜๊ณ ,

  • ๋กœ๋”ฉ ์ƒํƒœ์™€ ์˜ค์ง ์•ฑ์˜ ์‰˜(๋ ˆ์ด์•„์›ƒ)๋งŒ ๋ Œ๋”ํ•˜๋Š”๋ฐ

์œ ์ €๋Š” ๋„คํŠธ์›Œํฌ ์š”์ฒญ์ด ์™„๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ๋กœ๋”ฉ ์ƒํƒœ๋ฅผ ๋ณด๊ฒŒ ๋˜๊ณ , ๋ฆฌ๋ Œ๋”๋ฅผ ํ†ตํ•ด ๋กœ๋”ฉ UI(์Šคํ”ผ๋„ˆ, ์Šค์ผˆ๋ ˆํ†ค ๋“ฑ)๊ฐ€ ์‹ค์ œ ์ปจํ…์ธ ๋กœ ๋Œ€์ฒด๋œ๋‹ค.

์œ„๋Š” SSR์„ ์‚ฌ์šฉํ•œ ํŽ˜์น˜ ํŒจํ„ด

ํด๋ผ์ด์–ธํŠธ ์‚ฌ์ด๋“œ์™€ ๋‹ค๋ฅธ ์ ์€

  • ์ดˆ๊ธฐ ๋ Œ๋”๋ฅผ ์„œ๋ฒ„์—์„œ ํ•œ๋‹ค
    => ์œ ์ €๊ฐ€ ํ…… ๋นˆ HTML์„ ๋ฐ›์ง€ ์•Š๋Š”๋‹ค๋Š” ๊ฒƒ

์ดˆ๊ธฐ์— ์„œ๋ฒ„์—์„œ ๋ Œ๋” ํ•˜๊ฒŒ ๋˜๋ฉด, ์ข€ ๋” ๋น ๋ฅด๊ฒŒ ์‰˜์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.
์œ ์ €๋Š” ํ…… ๋นˆ ํŽ˜์ด์ง€๋ณด๋‹ค ์ƒํ™ฉ์ด ์ง„ํ–‰๋œ๋‹ค๊ณ  ๋А๋ผ๊ธฐ์— -> ๋กœ๋”ฉ ๊ฒฝํ—˜์ด ์ข€ ๋” ๋น ๋ฅด๊ฒŒ ๋А๊ปด์งˆ ์ˆ˜ ์žˆ๋‹ค.

ํ•˜์ง€๋งŒ ์œ„์™€ ๊ฐ™์€ ํ๋ฆ„์€ ๋ญ”๊ฐ€ ์ด์ƒํ•จ

ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„๋ฅผ ์™•๋ณตํ•˜์ง€ ์•Š๊ณ ,
๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ฟผ๋ฆฌ๋ฅผ ์ดˆ๊ธฐ์— ์„œ๋ฒ„์—์„œ ์š”์ฒญํ•œ๋‹ค๋ฉด
์ปจํ…์ธ ๊ฐ€ ์˜จ์ „ํžˆ ์ฑ„์›Œ์ง„ UI๋ฅผ ์ฆ‰์‹œ ์œ ์ €์—๊ฒŒ ๋ณด๋‚ผ ์ˆ˜ ์žˆ์„ ๊ฒƒ์ธ๋ฐ...

์ด๋•Œ, ๋ฆฌ์•กํŠธ ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ด๋Ÿฐ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค.

๋ฆฌ์•กํŠธ ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ

๋ฆฌ์•กํŠธ ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด

  • ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์—์„œ ๋ฐ์ดํ„ฐ ํŽ˜์น˜์™€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ฟผ๋ฆฌ๋ฅผ ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค€๋‹ค.

๋ฐ์ดํ„ฐ ํŽ˜์น˜ ๋กœ์ง ์ž์ฒด๋ฅผ ์„œ๋ฒ„๋กœ ์˜ฎ๊ธธ ์ˆ˜ ์žˆ๊ธฐ์—, ํด๋ผ์ด์–ธํŠธ์—์„œ๋Š” ๋ฐ์ดํ„ฐ์™€ ํ•จ๊ป˜ ๊ตฌ์„ฑ๋œ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ฐ›๋Š”๋‹ค.

๋ฆฌ์•กํŠธ ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์œ„์™€ ๊ฐ™์ด ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„ ์™•๋ณต ์—†์ด๋„ ๋ฐ์ดํ„ฐ์˜ ํ๋ฆ„์„ ๋งŒ๋“ค์–ด๋ƒ„
=> ์œ ์ €๋Š” ๋กœ๋”ฉ UI ์—†์ด ๋ฐ”๋กœ ์ปจํ…์ธ ๋ฅผ ํŽ˜์ด์ง€์—์„œ ๋ณผ ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹น

Server Component์™€ Client Component ์ •์˜ ๋ฐฉ๋ฒ• ๋ฐ ํŠน์ง•

๐Ÿ“Œ Server Componentย 

Next.js์—์„œ๋Š” /app ๋””๋ ‰ํ„ฐ๋ฆฌ ๋‚ด๋ถ€์— ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋งŒ๋“ค๋ฉด, ๋””ํดํŠธ๋กœ Server Component๊ฐ€ ๋œ๋‹ค.
๋”ฐ๋ผ์„œ Server Component๋กœ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด ๋ณ„๋„์˜ ์ž‘์—…์„ ํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค.

export default function Home(){
  return (
    <main>
      <h1>Home: Server Component</h1>
    </main>
  );
}

๋ชจ๋“  ์ปดํฌ๋„ŒํŠธ๋Š” Server Component๊ฐ€ ๋””ํดํŠธ.
์„œ๋ฒ„ ๋‹จ์—์„œ ๋ Œ๋”๋ง ๋˜๋ฏ€๋กœ, ๋ธŒ๋ผ์šฐ์ € ํ™˜๊ฒฝ์˜ ์ฝ”๋“œ๋Š” ์‚ฌ์šฉ ๋ถˆ๊ฐ€:

  • Event Listener(onClick ๋“ฑ) ์‚ฌ์šฉ ๋ถˆ๊ฐ€
  • React Hooks(useState ๋“ฑ) ์‚ฌ์šฉ ๋ถˆ๊ฐ€
  • Browser API(webStorage ๋“ฑ) ์‚ฌ์šฉ ๋ถˆ๊ฐ€

Server Component๋Š” Client Compoent ํฌํ•จ ๊ฐ€๋Šฅ(๋ฐ˜๋Œ€๋Š” ๋ถˆ๊ฐ€)
Server Component๋Š” async ํ•จ์ˆ˜๋กœ ์ •์˜ ๊ฐ€๋Šฅ

๋”ฐ๋ผ์„œ ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์—์„œ ๋ฐ”๋กœ await fetch() ํ˜ธ์ถœ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

export default async function Home() {
  const res = await fetch("https://jsonplaceholder.typicode.com/todos/1");
  const data = await res.json();

  return (
    <main>
      <h1>Home</h1>
      <p>{data.title}</p>
    </main>
  );
}

Server Component๋Š” ์„œ๋ฒ„์—์„œ ๋ Œ๋”๋ง ๋˜๋ฏ€๋กœ, ์•„๋ž˜์™€ ๊ฐ™์€ ์žฅ์ ์ด ์žˆ๋‹ค.

  • ๋ถˆํ•„์š”ํ•œ dependency๋ฅผ ํด๋ผ์ด์–ธํŠธ์— ์ „์†กํ•  ํ•„์š”๊ฐ€ ์—†๊ณ ,
  • Database ์ ‘๊ทผ ๋ฐ fetch ์†๋„๊ฐ€ ๊ฐœ์„ ๋  ์ˆ˜ ์žˆ์œผ๋ฉฐ,
  • ๋ณด์•ˆ ์ •๋ณด๋„ ์ข€๋” ์•ˆ์ „ํ•˜๊ฒŒ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.

๐Ÿ“ŒClient Componentย 

Client Component๋ฅผ ์ •์˜ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์ปดํฌ๋„ŒํŠธ ํŒŒ์ผ ์ตœ์ƒ๋‹จ์— "use client"๋ฅผ ์ถ”๊ฐ€ํ•ด ์ฃผ๋ฉด ๋œ๋‹ค.

"use client";

import { useState } from "react";

export default function Counter() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount((prev) => prev + 1)}>Click me</button>
    </div>
  );
}
 

์ปดํฌ๋„ŒํŠธ ํŒŒ์ผ ์ตœ์ƒ๋‹จ์— "use client"๋ฅผ ๋ถ™์—ฌ์ฃผ๋ฉด Client Component๊ฐ€ ๋œ๋‹ค.
ํด๋ผ์ด์–ธํŠธ(๋ธŒ๋ผ์šฐ์ €) ๋‹จ์—์„œ ๋ Œ๋”๋ง ๋˜๋ฏ€๋กœ, ๋ธŒ๋ผ์šฐ์ € ํ™˜๊ฒฝ์˜ ์ฝ”๋“œ ์‚ฌ์šฉ ๊ฐ€๋Šฅ:

  • Event Listener(onClick ๋“ฑ) ์‚ฌ์šฉ ๊ฐ€๋Šฅ
  • React Hooks(useState ๋“ฑ) ์‚ฌ์šฉ ๊ฐ€๋Šฅ
  • Browser API(webStorage ๋“ฑ) ์‚ฌ์šฉ ๊ฐ€๋Šฅ

Client Component์— ๋‚ด๋ถ€์— ํฌํ•จ๋˜๋Š” ์ž์‹ ์ปดํฌ๋„ŒํŠธ๋“ค๋„ ๋ชจ๋‘ ์ž๋™์œผ๋กœ Client Component๊ฐ€ ๋œ๋‹ค.
Client Componemt๋Š” Server Component๋ฅผ ํฌํ•จํ•  ์ˆ˜ ์—†๋‹ค. (๋ฐ˜๋Œ€๋งŒ ๊ฐ€๋Šฅ)

Server Component ์™€ Client Component์˜ ์‚ฌ์šฉ ๋ฐ ๋ฐฐ์น˜ ๋ฐฉ๋ฒ•

๊ธฐ๋ณธ์ ์œผ๋กœ ๋ชจ๋“  ์ปดํฌ๋„ŒํŠธ๋ฅผ Server Component๋กœ ๋งŒ๋“ค๊ณ ,
ํด๋ผ์ด์–ธํŠธ ๋‹จ์˜ ์œ ์ € ์ธํ„ฐ๋ž™์…˜ ์ฒ˜๋ฆฌ๋‚˜ React hooks ์‚ฌ์šฉ์ด ํ•„์š”ํ•  ๋•Œ๋งŒ Client Component๋ฅผ ์ถ”๊ฐ€ํ•ด์ฃผ๋ฉด ์ข‹๋‹ค.


1. Client Component ์‚ฌ์šฉ์ด ํ•„์š”ํ•  ๋•Œ:

  • ์ธํ„ฐ๋ž™ํ‹ฐ๋น„ํ‹ฐ ๋ฐ Event Listener ์‚ฌ์šฉ์ด ํ•„์š”ํ•  ๋•Œ
  • React Hooks (useState, useEffect ๋“ฑ) ์‚ฌ์šฉ์ด ํ•„์š”ํ•  ๋•Œ
  • Browser ๋‹จ์˜ API (web storage ๋“ฑ) ์‚ฌ์šฉ์ด ํ•„์š”ํ•  ๋•Œ

2. Server Component ์‚ฌ์šฉ์ด ํ•„์š”ํ•  ๋•Œ:

  • ์œ„์˜ Client Component ์‚ฌ์šฉ์ด ๋ถˆ๊ฐ€ํ”ผํ•œ ๊ฒฝ์šฐ๋ฅผ ์ œ์™ธํ•œ ๋ชจ๋“  ๊ฒฝ์šฐ!

๊ณต์‹ ๋ฌธ์„œ์—์„œ๋Š” ํŠนํžˆ ์•„๋ž˜์˜ ๊ฒฝ์šฐ 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

  • ์ปจํ…์ธ  ๋ฐย ๋‹จ์ˆœ ๋งํฌ(aํƒœ๊ทธ)ย ๋“ฑ์„ ๋‹ด๋Š” ์ปจํ…Œ์ด๋„ˆ์ผ ๋ฟ์ด๋‹ค.
  • ์œ ์ € ์ธํ„ฐ๋ž™์…˜์€ ์—†๊ฑฐ๋‚˜ ๋ถˆํ•„์š”ํ•˜๋‹ค.
  • Server Component๋กœ ์ •์˜ํ•œ๋‹ค.

Search, Button ์ปดํฌ๋„ŒํŠธ:

  • ๊ฒ€์ƒ‰์ฐฝ ์ž…๋ ฅ, ๋ฒ„ํŠผ ํด๋ฆญ ์ •๋„๋งŒ ์œ ์ € ์ธํ„ฐ๋ž™์…˜์ด ๋ฐœ์ƒํ•˜๋Š” ์˜์—ญ์ด๋‹ค.
  • change, click ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ ๋ฐ useState๋“ฑ์˜ React Hook์ด ํ•„์š”ํ•˜๋‹ค.
  • Client Component๋กœ ์ •์˜ํ•œ๋‹ค.

๋”ฐ๋ผ์„œ, Navbar, Sidebar, Main์ปดํฌ๋„ŒํŠธ๋Š” Server Component๋กœ ์ •์˜ํ•˜๊ณ ,
Search, Button ์ปดํฌ๋„ŒํŠธ๋Š” Client Component๋กœ ์ •์˜ํ•˜์—ฌ Main ์•ˆ์— ํฌํ•จ์‹œํ‚ค๋ฉด ๋œ๋‹ค.

Server Component๋Š” Client Component๋ฅผ ํฌํ•จํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

  • ์‚ฌ์šฉ์ž ์ƒํ˜ธ์ž‘์šฉ์ด ์ž˜ ์ผ์–ด๋‚˜์ง€ ์•Š๋Š” Navbar, Side bar ๋“ฑ์ด ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ ์— ํ•ด๋‹นํ•˜๊ณ ,
  • onChange ์ด๋ฒคํŠธ์™€ ๋”๋ถˆ์–ด useState ๋ฅผ ์‚ฌ์šฉํ•ด์•ผํ•˜๋Š” ๊ฒ€์ƒ‰์ฐฝ, ํด๋ฆญ ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๋ฒ„ํŠผ ๋“ฑ์ด ํด๋ผ์ด์–ธํŠธ ์ปดํฌ๋„ŒํŠธ ์— ํ•ด๋‹นํ•œ๋‹ค.

์ถœ์ฒ˜: https://curryyou.tistory.com/539 [์นด๋ ˆ์œ :ํ‹ฐ์Šคํ† ๋ฆฌ]https://www.yujiseok.blog/post/react-server-components

0๊ฐœ์˜ ๋Œ“๊ธ€