๐ก 15. ์๋ฒ๋ก ํ๊ทํ๋ค: RSC์ next.js ๋ธ๋ฆฟ์ง
๐ ๊ฐ์
React ์ํ๊ณ์ ํจ๋ฌ๋ค์ ๋ณํ์ธ ์๋ฒ ์ปดํฌ๋ํธ(RSC)์ ์๋ฏธ์, use client ์ง์์ด๊ฐ ํด๋ผ์ด์ธํธ์ ์๋ฒ๋ฅผ ๋๋๋ ๊ฒฝ๊ณ์ (Boundary) ์ญํ ์ ์ด๋ป๊ฒ ์ํํ๋์ง ์ด์ ๋ฆฌํฉ๋๋ค.
๐ฏ ์ด ์น์ ์ ์ฝ๊ณ ๋๋ฉด:
- React Server Components(RSC)๊ฐ ๊ธฐ์กด์ SSR(Server-Side Rendering)๊ณผ ์์ ํ ๋ค๋ฅธ ๋ง๋ฒ์ด๋ผ๋ ์ ์ ์ดํดํ๋ค.
use client์ต์๋จ ์ง์์ด์ ์ง์ง ์๋ฏธ๊ฐ '๋ธ๋ผ์ฐ์ ์ ์ฉ ์คํ'์ด ์๋๋ผ ๋จ์ ์ ๊ฒฝ๊ณ์ (Network Boundary) ์์ ์๋ฒฝํ ๊ทธ๋ ค๋ผ ์ ์๋ค.- ์ปดํฌ๋ํธ์ ์ฑ ์ ์์ฌ์ง(์๋ฒ๋, ํด๋ผ์ด์ธํธ๋)๋ฅผ ๋ช ํํ ํ๋ณํ๋ ์๊ฐ์ ๊ฐ๋๋ค. (๋๋จ์ ๋ง๋ฌด๋ฆฌ)
๐ ๋ชฉ์ฐจ
- ๐ค ์ ์์์ผ ํ๋๊ฐ:
JS ๋ฒ๋ค๋ค์ด์ดํธ์ ์ ์ - ๐๏ธ ๋น์ ๋ก ๋จผ์ ์ดํดํ๊ธฐ
- ๐งฉ ๊ทน์ ์ฒด๋: RSC์
use client์ ์ง์ง ์๋ฌด - ๐ ๋๋์ด, ๋๋จ์ ์ด์ ๋ฆฌ
- ๐ ๋ง๋ฌด๋ฆฌ(์ํ๋ก๊ทธ) ํด์ฆ
๐ ์ด ๋ฌธ์๋ฅผ ์ฝ๊ธฐ ์ ์
โฑ๏ธ ์์ ์ฝ๊ธฐ ์๊ฐ: 10๋ถ / ํต์ฌ ํํธ: 6๋ถ
๐บ๏ธ ์ด ๋ฌธ์์ ๋ฐฐ๊ฒฝ ์ธ๊ณ๊ด: '์์๋ค ์ปค๋ฎค๋ํฐ'
- ์์ฒ (์ ์
):"์ ๋ฐฐ๋! Next.js 13 ๋ฒ์ ๋ถํฐ ํ์ด์ง ์๋จ์
use client์ฐ๋ผ๊ณ ๊ณ์ ์๋ฌ๊ฐ ๋ ์ ๋ต๋ตํด์. ๊ทธ๋ฅ_app.tsx์ ค ์์ ํ ๋ฒ ์ ์ด๋๋ฉด ์ ๋ถ ํด๋ผ์ด์ธํธ๋ก ํธํ๊ฒ ์ธ ์ ์๋ ๊ฑฐ ์๋๊ฐ์?" - ์ํธ(๋ฆฌ๋):"์์ฒ ๋. ๊ทธ๊ฑธ ์ ๋ถ ํด๋ผ์ด์ธํธ๋ก ๋๋ ค๋ฒ๋ฆด ๊ฑฐ๋ฉด ๋ฌด๊ฑฐ์ด ๋ฒ๋ค ํ์ผ์ ์ ์ ๋ธ๋ผ์ฐ์ ๋ก ๋ชจ๋ ๋ณด๋ด๊ฒ ๋ค๋ ๋ป์ ๋๋ค. ์ฐ๋ฆฌ๋ ์ง๊ธ 10๋ ๋ง์ ์ผ์ด๋ 'ํ๋ก ํธ์๋์ ๋๋ฅ ์ด๋(์๋ฒ์ฌ์ด๋ ์ํ ๊ทํ)' ์ ํ๊ฐ์ด๋ฐ ์ ์์ต๋๋ค."
๐ค ์ ์์์ผ ํ๋๊ฐ: JS ๋ฒ๋ค ๋ค์ด์ดํธ์ ์ ์
์ง๊ธ๊น์ง 01๊ฐ๋ถํฐ 14๊ฐ๊น์ง ๋ฐฐ์ด ๋ชจ๋ ๋ด์ฉ์ ๋จ์๋ฅผ ๋ฌ๊ณ ์์์ต๋๋ค.
"์ด ์ฝ๋๋ ๋ธ๋ผ์ฐ์ (ํฌ๋กฌ, ์ฌํ๋ฆฌ) ์์์ ์คํ๋๋ค."
ํ์ง๋ง ์๊ฐํด๋ณด์ธ์. ๋น์ ์ด ๊ฑฐ๋ํ ๋ ์จ ๋ผ์ด๋ธ๋ฌ๋ฆฌ moment.js (ํฌ๊ธฐ: 300KB)๋ Markdown ๋ ๋๋ง ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์จ์ ํ๋ฉด์ ๊ทธ๋ฆฐ๋ค๊ณ ์นฉ์๋ค.
๊ธฐ์กด์ React ์ํ๊ณ(CSR, ์ ํต์ SPA)์์๋ ์ฌ์ฉ์๊ฐ ๋ชจ๋ฐ์ผ ํ๊ฒฝ์์ ๋ด ์ฌ์ดํธ์ ๋ค์ด์ค์๋ง์ ๊ทธ ๋ฌด๊ฑฐ์ด ์ฝ๋ฉ ํ์ผ 300KB๋ฅผ ๋ชฝ๋
๋ค์ด๋ก๋ํด์ผ ๋น๋ก์ ์คํ์ด ์์๋์์ต๋๋ค. "๋ก๋ฉ ์ค..." ์คํผ๋๊ฐ ๋ฌดํ์ ๋ฑ
๊ธ๋ฑ
๊ธ ๋๋๋ค.
๐ค ์ ๊น, ๋จผ์ ์๊ฐํด๋ด
์ด๊ฑฐ ์ฐ๋ฆฌ ์ปดํจํฐ(์๋ฒ) ์ฑ๋ฅ ์ข์๋ฐ... ์ฐ๋ฆฌ๊ฐ ์๋ฒ์์ ์ ๋ฌด๊ฑฐ์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค ๋๋ ค์ HTML๋ง ์์๊ฒ ๊น์๋ธ ๋ค์ ๊ฒฐ๊ณผ๋ฌผ ํ ์คํธ(๋ฌธ์์ด)๋ง ํฐ์ผ๋ก ๋ณด๋ด์ฃผ๋ฉด ์ ์ ๋ฐ์ดํฐ(MB)๋ ์๋ผ๊ณ ๋ก๋ฉ๋ 0.1์ด ์ปท ์๋๊น?
์. ๊ทธ ์๊ฐ์์ ์ถ๋ฐํ ๊ถ๊ทน์ ์งํ๊ฐ ๋ฐ๋ก React Server Components (RSC) ์ ๋๋ค.
๐๏ธ ๋น์ ๋ก ๋จผ์ ์ดํดํ๊ธฐ
๐ง 5์ด์๊ฒ ์ค๋ช ํ๋ค๋ฉด?
๊ณผ๊ฑฐ (Client Component ์์ฃผ ์๋):
์๋น ์๋ฆฌ์ฌ(์์ฒ )๊ฐ ์๋(๋ธ๋ผ์ฐ์ )์๊ฒ ์๊ณ ๊ธฐ, ์ผ์ฑ, ์นผ, ๋๋ง, ๊ฐ์ค๋ฒ๋(๊ฑฐ๋ํ JS ๋ฒ๋ค ์ฝ๋ ๋ฉ์ด๋ฆฌ)๋ฅผ ๋ฐ์ค ์ฑ๋ก ํ ์ด๋ธ์ ํ๊บผ๋ฒ์ ๊ฑด๋ค์ค.
โ์๋! ์ฌ๊ธฐ์๋ถํฐ๋ ์๋ ํด๋ํฐ์ด ์ง์ ๊ฐ์ค๋ฒ๋ ์ผ๊ณ (useEffect), ๋ค์ด๋ฒ์ ๋ ์จ ๋ฌผ์ด๋ณด๊ณ (fetch), ๊ณ ๊ธฐ ๊ตฌ์์ ํ๋ฒ๊ฑฐ ์กฐ๋ฆฝ(๋ ๋๋ง)ํด ๋์ธ์!โ -> ์ ์ ํฐ์ด ์์ฒญ ๋จ๊ฑฐ์์ง๊ณ ๋ก๋ฉ์ด ๊น.ํ์ฌ (์๋ฒ ์ปดํฌ๋ํธ, Server Components):
๊ฐ๋ ฅํ ์ฃผ๋ฐฉ(Node.js ์๋ฒ)์์ ์๋ฆฌ์ฌ(์ํธ)๊ฐ ์์ฒญ ๋น ๋ฅธ ์๋๋ก ๋ ์จ๋ ์์์ค๊ณ , ๊ณ ๊ธฐ๋ ๋ค ๊ตฝ๊ณ ๋งํฌ๋ค์ดํ์ฑ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ฒ๋ฆฌ๋ ๋ค ๋๋.
ํ ์ด๋ธ(์ ์ ํฐ)์๋ ๋ญ๋ง ๋ฐฐ๋ฌํด์ฃผ๋๋? ๋จ 0.01์ด ๋ง์ ์ด์๊ฒ ์์ฑ๋ ํ๋ฒ๊ฑฐ(์ ์ ์ธ HTML ๋ ์ด์์)๋ง ์ํ ์์ ์ฌ๋ฟํ ์ฌ๋ ค์ค.
์ ์ ๋ ํ์ผ ์ฉ๋์ ๊ฑฐ์ ์ ๋ฐ์๋ ํ๋ฉด์ ์ฆ๊ฐ(0์ด ๋ง์) ๋ณด๊ฒ ๋จ!
์ด ์์ฒญ๋ ํจ๋ฌ๋ค์ ๋๋ฌธ์ Next.js ๊ฐ์ ์ ๊ธฐ์ ์์์๋ ์ด์ "๋ชจ๋ ์ปดํฌ๋ํธ์ ๊ธฐ๋ณธ๊ฐ(Default)์ ๋ฌด์กฐ๊ฑด ์ฃผ๋ฐฉ(์๋ฒ ์ปดํฌ๋ํธ)์์ ๊ตฌ์์ง๋ค" ๋ก ๊ท์น์ด ์์ ํ ๋ค์งํ ๊ฒ์ ๋๋ค.
๐งฉ ๊ทน์ ์ฒด๋: RSC์ use client์ ์ง์ง ์๋ฌด
๊ทธ๋ผ ์์ฒ ์ด์ ์ง๋ฌธ์ผ๋ก ๋์๊ฐ ๋ด
์๋ค. ์ ์๊พธ ์๋ฌ๊ฐ ๋๊ณ use client๋ฅผ ๊ฐ์ ํ์๊น์?
์๋ฒ ์ฃผ๋ฐฉ์์ ์๋ฆฌ๋ฅผ ์๋ง ์ ๊ตฌ์์ ์คฌ์ด๋, "์๋์ด ์ง์ ๋ฒํผ์ ๋๋ฅผ ๋๋ง๋ค ๋ฐ์ํ๋ ๋ฐ์(onClick)" ์ด๋ "์๋์ ์ง๊ธ ํ์ฌ ๋ง์ฐ์ค ์์น(useState)" ๋ ์๋ฒ ์ฃผ๋ฐฉ์์ ์ ํฑ์ด ์๊ธฐ ๋๋ฌธ์ ๋๋ค!
โ 1. RSC์ ์ฒ ์น (์๋ฒ์ ์ํ )
๊ธฐ๋ณธ์ ์ผ๋ก ์๋ฌด๊ฒ๋ ์ ์ ์ผ๋ฉด ๋ชฝ๋ ์๋ฒ ์ปดํฌ๋ํธ ์ ๋๋ค.
// ๐ฏ ์ด๊ฑฐ์จ ์๋ฒ ์ปดํฌ๋ํธ (Next.js 13+ App Router ๊ธฐ์ค)
// ์ต์๋จ์ ์๋ฌด๊ฒ๋ ์๋ค. ๊ณ ๋ก ๋๋ ์๋ฒ์์ ๋น์ด์ ธ ๋ด๋ ค๊ฐ๋ค.
import fs from 'fs'; // ํ! ๋ฆฌ์กํธ ๋ด๋ถ์์ ๋์คํฌ ํ์ผ ์ฝ๊ธฐ๊ฐ ๊ฐ๋ฅํด์ง!
import HeavyMarkdownToHtml from 'markdown-heavy-lib'; // 300MB์ง๋ฆฌ ์ํํ ๋ฌด๊ฑฐ์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ!
// ํ! ์ปดํฌ๋ํธ ํจ์ ์์ async๊ฐ ๋ถ์ด? (useEffect ์์ด await๋ก API ์ง๋นต ์ฝ)
export default async function WeatherBoard() {
const dbData = await db.query("SELECT * FROM weather"); // DB ์ง์ ์ฐ๋ฅด๊ธฐ!
const htmlResult = HeavyMarkdownToHtml(dbData.content);
// ๐ฅ ์ค์ํ ํํ: ์์์ ์ฐ์ธ HeavyMarkdownToHtml ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์์ค์ฝ๋๋
// ์ ์ ์ ๋ธ๋ผ์ฐ์ ๋ก 1kb๋ ์ ์ก(๋ค์ด๋ก๋)๋์ง ์๋๋ค! ์ค์ง ๋ณํ๋ <div> ๊ฒฐ๊ณผ๋ฌผ๋ง ์ ์ก!
return <div>{htmlResult}</div>;
}์ด๊ฑด ๊ธฐ์กด CSR ๋ฆฌ์กํธ๋ก์ ๊ฐํ ์์๋ ๋ชปํ ์๋์ ์ธ ๋ฅ๋ ฅ์ ๋๋ค. ํ์ผ ํฌ๊ธฐ ์ ๋ก, ๋ก๋ฉ ์ ๋ก.
โ
2. use client ์ ์ธ์ ์ง์ง ๋ป (๋๊ฐ๊ต ๋ด๋ฆฌ๊ธฐ)
๊ทธ๋ฐ๋ฐ ์ ๊ฒ์ํ ์์ "๐ ์ข์์ ๋ฒํผ"์ ๋ฌ์์ผ ํฉ๋๋ค. ํด๋ฆญํ๋ฉด ์ซ์๊ฐ ์ฌ๋ผ๊ฐ๋ ์ํ(useState)๊ฐ ํ์ํ์ฃ .
์๋ฒ ์ปดํฌ๋ํธ ์์์ export default function WeatherBoard ์์ onClick= ์ด๋ด ๊ฑธ ์ฐ๋ฉด ๋ค์๊ณผ ๊ฐ์ ์๋ฌ๊ฐ ๋นก! ํฐ์ง๋๋ค.
"Error: Event handlers cannot be passed to Client Component props. (์ด๋ด! ์ฌ๊ธด ์๋ฒ ์ฃผ๋ฐฉ์ด๋ผ๊ณ ! ์ ์ ๋ง์ฐ์ค ํด๋ฆญ ์ด๋ฒคํธ๋ฅผ ๋ด๊ฐ ์ฌ๊ธฐ์ ์ด๋ป๊ฒ ๊ฐ์งํด!)"
์ด๋ด ๋ ์ฐ๋ ๊ฒ์ด ๋ฐ๋ก use client ์
๋๋ค.
use client๋ "๋ฆฌ์กํธ ์์ง๋, ์ ํ์ผ๋ถํฐ๋ ์ฃผ๋ฐฉ(์๋ฒ) ๋ฐ์ผ๋ก ๋ณด๋ด์, ์ ์ ํฐ(ํด๋ผ์ด์ธํธ) ์์์ ์ง์ ์๋ฐ์คํฌ๋ฆฝํธ๋ก ์คํ๋๊ฒ ๋ฒ๋ค์ ํฌ์ฅ ๋ฐฐ๋ฌํด์ฃผ์ธ์!" ๋ผ๋ ๋คํธ์ํฌ ๊ฒฝ๊ณ์ (Boundary) ์ปคํ
์ง์์ด ์
๋๋ค.
// ๐ฏ 1. LikeButton.tsx ํ์ผ (์๋ก ๋ถ๋ฆฌ)
'use client' // ์ฌ๊ถ์ ๋ฐ๊ธํ๋ค. "๋๋ ์ง๊ธ๋ถํฐ ๋ธ๋ผ์ฐ์ ํด๋ผ์ด์ธํธ ๋
์ผ๋ก ์
๊ตญํ ์ฝ๋๋ค."
import { useState } from 'react';
export default function LikeButton() {
const [likes, setLikes] = useState(0); // ํฐ์์ ๋์๊ฐ ๋ก์ง
return <button onClick={() => setLikes(c => c+1)}>โค๏ธ {likes}</button>;
}์ด์ ์๋ฒ์์ ๋๋ ๊ฑฐ๋ํ ๊ฒ์ํ(WeatherBoard) ์์, ํด๋ผ์ด์ธํธ์์ ์ํธ์์ฉํ ์์ ์กฐ๊ฐ(LikeButton)์ ๊ตฌ๋ฉ ์ก์ก ํ์ ๋ผ์ ๋ฃ์ผ๋ฉด ํ์์ ์ธ ํ์ด๋ธ๋ฆฌ๋ ์ํคํ ์ฒ๊ฐ ์์ฑ๋ฉ๋๋ค.
// ๐ฏ 2. WeatherBoard.tsx ํ์ผ (์๋ฒ ์ฃผ๋ฐฉ)
// (use client ๊ตฌ๋ฌธ ์์. ๊ณ ๋ก ์๋ฒ)
import LikeButton from './LikeButton'; // ๋ธ๋ฆฟ์ง ๊ฒฐํฉ!
export default async function WeatherBoard() {
return (
<div>
<h1>์ค๋์ ๋ ์จ (์๋ฒ์์ DB ๊ธ์ด์ด)</h1>
<p>๊ตฌ๋ฆ ๋ง์</p>
{/* ๐ ์ฌ๊ธฐ ํ์๋ถํฐ๋ ํด๋ผ์ด์ธํธ ํฐ์์ ์๋ฐ์คํฌ๋ฆฝํธ๊ฐ ๋๊ธฐ ์์ํ๋ค ๐ */}
<LikeButton />
</div>
);
}์ฐ๋ฆฌ๋ ์ด๊ฒ์ "๋๋ญ์(Leaf) ๋๋จ์ผ๋ก ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ๋ฅผ ๋ชฐ์๋ด๋ผ (Push client components to the leaves)" ๋ผ๊ณ ๋ถ๋ฆ
๋๋ค.
๋ฌด๊ฑฐ์ด ๋ ๋๋ง ํธ๋ฆฌ์ ๊ธฐ๋ฅ๊ณผ ๊ฐ์ง(Layout, Data Fetching, Markdown ๋ ๋)๋ ํผํผํ ์๋ฒ์์ ๋งก์ ๋ค ๊ทธ๋ ค๋ฒ๋ฆฌ๊ณ , ๋๋ญ์ ๋์์ ์ด๋๊ฑฐ๋ฆฌ๋ ๋ฒํผ ์ธํฐ๋์
๋ถ์ค๋ฌ๊ธฐ๋ค๋ง ๋ผ์ด๋ด์ ์ ์ ๋ธ๋ผ์ฐ์ (ํฐ)์ ์ ์กํ๋ ํ์์ ์ธ ์ฑ๋ฅ ์ต์ ํ ๊ตฌ์กฐ.
์ด๊ฒ์ด ํ๋ก ํธ์๋์ ๋ค์ ๋ชฉ์ ์ง, ๋ธ๋ฆฟ์ง ํ์ด๋ธ๋ฆฌ๋ ํจํด ์ ๋๋ค.
๐ ๋๋์ด, ๋๋จ์ ์ด์ ๋ฆฌ
์ง๊ธ๊น์ง ์ ์ '์์ฒ '์ด๊ฐ ๊ฒช์ ๋ชจ๋ ๋ฆฌ์กํธ์ ํจ์ ๊ณผ, ๋ฆฌ๋ '์ํธ'๊ฐ ์๋ ค์ค ์๋์ด์ ํต์ ๊ธฐ์ ์ ๋ชฉ๋ํ์ต๋๋ค.
- ์ํ ๊ด๋ฆฌ์ ์ฐฉ๊ฐ (๊ฐ์ด๋ 1~4): ์ํ๋ ๋ ๋๋ง ์ค๋ ์ท์ด๋ค. ๋ถ๋ณ์ฑ์ ํ๋ฉด์ ์๋ก ๊ทธ๋ฆฌ๊ธฐ ์ํ ์ ํธํ์ด๋ค. ํจ๋ถ๋ก ์ ์ญ ๋๊ตฌ๋ฅผ ์น๋์น๋ ๋ฐ๋ฅด๊ธฐ ์ ์ "State Colocation(๋ฐ๋์ผ๋ก ๋ฐ์ด๋ด๊ธฐ)"์ ์ค์ฒํ๋ผ.
- ์ดํํธ์ ๋ผ์ดํ์ฌ์ดํด ๋ฏธ๋ (๊ฐ์ด๋ 5~8):
useEffect๋ ๋ง์ดํธ ์์ ์ฝ๋ฐฑ์ ๋ชจ์๋๋ ์ฅ์์ด ์๋๋ผ, ๋ฆฌ์กํธ ์ธ๋ถ ์์ญ(DOM API, ์๋ฒ ๋๊ธฐํ)๊ณผ ์์๋ฅผ ๋ง์ถ๋ ๋๊ธฐํ ์ง์ ๋ค. - ์ต์ ํ ๊ฐ๋ฐ์ ํด์ฒด (๊ฐ์ด๋ 9~11):
useMemo๋useCallback์ผ๋ก ๋ง์ฅ ๋ฐฉ์ด๋ฅผ ์ง๊ธฐ ์ ์, "์ปดํฌ๋ํธ ์ชผ๊ฐ๊ธฐ + Children ํฉ์ฑ + Context State/Action ๋ถ๋จ" ์ด๋ผ๋ ์ํธ์ ๊ทผ์์ ์ํคํ ์ฒ ์์ ๋ฒ์ ๋ค์ด๋ฐ์ด๋ผ. - ์ฐจ์ธ๋ ๋์์ธ ์บก์ํ (๊ฐ์ด๋ 12~14): ์ ์ด๊ถ์ ๋ถ๋ชจ๋ก ๋ค ๋ด๋์ง๊ณ (IoC), ์ปดํ์ด๋ ๋ธ๋ก์ ์ญํ ๋ณ๋ก ๋๋๊ณ , Headless Hook๋ก ๋ก์ง ์ฝ์ด๋ฅผ ์๋ฒฝํ ์ ์ถํ๋ฉด ๊ทธ ์ด๋ค ๋์์ธ์ด ๋ฐ๋์ด๋ ๋๋ ต์ง ์๋ค.
- ์๋ฒ๋ก ๊ทํ (ํ์ฌ ๊ฐ์ด๋ 15): ์ด์ ๋ฆฌ์กํธ๋ ๋ธ๋ผ์ฐ์ ๋ผ๋ ๊ฐ์ฅ์ ํ์ถํด ์๋ฒ๊น์ง ์ง์ด์ผ์ผฐ๋ค. ์ํธ์ ์์ฒ ์ด๋ ๋ฐ์ผํ๋ก RSC ๋ผ๋ ์๋ก์ด ๋๋ฅ์ ๋๋ฌํ๋ค.
๋จ์ธ์ปจ๋, ๋น์ ์ด 15๊ฐ๊น์ง์ ์ฝ๋๋ฅผ ๋์ผ๋ก ์ข์ผ๋ฉฐ ๊ณ ๊ฐ๋ฅผ ๋๋์๋ค๋ฉด, ๋น์ ์ ์ด๋ฏธ ๋จ์ํ '์ฝ๋'๋ฅผ ๋์ด ์์คํ ์ ๋ณ๋ชฉ์ ์ง๋จํ๊ณ ๋ถ์ด๋ฒ๋ฆฌ๋ '5๋ ์ฐจ ํ๋ก ํธ์๋ ์ค๊ณ์'์ ๋๋ฅผ ์ฅ์ฐฉํ ๊ฒ์ ๋๋ค.
๊ทธ๋์ ๊ธฐ๋๊ธด ๋์ฅ์ ์ ํจ๊ปํ ์์๋ค ์ปค๋ฎค๋ํฐ ์ ๋์์๊ฒ ๋ฐ์๋ฅผ ๋ณด๋ ๋๋ค! ์ฝ๋ฉ์ ์ถ๋ณต์ด ๋น์ ์ ๋น๋ ํ์ดํ๋ผ์ธ๊ณผ ํจ๊ปํ๊ธฐ๋ฅผ.
๐ ๋ง๋ฌด๋ฆฌ(์ํ๋ก๊ทธ) ํด์ฆ
Q1. ์์ฒ ์ด๊ฐ App Router์ ์ต์๋จ layout.tsx์ ์ต๊ด์ฒ๋ผ 'use client'๋ฅผ ๋ถ์ด๋ฉด ์ด๋ค ๋ฌธ์ ๊ฐ ์๊ธฐ๋์?
โ
์ ๋ต: ์์ ๊ฒฝ๊ณ ์๋์ ๋ง์ ํ์ ์ปดํฌ๋ํธ๊ฐ ํด๋ผ์ด์ธํธ ๋ฒ๋ค๋ก ๋ฐ๋ผ ๋ด๋ ค๊ฐ JS ๋ค์ด๋ก๋์ hydration ๋น์ฉ์ด ์ปค์ง๋ค
๐ก ์์ธ ํด์ค:
- ์๋ฆฌ ์ค๋ช
:
'use client'๋ ํ์ผ ํ๋์ ํธ์ ํ๋๊ทธ๊ฐ ์๋๋ผ ์๋ฒ์ ํด๋ผ์ด์ธํธ๋ฅผ ๊ฐ๋ฅด๋ ๋ฒ๋ค ๊ฒฝ๊ณ์ ๋๋ค. ์ํธ๊ฐ ๋งํ ๊ฒ์ฒ๋ผ ๋ฐ์ดํฐ ์กฐํ, ๋งํฌ๋ค์ด ๋ณํ, ์ ์ ๋ ์ด์์์ ์๋ฒ์ ๋จ๊ธฐ๊ณ ๋ฒํผ์ด๋ ์ ๋ ฅ์ฒ๋ผ ๋ธ๋ผ์ฐ์ ์ํธ์์ฉ์ด ํ์ํ leaf๋ง ํด๋ผ์ด์ธํธ๋ก ๋ด๋ ค์ผ ํฉ๋๋ค. - ์ค๋ต ํผ๋๋ฐฑ: ์๋ฌ๊ฐ ์ฌ๋ผ์ง๋ค๋ ์ด์ ๋ก ๊ฒฝ๊ณ๋ฅผ ์๋ก ์ฌ๋ฆฌ๋ฉด RSC์ ์ฅ์ ์ธ ์์ ๋ฒ๋ค, ์๋ฒ ๋ฐ์ดํฐ ์ ๊ทผ, ๋ฎ์ hydration ๋น์ฉ์ ์์ต๋๋ค.
- ๐ ํต์ฌ ๊ธฐ์ต๋ฒ: ํด๋ผ์ด์ธํธ ๊ฒฝ๊ณ๋ ํธ์๊ฐ ์๋๋ผ ๋น์ฉ์ ๋๋ค.
Q2. ์๋ฒ ์ปดํฌ๋ํธ ๋ด๋ถ์์ ์ง์ ์ฒ๋ฆฌํ๋ฉด ์ ๋๋ ๊ฒ์ ๋ฌด์์ธ๊ฐ์?
โ
์ ๋ต: useState, useEffect, onClick์ฒ๋ผ ๋ธ๋ผ์ฐ์ ์ํ์ ์ฌ์ฉ์ ์ด๋ฒคํธ์ ์์กดํ๋ ์ํธ์์ฉ ๋ก์ง
๐ก ์์ธ ํด์ค:
- ์๋ฆฌ ์ค๋ช : ์๋ฒ ์ปดํฌ๋ํธ๋ ๋ธ๋ผ์ฐ์ ์ ํ์ฌ ํด๋ฆญ, ํฌ์ปค์ค, ์ฐฝ ํฌ๊ธฐ, ๋ก์ปฌ ์ํ๋ฅผ ์ ์ ์์ต๋๋ค. ์์์ด ์๊ตฌํ ์ข์์ ๋ฒํผ์ฒ๋ผ ์ฌ์ฉ์๊ฐ ์ง์ ๋ง์ง๋ ๋ถ๋ถ์ ์์ Client Component๋ก ๋ถ๋ฆฌํด์ผ ํฉ๋๋ค.
- ์ค๋ต ํผ๋๋ฐฑ: ์๋ฒ ์ปดํฌ๋ํธ๊ฐ HTML์ ๋ง๋ค ์ ์๋ค๊ณ ํด์ ๋ธ๋ผ์ฐ์ ์ด๋ฒคํธ๊น์ง ๊ฐ์งํ ์ ์๋ ๊ฒ์ ์๋๋๋ค.
- ๐ ํต์ฌ ๊ธฐ์ต๋ฒ: ์๋ฒ๋ ์ค๋นํ๊ณ , ํด๋ผ์ด์ธํธ๋ ๋ฐ์ํฉ๋๋ค.
Q3. ์๋ฒ ์ปดํฌ๋ํธ๊ฐ ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ์ ๊ฐ์ ๋๊ธธ ๋ ํ์ธํด์ผ ํ ๊ฐ์ฅ ์ค์ํ ์กฐ๊ฑด์ ๋ฌด์์ธ๊ฐ์?
โ
์ ๋ต: ๋คํธ์ํฌ ๊ฒฝ๊ณ๋ฅผ ์ง๋๊ฐ ์ ์๋๋ก ์ง๋ ฌํ ๊ฐ๋ฅํ ๋ฐ์ดํฐ๋ง props๋ก ์ ๋ฌํด์ผ ํ๋ค
๐ก ์์ธ ํด์ค:
- ์๋ฆฌ ์ค๋ช : RSC ๊ฒฝ๊ณ๋ ํจ์ ํธ์ถ ๊ฒฝ๊ณ๊ฐ ์๋๋ผ ์๋ฒ์์ ๋ธ๋ผ์ฐ์ ๋ก ์ ๋ฌ๋๋ ๋ฐ์ดํฐ ๊ฒฝ๊ณ์ ๋๋ค. ํจ์, DB ์ปค๋ฅ์ , ํด๋์ค ์ธ์คํด์ค์ฒ๋ผ ์คํ ํ๊ฒฝ์ ๋ฌถ์ธ ๊ฐ์ ๊ทธ๋๋ก ๋๊ธธ ์ ์์ต๋๋ค.
- ์ค๋ต ํผ๋๋ฐฑ: ์์๋ค ์ปค๋ฎค๋ํฐ ๊ฒ์๊ธ ๋ฐ์ดํฐ์ฒ๋ผ JSON์ผ๋ก ํํ ๊ฐ๋ฅํ ๊ฐ์ ๊ด์ฐฎ์ง๋ง, ์๋ฒ์์๋ง ์๋ฏธ ์๋ ๋ฆฌ์์ค๋ฅผ ํด๋ผ์ด์ธํธ์ ๋ค๊ณ ๊ฐ๋ ค ํ๋ฉด ๊ฒฝ๊ณ๊ฐ ๋ฌด๋์ง๋๋ค.
- ๐ ํต์ฌ ๊ธฐ์ต๋ฒ: props๋ ์คํ ์ฝ๋๊ฐ ์๋๋ผ ์ ๋ฌ ๊ฐ๋ฅํ ๋ฐ์ดํฐ์ ๋๋ค.
๐ฃ ์์ฒ ์ด์ ํด๊ทผ ์ผ๊ธฐ
15๊ฐ ๋์ฅ์ ์ ๋ง๋ฌด๋ฆฌํ๋ฉฐ ๊ฐ์ฅ ํฌ๊ฒ ๋ฐ๋ ์๊ฐ์ ํ๋๋ค. use client๋ ์๋ฌ๋ฅผ ์์ ๋ ์ฃผ๋ฌธ์ด ์๋๋ผ ์์๋ค ์ปค๋ฎค๋ํฐ์ ์๋ฒ์ ์ฌ์ฉ์ ๋ธ๋ผ์ฐ์ ์ฌ์ด์ ๋๋ ์ค์ ๊ฒฝ๊ณ์ ์ด์๋ค. ์์ ์ ๋๋ "๋ฒํผ ํ๋ ๋๋ฌธ์ ๊ท์ฐฎ์ผ๋ ์์ ๋ถ์ด๋ฉด ๋๊ฒ ์ง"๋ผ๊ณ ์๊ฐํ์ง๋ง, ์ด์ ๋ ๊ทธ ํ ์ค์ด ์์์ด ๋ง๋ ํ๋ฉด์ ๋ก๋ฉ๊ฐ๊ณผ ์์๊ฐ ๋ณด๋ ์ด์ ๋น์ฉ๊น์ง ๋ฐ๊พผ๋ค๋ ๊ฑธ ์๋ค.
๐ก "๋ฌด๊ฑฐ์ด ๋ฐ์ดํฐ ์ ๊ทผ๊ณผ ์ ์ ๊ตฌ์กฐ๋ ์๋ฒ์ ๋จ๊ธฐ๊ณ , ์ฌ์ฉ์๊ฐ ์ง์ ๋ง์ง๋ ์์ ์กฐ๊ฐ๋ง ํด๋ผ์ด์ธํธ๋ก ๋ด๋ ค๋ณด๋ด๋ผ."
์ํธ๋ ์ค๋๋ ๋ต์ ๋์ ์ฃผ๊ธฐ๋ณด๋ค ํ๋จ ๊ธฐ์ค์ ๋จ๊ฒผ๋ค. ๋ ๋๋ง, ์ํ, ์ดํํธ, ํฉ์ฑ, ์ ๊ทผ์ฑ, ๊ทธ๋ฆฌ๊ณ RSC๊น์ง ์ง๋์ค๋ฉด์ ๋๋ React๋ฅผ ๋ฌธ๋ฒ ๋ฌถ์์ด ์๋๋ผ ๋น์ฉ๊ณผ ์ฑ ์์ ๋ฐฐ์นํ๋ ๋๊ตฌ๋ก ๋ณด๊ธฐ ์์ํ๋ค. ์ด์ ์ ์ด๋ "์ด๋์์ ์คํ๋์ด์ผ ํ๋๊ฐ"๋ฅผ ๋จผ์ ๋ฌป๋ ๊ฐ๋ฐ์๊ฐ ๋์๋ค.