๋จ๋ฆฌ๋ ๋ง์์ ์๊ณ , ์๋ก ์์ํ๋ ํ๋ก์ ํธ๋ฅผ NextJS using App router
๋ก ์์ํ์์ต๋๋ค. ๋ช ๊ฐ์ ์ ์ฏค ์ ํ์ฌ์์ app router๊ฐ ๋ฒ ํ ๋ฒ์ ์ผ๋ก ๋ฆด๋ฆฌ์ฆ๋์์ ๋, ํ๋ฒ ๋ฆฌํฉํ ๋ง์ ์๋ํ๋ค๊ฐ, ์คํจํ ๊ฒฝํ์ด ์์ต๋๋ค. ํ๋ก์ ํธ๊ฐ ์ด๋ฏธ ์ข ์ปค์ง๊ธฐ๋ ํ๊ณ , ๋ฌด์๋ณด๋ค "use client", "use server"ํ๋ฉฐ, ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ, ์๋ฒ ์ปดํฌ๋ํธ์ ๊ฐ์ ๊ฐ๋
๋ค์ด ๋ฑ์ฅํ๊ธฐ ์์ํ๋๋ฐ, ์ด๋ค ๊ฐ๋
์ธ์ง ์ ํํ ์ดํดํ์ง ๋ชปํ๊ณ ์๋ ํฐ๋ผ, ์ฐ์ Server Component์ ๊ฐ๋
๋ถํฐ ์ ํํ ์ ๋ฆฌํด๋ณด๊ธฐ๋ก ํ์์ต๋๋ค.
ํ๋ฌ ์ฏค ์ ์ ํธ์ํฐ์์ ์๋ฒ์ปดํฌ๋ํธ์ ๊ด๋ จํด ์ข์ ๋ธ๋ก๊ทธ ํฌ์คํธ๊ฐ ๊ณต์ ๋ ๊ฒ์ ํ์ธํ๊ณ , ์ด ๋ธ๋ก๊ทธ ํฌ์คํธ๋ฅผ ๋ฒ์ญํด๋ณด๋ฉด์ ์๋ฒ ์ปดํฌ๋ํธ์ ๋ํด ์ดํดํด๋ณด๊ธฐ๋ก ํ์ต๋๋ค.
๋ธ๋ก๊ทธ ํฌ์คํธ๋ฅผ ๋จผ์ ์๊ฐ๋๋ฆฝ๋๋ค! ๐๐ผ Making Sense of React Server Components
์๋์์ ์ด์ด์ง๋ ๋ด์ฉ์ Josh W Comeau๋์ Making Sense of React Server Components๋ฅผ ๋ฒ์ญํ ๊ธ์ ๋๋ค.
๋ฆฌ์กํธ๋ ์ง๋ 10๋ ๊ฐ, ๋ ๋ ๋์ ์๋ฃจ์ ์ ์ฐพ์์์ต๋๋ค. ๊ทธ๋์ ๋ฆฌ์กํธ๋ ์ฌ๋ฌ ์ฐจ๋ก์ ๋ณํ๋ฅผ ๊พํ๊ณ , ์งํํด์์ต๋๋ค. ๋ช ๋ฌ ์ Reactํ์ React Server Components๋ฅผ ๊ณต๊ฐํ๊ณ , ์ด๊ฒ์ ์ต๊ทผ ๋ฆฌ์กํธ์ ํจ๋ฌ๋ค์ ์ ํ ์ค ํ๋์ ๋๋ค. ๋ง์ ๊ฐ๋ฐ์๋ค์ด React Server Components์ ๋ํด ์ง๋ฌธํด์ฃผ์์ต๋๋ค. ์ ๋ ์ค๋ ๊ทธ ์ง๋ฌธ๋ค์ ๋ตํ๋ฉด์, ๋ง์ ๊ฐ๋ฐ์๋ค์ ๊ถ๊ธ์ฆ์ ํด์ํ๋ ๊ฒ์ด ๋ชฉํ์ ๋๋ค.
2015๋ ์ ๋ฆฌ์กํธ๋ฅผ ์ฒ์ ์ฌ์ฉํ ๋ ๋๋ถ๋ถ์ ๋ฆฌ์กํธ ์ค์ ์ CSR์ ์ฌ์ฉํ์ต๋๋ค. ์ ์ ๋ ๋ค์๊ณผ ๊ฐ์ html ํ์ผ์ ๋ฐ์์ต๋๋ค.
<!DOCTYPE html>
<html>
<body>
<div id="root"></div>
<script src="/static/js/bundle.js"></script>
</body>
</html>
bundle.js
์คํฌ๋ฆฝํธ๋ ๋ฆฌ์กํธ ๊ทธ ์์ฒด์ third-party ๋ํ๋์๋ฅผ ํฌํจํด, ์ดํ๋ฆฌ์ผ์ด์
์ ์คํํ๊ณ ๋ง์ดํธํ๊ธฐ ์ํ ๋ชจ๋ ์ฝ๋๋ฅผ ๋ด๊ณ ์์์ต๋๋ค. ๋ฌธ์ ๋ ์คํฌ๋ฆฝํธ๊ฐ ํ์ฑ๋๊ณ , ๋ฆฌ์กํธ๊ฐ ์ดํ๋ฆฌ์ผ์ด์
์ ๋ํ ๋ชจ๋ DOM ๋
ธ๋๋ฅผ ์์ฑํ๋ ๋์, ์ฌ์ฉ์๋ ๋นํ๋ฉด์ ๋ฐ๋ผ๋ณด๊ณ ์์ด์ผ ํ๋ค๋ ์ ์ด์์ต๋๋ค. ์๋ก์ด ๊ธฐ๋ฅ์ด ๋ฑ์ฅํ๋ฉด์, ์๋ฐ์คํฌ๋ฆฝํธ ๋ฒ๋ค์ ํฌ๊ธฐ๋ ๋์ฑ ์ปค์ก๊ณ , ์ ์ ๋ค์ ๋ ๋ง์ ์๊ฐ๋์ ๋น ํ๋ฉด์ ๋ฐ๋ผ๋ด์ผ ํ์ต๋๋ค.
SSR์ ์ด ๊ฒฝํ์ ๊ฐ์ ํ๊ธฐ ์ํด ์ค๊ณ๋์์ต๋๋ค. ์ ์ ๊ฐ ์น์ฌ์ดํธ์ ๋ฐฉ๋ฌธํ์ ๋, ๋น html ํ์ผ์ ๋ด๋ ค๋ณด๋ด๋ ๋์ , ์๋ฒ๋ ์ดํ๋ฆฌ์ผ์ด์
์ ๋ ๋๋งํ์ฌ ์ค์ html์ ์์ฑํ๊ณ , ์ ์ ๋ ํ์ด ๊ฐ์ถฐ์ง html ๋ฌธ์๋ฅผ ๋ฐ๊ฒ ๋์์ต๋๋ค. ๋ฌผ๋ก ํด๋น html ํ์ผ์ ์ฌ์ ํ script ํ๊ทธ๋ฅผ ๊ฐ๊ณ ์์ต๋๋ค. ๊ทธ๋ฌ๋ CSR๊ณผ๋ ์กฐ๊ธ ๋ค๋ฅธ ํํ๋ก React๊ฐ ๋์ํ๋ค๋ ์ ์ ์ ๋
ํด์ผ ํฉ๋๋ค. React๋ ๋ ์ด์ ์ฒ์๋ถํฐ ๋ชจ๋ DOM ๋
ธ๋๋ฅผ ๋ง๋ค์ง ์์ต๋๋ค. ๋ฆฌ์กํธ๋ ์ด์ ์ด๋ฏธ ๋ง๋ค์ด์ง html์ ์ฑํํฉ๋๋ค. ์ด ๊ณผ์ ์ ๋ฐ๋ก hydration
์ด๋ผ๊ณ ํฉ๋๋ค. Dan Abramov๋ hydration์ ๋ค์๊ณผ ๊ฐ์ด ์ค๋ช
ํฉ๋๋ค.
Hydration is like watering the โdryโ HTML with the โwaterโ of interactivity and event handlers.
Hydration์ ๋ง๋ผ์๋ html์ ์ด๋ฒคํธ ํธ๋ค๋ฌ์ ์ ์ ์์ ์ํธ์์ฉ์ผ๋ก ์ ์๋ ๊ฒ๊ณผ ๊ฐ์ต๋๋ค.
์ด๊ฒ์ด SSR์ ์์ ์ ๋๋ค. ์๋ฒ๊ฐ ๋จผ์ ์ด๊ธฐ html์ ์์ฑํ์ฌ ์ด๋ฅผ ๋ด๋ ค๋ณด๋ด๋ฉด, JS ๋ฒ๋ค์ด ๋ค์ด๋ก๋๋๊ณ ํ์ฑ๋๋ ๋์ ์ ์ ๋ ๋น ํ๋ฉด์ ๋ฐ๋ผ๋ณด์ง ์์๋ ๋๋ ๊ฒ์ด์ฃ . ํด๋ผ์ด์ธํธ๋ ์๋ฒ๊ฐ ์ค๋จํ ๊ณณ์์๋ถํฐ DOM์ ๋ง์ถ์ด, ์ด๋ฒคํธ ํธ๋ค๋ฌ ๋ฑ ์ํธ์์ฉ์ ๋ํฉ๋๋ค.
An umbrella term
๋ณดํต SSR์ ๋ ์ฌ๋ฆฌ๋ฉด ์๋์ ๊ฐ์ ํ๋ฆ์ ์์ํฉ๋๋ค.
ใฑ) ์ฌ์ฉ์๊ฐ ์น์ฌ์ดํธ๋ฅผ ๋ฐฉ๋ฌธ
ใด) NodeJS ์๋ฒ๊ฐ ์์ฒญ์ ๋ฐ์ ์ฆ์ React ์ฑ์ ๋ ๋๋งํด html ์์ฑ
ใท) ๊ฐ ๊ตฌ์ด html์ ํด๋ผ์ด์ธํธ๋ก ์ ์ก
์ฌ์ค ์ด ๋ฐฉ๋ฒ์ SSR์ ๊ตฌํํ๋ ํ๋์ ๋ฐฉ๋ฒ์ ๋๋ค. ๋ ๋ค๋ฅธ ์ต์ ์ ์ฑ์ ๋น๋ํ ๋, html์ ์์ฑํ๋ ๊ฒ์ ๋๋ค. ์ผ๋ฐ์ ์ผ๋ก ๋ฆฌ์กํธ ์ฑ์ jsx๋ฅผ ๋ฐ๋๋ผ js๋ก ๋ณํํ๊ณ , ๋ชจ๋ ๋ชจ๋์ ๋ฒ๋ค๋งํด์ผ ํฉ๋๋ค. ์ด ๊ณผ์ ์์ html์ ๋ฏธ๋ฆฌ ๋ ๋ํ๋ค๋ฉด ์ด๋จ๊น์? ์ด๊ฒ์ ๋ฐ๋ก SSG๋ผ๊ณ ํฉ๋๋ค. SSR์ ํ์ ๋ณํ์ธ ๊ฒ์ด์ฃ . SSR์ ์ฌ๋ฌ ๋ค๋ฅธ ๋ ๋๋ง ์ ๋ต์ ํฌํจํ๋ ๋ํ์ฉ์ด์ ๋๋ค.
๋ฆฌ์กํธ์ Data-fetching์ ๋ํด ์ด์ผ๊ธฐํด๋ด ์๋ค. ์ผ๋ฐ์ ์ผ๋ก ๋คํธ์ํฌ๋ฅผ ํตํด ํต์ ํ๋ ๋๊ฐ์ ๋ณ๋์ ์ดํ๋ฆฌ์ผ์ด์ ์ด ์์ต๋๋ค. ํด๋ผ์ด์ธํธ ์ฌ์ด๋์ ๋ฆฌ์กํธ ์ฑ๊ณผ, ์๋ฒ ์ฌ์ด๋์ RestAPI๊ฐ ๊ทธ๊ฒ์ ๋๋ค. Data-fetching ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ฑ์ ํตํด ํด๋ผ์ด์ธํธ๋ ๋ฐฑ์๋๋ก ๋คํธ์ํฌ ์์ฒญ์ ๋ณด๋ด๊ณ , ๋ฐฑ์๋๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ๋ฐ์ดํฐ๋ฅผ ์ฐพ์ ๋ฐํํฉ๋๋ค.
์ ๊ทธ๋ํ๋ CSR ์ ๋ต์ ์ฌ์ฉํ ๊ฒฝ์ฐ์ ํ๋ฆ์ ๋๋ค. ์ฒ์์๋ ์ค์ ๋ฐ์ดํฐ๊ฐ ์์ผ๋ฏ๋ก ๋ก๋ฉ์ํ์ Shell(ํค๋, ํธํฐ, ์ผ๋ฐ์ ์ธ ๋ ์ด์์)๋ง ๋ ๋๋งํ ์ ์์ต๋๋ค. ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๋ ๋์ Skeleton UI๋ฅผ ๋ณด์ฌ์ฃผ๋ ๊ฒ์ด ์ด ๊ฒฝ์ฐ์ ํด๋นํฉ๋๋ค. ๋คํธ์ํฌ ์์ฒญ์ด ์๋ฃ๋๊ณ , ๋ฆฌ์กํธ๊ฐ ๋ฆฌ๋ ๋๋ง ๋ ๋๊น์ง ์ ์ ๋ ๋ก๋ฉ์ํ๋ฅผ ๋ด ๋๋ค.
์ด๋ฒ์๋ SSR ์ ๋ต์ ์ฌ์ฉํ ๊ฒฝ์ฐ๋ฅผ ๋์ํํ ๊ทธ๋ํ์ ๋๋ค. ์ด์ ์ฌ์ฉ์๋ ๋น์ด ์์ง ์์ html ํ์ผ์ ๋ด๋ ค๋ฐ์ต๋๋ค. ๊ทธ๋ฌ๋ ๊ถ๊ทน์ ์ผ๋ก ํฐ ์ฐจ์ด๋ฅผ ๋ง๋ค์ง๋ ์์ต๋๋ค. (SSR์ ์ฌ์ฉํ๋๋ผ๋ ํด๋ผ์ด์ธํธ์์ ๋ฐ์ดํฐ๋ฅผ ํ์นญํ๋ ๊ฒฝ์ฐ๋ฅผ ๋งํ๋ ๊ฒ ๊ฐ์ต๋๋ค.) ์ ์ ๋ ๋ก๋ฉํ๋ฉด์ ๋ณด๊ธฐ ์ํด ์ฑ์ ๋ฐฉ๋ฌธํ๋ ๊ฒ์ด ์๋๋ผ ๋ด์ฉ์ ๋ณด๋ฌ ๋ฐฉ๋ฌธํ๋ ๊ฒ์ด๋๊น์. ๊ทธ๋ ๋ค๋ฉด ์ฐจ์ด๋ฅผ ํ์ ํ๊ธฐ ์ํด First Paint, Page Interactive, Content Paint ๋ฑ์ ์น ์ฑ๋ฅ ์งํ์ ํจ๊ป ์ดํด๋ด ์๋ค.
์๋ฒ์์ ์ด๊ธฐ์ ๋ ๋๋ง์ ์ํํ๋ฏ๋ก ์ด๊ธฐ Shell์ ๋ ๋นจ๋ฆฌ ๊ทธ๋ฆด ์ ์์ต๋๋ค. ๋ก๋ฉ ๊ฒฝํ์ด ๋น ๋ฅด๊ฒ ๋๊ปด์ง ์ ์์ผ๋ฉฐ, ์งํ์ด ์์์ ๋๋ผ๊ฒ ํฉ๋๋ค. ๋ง์ผ ์ฌ์ฉ์๊ฐ ์ํ๋ ๊ฒ์ด ๋ค๋น๊ฒ์ด์ ๋งํฌ๋ฅผ ํด๋ฆญํ๋ ๊ฒ์ด๋ผ๋ฉด ์ ์๋ฏธํ ๊ฐ์ ์ ๋๋ค. ๊ทธ๋ฐ๋ฐ ์ด๋ฐ ์๊ฐ์ ํด๋ณผ ์ ์์ต๋๋ค. SSR ๊ทธ๋ํ๋ฅผ ๋ณด๋ฉด ์์ฒญ์ด ์๋ฒ์์ ์์ํฉ๋๋ค. ๋ ๋ฒ์งธ ์๋ณต ๋คํธ์ํฌ ์์ฒญ ๋์ ์ด๊ธฐ ์์ฒญ ์ค์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์์ ์ ์ ์ํํ์ง ์๋ ๊ฑธ๊น์?
ํด๋ผ์ด์ธํธ์ ์๋ฒ๋ฅผ ์๋ค๊ฐ๋ค ํ๋ ๋์ , ์ด๊ธฐ ์์ฒญ์ ์ผ๋ถ๋ก ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฟผ๋ฆฌ๋ฅผ ์ํํ๊ณ ์์ ํ ์ฑ์์ง UI๋ฅผ ์ฌ์ฉ์์๊ฒ ์ง์ ์ ์กํ๋ ๋ฐฉ์์ ๋๋ค. React์์ ์ ๊ทธ๋ํ์ ๊ฐ์ ํ๋ฆ์ ๊ตฌํํ๊ธฐ์๋ ๋ณต์กํฉ๋๋ค. ์ด ๋ฌธ์ ์ ๋ํ ํด๊ฒฐ์ฑ ์ผ๋ก ๋ฑ์ฅํ ๊ฒ์ด NextJS์ GatsbyJS๊ฐ์ ๋ฉํ ํ๋ ์์ํฌ์ ๋๋ค.
import db from 'imaginary-db';
// This code only runs on the server:
export async function getServerSideProps() {
const link = db.connect('localhost', 'root', 'passw0rd');
const data = await db.query(link, 'SELECT * FROM products');
return {
props: { data },
};
}
// This code runs on the server + on the client
export default function Homepage({ data }) {
return (
<>
<h1>Trending Products</h1>
{data.map((item) => (
<article key={item.id}>
<h2>{item.title}</h2>
<p>{item.description}</p>
</article>
))}
</>
);
}
NextJS์ Page router๋ฅผ ํ์ฉํ ์์์ ๋๋ค.
์์ธํ ์ดํด๋ณด๊ฒ ์ต๋๋ค. ์ ์ ๊ฐ ์ฑ์ ๋ฐฉ๋ฌธํด ์๋ฒ๊ฐ ์์ฒญ์ ๋ฐ์ผ๋ฉด, getServerSideProps ํจ์๊ฐ ํธ์ถ๋ฉ๋๋ค. ์ด ํจ์๋ props ๊ฐ์ฒด๋ฅผ ๋ฐํํ๊ณ , props๋ ์ปดํฌ๋ํธ๋ก ์ ๋ฌ๋์ด, ๋จผ์ ์๋ฒ์์ ๋ ๋๋ง๋๊ณ ๊ทธ๋ฐ๋ค์ ํด๋ผ์ด์ธํธ์์ hydrate๋ฉ๋๋ค. ์ค์ํ ์ ์ getServerSideProps๋ ํด๋ผ์ด์ธํธ์์ ๋ค์ ์คํ๋์ง ์๋๋ค๋ ์ ์ ๋๋ค. ์ฌ์ค ์ด ํจ์๋ JS ๋ฒ๋ค์ ํฌํจ๋์ง๋ ์์ต๋๋ค. ๋๋ฌด ๋ฉ์ง ๋ฐฉ๋ฒ์ด์ง๋ง ์ฌ๊ธฐ์ ๋ช ๊ฐ์ง ๋จ์ ์ด ์์ต๋๋ค.
์ ๋จ์ ๋ค์ ๋ํ ํด๊ฒฐ์ฑ ์ด ๋ฐ๋ก React Server Component์ ๋๋ค!
React Server Component๋ ๋ฆฌ์กํธ์ ์๋ก์ด ํจ๋ฌ๋ค์์ ๋๋ค. ์ด์ ์๋ฒ ์ ์ฉ์ผ๋ก ์คํ๋๋ ์ปดํฌ๋ํธ๋ฅผ ๋ง๋ค ์ ์์ต๋๋ค. React ์ปดํฌ๋ํธ ๋ด๋ถ์์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฟผ๋ฆฌ๋ฅผ ์ง์ ์์ฑํ๋ ๊ฒ๊ณผ ๊ฐ์ ์์ ์ ์ํํ ์ ์์ต๋๋ค.
import db from 'imaginary-db';
async function Homepage() {
const link = db.connect('localhost', 'root', 'passw0rd');
const data = await db.query(link, 'SELECT * FROM products');
return (
<>
<h1>Trending Products</h1>
{data.map((item) => (
<article key={item.id}>
<h2>{item.title}</h2>
<p>{item.description}</p>
</article>
))}
</>
);
}
export default Homepage;
๋ฆฌ์กํธ๋ฅผ ์ค๋ซ๋์ ์ฌ์ฉํด์จ ์ฌ๋์ผ๋ก์ ์ ์ฝ๋๋ ์์ฒญ๋ ๋ฏ ๋ณด์์ต๋๋ค. ํจ์ ์ปดํฌ๋ํธ๋ ์ง๊ธ๊ป ๋น๋๊ธฐ์ผ ์ ์์๊ณ , ๋ ๋๋ง ์์ ์ง์ ์ฌ์ด๋ ์ดํํธ๋ฅผ ๊ฐ์ง ์๋ ์์์ผ๋๊น์. ์ฌ๊ธฐ์ ์ฐ๋ฆฌ๊ฐ ์ดํดํด์ผ ํ๋ ์ค์ํ ๊ฒ์ ์๋ฒ ์ปดํฌ๋ํธ๋ ๋ค์ ๋ ๋๋ง๋์ง ์๋๋ค๋ ๊ฒ์ ๋๋ค. ์๋ฒ ์ปดํฌ๋ํธ๋ UI๋ฅผ ์์ฑํ๊ธฐ ์ํด ์๋ฒ์์ ํ ๋ฒ ์คํ๋ฉ๋๋ค. ๋ ๋๋ง๋ ๋ด์ฉ์ด ํด๋ผ์ด์ธํธ๋ก ์ ์ก๋๊ณ ๊ทธ ์ํ๋ก ๋ถ๋ณํฉ๋๋ค. ์ด๋ ์ฌ์ค ๋ฆฌ์กํธ์ API ์ค ์๋น ๋ถ๋ถ์ด ์๋ฒ ์ปดํฌ๋ํธ์ ํธํ๋์ง ์๋๋ค๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค. ๊ฐ์ฅ ๊ธฐ๋ณธ์ ์ผ๋ก state๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค. state๋ ์ปดํฌ๋ํธ ๋ด์์ ๋ณ๊ฒฝ๋๋ ๊ฐ์ด์ง๋ง, ์๋ฒ ์ปดํฌ๋ํธ๋ ๋ค์ ๋ ๋๋ง๋ ์ ์์ผ๋๊น์. ์ด๋ ์ฌ์ค ๋ฆฌ์กํธ์ ๋ฃฐ์ ๋ํด ์ข ๋ ์ ์ฐํ๊ฒ ๋์ฒํ ์ ์๋ค๋ ์๋ฏธ์ด๊ธฐ๋ ํฉ๋๋ค. ์ฐ๋ฆฌ๋ ๊ธฐ์กด ๋ฆฌ์กํธ์์ ๋ชจ๋ ๋ ๋๋ง์์ ์ฌ์ด๋ ์ดํํธ๋ฅผ ๋ฐ๋ณตํ์ง ์๋๋ก useEffect๋ฅผ ํ์ฉํ์ต๋๋ค. ๊ทธ๋ฌ๋ ์ปดํฌ๋ํธ๊ฐ ํ ๋ฒ๋ง ์คํ๋๋ค๋ฉด ์์ ๊ฐ์ ๊ฑฑ์ ์ ํ์ง ์์๋ ๋ฉ๋๋ค. ์๋ฒ ์ปดํฌ๋ํธ๋ ๋๋๋๋ก ๊ฐ๋จํ์ง๋ง React Server Component ํจ๋ฌ๋ค์์ ํจ์ฌ ๋ณต์กํฉ๋๋ค. ์ฌ์ ํ ์ผ๋ฐ์ ์ธ ์ปดํฌ๋ํธ (์๋ก์ด ํจ๋ฌ๋ค์์์ ์ด๋ฅผ Client Components๋ผ๊ณ ํฉ๋๋ค. ๊ทธ๋ฌ๋ ์ฌ์ค ํด๋ผ์ธ์ธํธ ์ปดํฌ๋ํธ๋ ํด๋ผ์ด์ธํธ์ ์๋ฒ ๋ชจ๋์์ ๋ ๋๋ง๋ฉ๋๋ค. ์ด๋ฆ์ ์์ง ๋ง์๋ค.)
(์๋ฒ ์ปดํฌ๋ํธ๋ JS ๋ฒ๋ค์ ํฌํจ๋์ง ์์ผ๋ฏ๋ก Hydrate๋๊ฑฐ๋ ๋ฆฌ๋ ๋๋ง๋์ง ์์ต๋๋ค.)
ํ ์์ React Server Components๋ฅผ ํ์ฉํ ์ ์๋ ๋ฐฉ๋ฒ์ NextJS 13.4+๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ๋ฐ์ ์์ต๋๋ค. ๊ทธ ์ค์์๋ App router๋ฅผ ์ฌ์ฉํด์ผ ํฉ๋๋ค. ํฅํ์ ๋ ๋ง์ ๋ฆฌ์กํธ ๊ธฐ๋ฐ ํ๋ ์์ํฌ๊ฐ Server Components๋ฅผ ํตํฉํ๊ธฐ ์์ํ ๊ฒ์ผ๋ก ๊ธฐ๋ํฉ๋๋ค.
React Server Components๋ผ๋ ์๋ก์ด ํจ๋ฌ๋ค์ ์์์ ๋ชจ๋ ์ปดํฌ๋ํธ๋ ์๋ฒ ์ปดํฌ๋ํธ๋ก ๊ธฐ๋ณธ์ ์ผ๋ก ๊ฐ์ฃผ๋ฉ๋๋ค. ๋๋ฌธ์ ์ด๋ค ์ปดํฌ๋ํธ๋ฅผ ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ๋ก ์ฌ์ฉํ๋ ค๋ฉด ๋ฐ๋ก ์ปดํฌ๋ํธ์ ํ์ํด์ฃผ์ด์ผ ํฉ๋๋ค.
'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 ๋ฒ๋ค์ ํฌํจ๋์ด ํด๋ผ์ด์ธํธ์์ ๋ค์ ๋ ๋๋ง๋ ์ ์์ต๋๋ค. ์ด์ํ๊ฒ ๋ณด์ผ ์ ์์ง๋ง ์ฐ๋ฆฌ๋ Strict Mode๋ฅผ ์ง์ ํ๊ธฐ ์ํด "use strict"๋ผ๋ ์ง์๋ฌธ์ ํ์ฉํด๋ณธ ๊ฒฝํ์ด ์์ต๋๋ค. ์๋ฒ ์ปดํฌ๋ํธ๋ฅผ ์ง์ ํ๊ธฐ ์ํด "use server"๋ฅผ ์ ์ง๋ ์์ต๋๋ค. "use server"๋ ์์ ํ ๋ค๋ฅธ ๊ธฐ๋ฅ์ธ "์๋ฒ ์ก์ (Server Action)"์ ํ์ฉ๋ฉ๋๋ค. (ํด๋น ๋ธ๋ก๊ทธ ํฌ์คํ ์ ๋ฒ์๋ฅผ ๋ฒ์ด๋ ๋ด์ฉ)
์ด๋ค ์ปดํฌ๋ํธ๊ฐ ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ์ฌ์ผ ํ ๊น์?
์ผ๋ฐ์ ์ธ ๊ท์น์ผ๋ก ๋ง์ฝ ์ปดํฌ๋ํธ๊ฐ ์๋ฒ ์ปดํฌ๋ํธ๊ฐ ๋ ์ ์๋ค๋ฉด ์๋ฒ ์ปดํฌ๋ํธ์ฌ์ผ ํฉ๋๋ค. ์๋ฒ ์ปดํฌ๋ํธ๋ ์ผ๋ฐ์ ์ผ๋ก ๊ฐ๋จํ๊ณ ์ดํดํ๊ธฐ ์ฝ์ต๋๋ค. ๋ํ ์ฑ๋ฅ์์ ์ด์ ์ด ์์ต๋๋ค. JS ๋ฒ๋ค์ ํฌํจ๋์ง ์๊ธฐ ๋๋ฌธ์ ๋๋ค. ๊ทธ๋ ๋ค๊ณ ํด์ ๊ฐ๋ฅํ ๋ง์ ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ๋ฅผ ์ ๊ฑฐํ๊ธฐ ์ํด ๋ ธ๋ ฅํ ํ์๋ ์์ต๋๋ค.
React Server Components๊ฐ ์ต์ํด์ง๋ ๊ณผ์ ์์ ๊ฐ์ฅ ๋จผ์ ๋ ์ค๋ฅธ ์ง๋ฌธ ์ค ํ๋๋ "ํ๋กญ์ค๊ฐ ๋ณ๊ฒฝ๋ ๋ ์ด๋ป๊ฒ ๋์ํ๋์?" ์์ต๋๋ค. ๋ค์๊ณผ ๊ฐ์ ์๋ฒ ์ปดํฌ๋ํธ๊ฐ ์๋ค๊ณ ๊ฐ์ ํฉ์๋ค.
function HitCounter({ hits }) {
return (
<div>
Number of hits: {hits}
</div>
);
}
์ฒซ ์๋ฒ์ฌ์ด๋์์ ๋ ๋๋ง ๋ ๋ ๋ค์๊ณผ ๊ฐ์ ๋งํฌ์ ์ ๊ฐ์ง ๊ฒ์ ๋๋ค.
<div>
Number of hits: 0
</div>
๊ทธ๋ฌ๋ ๋ง์ผ hits์ ๊ฐ์ด ๋ณ๊ฒฝ๋๋ค๋ฉด? HitCounter๋ ๋ฆฌ๋ ๋๋ง๋์ด์ผ ํ์ง๋ง, ์๋ฒ์ปดํฌ๋ํธ์ด๋ฏ๋ก ๋ค์ ๋ ๋๋ง๋ ์ ์์ต๋๋ค! ๋ค์๊ณผ ๊ฐ์ ์ปดํฌ๋ํธ ํธ๋ฆฌ๊ฐ ์๋ค๊ณ ๊ฐ์
ํด๋ด
์๋ค.
์ ๊ทธ๋ฆผ์ ๋ชจ๋ ์ปดํฌ๋ํธ๊ฐ ์๋ฒ ์ปดํฌ๋ํธ์ด๋ฉด ๋ง์ด๋ฉ๋๋ค. ์ด๋ค ํ๋กญ์ค๋ ๋ณ๊ฒฝ๋์ง ์์ํ ๋๊น์. ๊ทธ๋ฌ๋ Article ์ปดํฌ๋ํธ๊ฐ hits ์ํ ๋ณ์๋ฅผ ๊ฐ์ง๋ค๊ณ ๊ฐ์ ํด๋ด ์๋ค. state๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ์ฌ์ผ ํฉ๋๋ค.
Article์ด ๋ฆฌ๋ ๋๋ง๋๋ฉด ์์ ์ปดํฌ๋ํธ์ธ HitCounter์ Discussion๋ ๋ฆฌ๋ ๋๋ง๋ฉ๋๋ค. ๋๋ฌธ์ ๋ฆฌ์กํธํ์ ๊ท์น์ ์ถ๊ฐํ์ต๋๋ค. "use client" ์ง์๋ฌธ์ HitCounter์ Discussion์ ์ธ์คํด์ค๊ฐ ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ๋ก ๋ณํ๋์ด์ผ ํจ์ ์๋ฏธํฉ๋๋ค.
"use client" ์ง์๋ฌธ์ Article ์ปดํฌ๋ํธ์ ์ถ๊ฐํ๋ฉด ํด๋ผ์ด์ธํธ ๊ฒฝ๊ณ๊ฐ ๋ง๋ค์ด์ง๋ ๊ฒ์ ๋๋ค. ์ด ๊ฒฝ๊ณ ๋ด์ ๋ชจ๋ ์ปดํฌ๋ํธ๋ ์์์ ์ผ๋ก ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ๋ก ๋ณํ๋ฉ๋๋ค. HitCounter์ ๊ฐ์ ์ปดํฌ๋ํธ์ "use client" ์ง์๋ฌธ์ด ์๋๋ผ๋ ํน์ ์ํฉ์์๋ ์ฌ์ ํ ํด๋ผ์ด์ธํธ์์ ์ํ๋๊ฑฐ๋ ๋ ๋๋ง๋ฉ๋๋ค. ๊ฒฐ๊ตญ ๋ชจ๋ ํ์ผ์ ์ผ์ผ์ด "use client"๋ฅผ ์์ฑํด์ค ํ์๋ ์๋ค๋ ๋ป์ ๋๋ค.
์ฑ์ ์ต์๋จ์์ ์ํ๋ฅผ ์ฌ์ฉํด์ผ ํ ๊ฒฝ์ฐ๋ ์์ ํ ๋ฐ, ๊ทธ๋ ๋ค๋ฉด ๋ชจ๋ ์ปดํฌ๋ํธ๋ฅผ ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ๋ก ๋ง๋ค์ด์ผ ํ๋ค๋ ๋ง์ผ๊น์? ์ฐ๋ฆฌ๋ ์ํ๋ฅผ ์์ ํ๋ ์ปดํฌ๋ํธ๋ฅผ ์กฐ์ ํด, ์ด ์ ํ์ ๊ทน๋ณตํ ์ ์์ต๋๋ค. ์์ ๋ฅผ ์ดํด๋ด ์๋ค.
'use client';
import { DARK_COLORS, LIGHT_COLORS } from '@/constants.js';
import Header from './Header';
import MainContent from './MainContent';
function Homepage() {
const [colorTheme, setColorTheme] = React.useState('light');
const colorVariables = colorTheme === 'light'
? LIGHT_COLORS
: DARK_COLORS;
return (
<body style={colorVariables}>
<Header />
<MainContent />
</body>
);
}
๋คํฌ๋ชจ๋ ์ค์ ์์์ ๋๋ค. ๋คํฌ๋ชจ๋๋ body ํ๊ทธ์ css ๋ณ์๋ฅผ ์ ์ฉํ ์ ์๋๋ก ์ฑ ํธ๋ฆฌ์์ ๋์ ์์น์ ์ง์ ๋์ด์ผ ํฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ํ๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด Homepage๋ฅผ ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ๋ก ๋ง๋ค์ด์ผ ํฉ๋๋ค. ์ด๋ ์ฑ์ ์ต์๋จ์ด๋ฏ๋ก ๋ค๋ฅธ ๋ชจ๋ ์ปดํฌ๋ํธ๋ ์์์ ์ผ๋ก ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ๊ฐ ๋ ๊ฒ์ ๋๋ค. ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด theme ๊ด๋ฆฌ ๋ด์ฉ์ ์์ฒด ์ปดํฌ๋ํธ๋ก ๋ถ๋ฆฌํ๊ณ ๋ณ๋์ ํ์ผ๋ก ์ด๋์ํค๊ฒ ์ต๋๋ค.
// /components/ColorProvider.js
'use client';
import { DARK_COLORS, LIGHT_COLORS } from '@/constants.js';
function ColorProvider({ children }) {
const [colorTheme, setColorTheme] = React.useState('light');
const colorVariables = colorTheme === 'light'
? LIGHT_COLORS
: DARK_COLORS;
return (
<body style={colorVariables}>
{children}
</body>
);
}
์ด์ Homepage.js๋ ๋ค์๊ณผ ๊ฐ์ด ์ ๋ฆฌ๋ฉ๋๋ค.
// /components/Homepage.js
import Header from './Header';
import MainContent from './MainContent';
import ColorProvider from './ColorProvider';
function Homepage() {
return (
<ColorProvider>
<Header />
<MainContent />
</ColorProvider>
);
}
Homepage์์ ์ํ ๋๋ ๋ค๋ฅธ ํด๋ผ์ด์ธํธ ์ธก ๋ฆฌ์กํธ ๊ธฐ๋ฅ์ ํ์ฉํ์ง ์์ผ๋ฏ๋ก, Homepage์์ "use client"๋ฅผ ์ ๊ฑฐํ ์ ์์ต๋๋ค. ์ด์ Header์ MainContent๋ ๋ ์ด์ ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ๋ก ์์์ ์ผ๋ก ๋ณํ๋์ง ์์ต๋๋ค. ColorProvider๊ฐ ์ฌ์ ํ Header์ MainContent์ ๋ถ๋ชจ๊ฐ ์๋๋๊ณ ์๊ฐํ ์ ์์ต๋๋ค. ๊ทธ๋ฌ๋ client boundries์์ ๋ถ๋ชจ/์์ ๊ด๊ณ๋ ์ค์์น ์์ต๋๋ค. ์ ํํ ๋งํ๋ฉด "use client" ์ง์๋ฌธ์ ํ์ผ/๋ชจ๋ ์์ค์์ ์๋ํฉ๋๋ค. ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ ํ์ผ์์ ๊ฐ์ ธ์จ ๋ชจ๋ ๋ชจ๋๋ ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ ์ฌ์ผ ํฉ๋๋ค.
์ด๋ป๊ฒ ์ปฌ๋ฌ theme์ ๋ณ๊ฒฝํ๋์?
์์ ์์์๋ ํ ๋ง๋ฅผ ๋ณ๊ฒฝํ๋ ์ฝ๋๊ฐ ์์ต๋๋ค. ๊ฐ๊ฒฐํ๊ฒ ์์๋ฅผ ์์ฑํ๊ธฐ ์ํด ํด๋น ๋ด์ฉ์ ๊ณ ์๋ก ์๋ตํ์ต๋๋ค. React ์ปจํ ์คํธ๋ฅผ ํ์ฉํ์ฌ, setterํจ์๋ฅผ ํ์ ์ปดํฌ๋ํธ์์ ์ฌ์ฉํ ๊ฒ์ ๋๋ค. ์ด ๊ฒฝ์ฐ ์ปจํ ์คํธ๋ฅผ ์์ํ๋ ์ปดํฌ๋ํธ๊ฐ ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ๋ผ๋ฉด ๋ชจ๋ ๊ฒ์ด ์ํํ ๋์ํ ๊ฒ์ ๋๋ค.
์๋ฒ ์ปดํฌ๋ํธ๋ฅผ ์ฌ์ฉํ ๋ ์ถ๋ ฅ์ ์ด๋ป๊ฒ ๋ณด์ด๊ณ ์ค์ ๋ก ์์ฑ๋๋ ๊ฒ์ ๋ฌด์์ผ๊น์? ๋งค์ฐ ๊ฐ๋จํ ์์๋ก ์์ํด๋ด ์๋ค.
function Homepage() {
return (
<p>
Hello world!
</p>
);
}
์ ์ปดํฌ๋ํธ๋ ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ๋ผ๊ณ ํ์ํ์ง ์์์ผ๋ฏ๋ก ์๋ฒ์์๋ง ๋ ๋๋ง๋ฉ๋๋ค. ๋ธ๋ผ์ฐ์ ์์ ์ด ์ฑ์ ๋ฐฉ๋ฌธํ๋ฉด ๋ค์๊ณผ ๊ฐ์ html ๋ฌธ์๋ฅผ ๋ฐ๊ฒ ๋ฉ๋๋ค.
<!DOCTYPE html>
<html>
<body>
<p>Hello world!</p>
<script src="/static/js/bundle.js"></script>
<script>
self.__next['$Homepage-1'] = {
type: 'p',
props: null,
children: "Hello world!",
};
</script>
</body>
</html>
์ดํด๋ฅผ ๋๊ธฐ ์ํ ์ฌ๊ตฌ์กฐํ
์ html์์ ์ค์ ์์ฑ๋ ๊ฒฝ์ฐ์๋ ๋ฌธ์ ํ์ผ ํฌ๊ธฐ๋ฅผ ์ค์ด๊ธฐ ์ํ ์ต์ ํ๋ก ๋ฌธ์์ฌ๋กํ๋ JSON ๋ฐฐ์ด์ ํ์ฉํฉ๋๋ค. ๋ํ head ํ๊ทธ ๋ฑ์ ๋น ํต์ฌ์์๋ ๋ชจ๋ ์ ๊ฑฐํ์ต๋๋ค.
์ ๋ด์ฉ์ ์ดํด๋ณด๋ฉด, JS ๋ฒ๋ค์ ๋ก๋ํ๋ ์คํฌ๋ฆฝํธ ํ๊ทธ๊ฐ ์์ต๋๋ค. ์ด ๋ฒ๋ค์๋ ๋ฆฌ์กํธ์ ๊ฐ์ ์ข ์์ฑ ๋ฟ ์๋๋ผ, ์ฑ์์ ์ฌ์ฉํ๋ ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ๋ ํฌํจ๋ฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ Homepage ์ปดํฌ๋ํธ๊ฐ ์๋ฒ ์ปดํฌ๋ํธ์ด๋ฏ๋ก ์ด ์ปดํฌ๋ํธ์ ์ฝ๋๋ ์ด ๋ฒ๋ค์ ํฌํจ๋์ง ์์ต๋๋ค. ๊ทธ ๋ฐ์๋ ์ธ๋ผ์ธ JS๊ฐ ํฌํจ๋ ๋ ๋ฒ์งธ ์คํฌ๋ฆฝํธ ํ๊ทธ๊ฐ ์์ต๋๋ค.
self.__next['$Homepage-1'] = {
type: 'p',
props: null,
children: "Hello world!",
};
์ ๋ด์ฉ์ด ํ๋ ์ญํ ์, ๋ฆฌ์กํธ์๊ฒ "์๊ฒ ์ด, Homepage ์ปดํฌ๋ํธ ์ฝ๋๊ฐ ๋๋ฝ๋์์ง? ์ฌ๊ธฐ์ ์ด๊ฒ ๋ ๋๋ง๋ ๋ด์ฉ์ด์ผ"๋ผ๊ณ ์๋ ค์ฃผ๋ ๊ฒ์ ๋๋ค. ์ผ๋ฐ์ ์ผ๋ก ๋ฆฌ์กํธ๋ ํด๋ผ์ด์ธํธ์์ ๋ ๋๋งํ ๋ ๊ฐ์DOM์ ๋น๋ํฉ๋๋ค. ๊ทธ๋ฌ๋ ์๋ฒ ์ปดํฌ๋ํธ์๋ ์ด๋ฅผ ์คํํ ์ ์์ต๋๋ค. JS ๋ฒ๋ค์ ์ฝ๋๊ฐ ์์ผ๋๊น์. ๊ทธ๋์ ์ด๋ ํด๋ผ์ด์ธํธ์์ ๋ฆฌ์กํธ๊ฐ ๋ก๋๋ ๋, ๊ฐ์DOM ๋น๋์ ํ์ฉํ ์ ์๋๋ก ์์ ๊ฐ์ ์คํฌ๋ฆฝํธ๊ฐ ํฌํจ๋๋ ๊ฒ์ ๋๋ค.
์ด๊ฒ์ด ColorProvider๊ฐ ๋์ํ๋ ์๋ฆฌ์ ๋๋ค. Header์ MainContent์์ ๋์จ ์ถ๋ ฅ๋ฌผ์ children ํ๋กญ์ ํตํด ColorProvider ์ปดํฌ๋ํธ๋ก ์ ๋ฌ๋ฉ๋๋ค. ColorProvider๋ ์ผ๋ง๋ ๋ฆฌ๋ ๋ ๋ ์ ์์ต๋๋ค. ๊ทธ๋ฌ๋ ์ด ๋ฐ์ดํฐ(Homepage๋ผ๋ ์๋ฒ ์ปดํฌ๋ํธ๋ฅผ ์ง์นญํ๋ ๊ฒ์ผ๋ก ๋ณด์ธ๋ค.)๋ ์๋ฒ์ ๊ณ ์ ๋์ด ์๊ณ ๋ณ๊ฒฝ๋์ง ์์ต๋๋ค. ๋ง์ผ ์ด๋ป๊ฒ ์๋ฒ ์ปดํฌ๋ํธ๊ฐ ์๋ฆฌ์ผ๋ผ์ด์ฆ๋๊ณ ๋คํธ์ํฌ๋ก ์ ์ก๋๋์ง ์ค์ ํํ์ ๋ณด๊ณ ์ถ๋ค๋ฉด ๊ฐ๋ฐ์ Alvar Lagerlรถf์ RSC Devtools๋ฅผ ์ดํด๋ณด์ธ์!
์ฌ์ค 2016๋ ํ๋ก NextJS์์ ์๋ฒ์ ์ฉ ์ฝ๋๋ฅผ ์คํํ ์ ์์์ต๋๋ค. ๊ฐ์ฅ ํฐ ์ฐจ์ด์ ์ ์ด์ ์๋ ์ปดํฌ๋ํธ ๋ด์์ ์๋ฒ ์ ์ฉ ์ฝ๋๋ฅผ ์คํํ ๋ฐฉ๋ฒ์ด ์์๋ค๋ ๊ฒ์ด์ฃ . ์ฌ์ค ๊ฐ์ฅ ๋ช ๋ฐฑํ ์ด์ ์ ์ฑ๋ฅ์ ๋๋ค. ์๋ฒ ์ปดํฌ๋ํธ๋ JS ๋ฒ๋ค์ ํฌํจ๋์ง ์์ผ๋ฏ๋ก ๋ค์ด๋ก๋ํด์ผ ํ๋ JS ์๊ณผ ์ํํด์ผ ํ๋ ์ปดํฌ๋ํธ์ ์๊ฐ ์ค์ด๋ญ๋๋ค.
์ฌ์ค NextJS ์ฑ์ ํ์ด์ง์ธํฐ๋ํฐ๋ธ ํ์ด๋ฐ์ ๋ํ ์ฑ๋ฅ๋ฉด์์ ์ถฉ๋ถํ ๋น ๋ฆ ๋๋ค. ์๋ฏธ๋ก ์ html ์์น์ ๋ฐ๋ฅด๋ฉด ๋ฆฌ์กํธ๋ ํ์ด๋๋ ์ดํธ ๋๊ธฐ ์ ์ ์ด๋ฏธ ์๋ํด์ผ ํฉ๋๋ค. link๋ form, accordions ๋ฑ. ๋๋ถ๋ถ์ ํ๋ก์ ํธ์์ React๊ฐ hydrate๋๊ธฐ๊น์ง ๋ช์ด๊ฐ ๊ฑธ๋ ค๋ ๊ด์ฐฎ์ต๋๋ค. ํ์ง๋ง ์ฌ๊ธฐ์ ์ ๋ง ์ค์ํ ์ ์ ๊ธฐ๋ฅ vs ๋ฒ๋ค ํฌ๊ธฐ๋ฅผ ๊ฐ๊ณ ๋ ์ด์ ํ์ชฝ์ ํฌ๊ธฐํ๊ฑฐ๋ ํํํ์ง ์์๋ ๋๋ค๋ ์ ์ ๋๋ค. ์๋ฅผ ๋ค์ด ๋๋ถ๋ถ์ ๊ธฐ์ ๋ธ๋ก๊ทธ์๋๋ ๊ตฌ๋ฌธ ๊ฐ์กฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ํ์ํฉ๋๋ค.
function exampleJavaScriptFunction(param) {
return "Hello world!"
}
๋ชจ๋ ์ธ๊ธฐ์๋ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด๋ฅผ ์ง์ํ๋ ๊ตฌ๋ฌธ ๊ฐ์กฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ JS ๋ฒ๋ค์ ๋ฃ๊ธฐ์๋ ๋๋ฌด ํฝ๋๋ค. ๊ฒฐ๊ณผ์ ์ผ๋ก ์ฐ๋ฆฌ๋ ๋ฒ๋ค์ฌ์ด์ฆ๋ฅผ ์ค์ด๊ธฐ ์ํด์ ์ธ์ด์ ๊ธฐ๋ฅ์ ์ ๋ฆฌํ๊ณคํฉ๋๋ค. ๊ทธ๋ฌ๋ ์๋ฒ ์ปดํฌ๋ํธ์์ ๊ตฌ๋ฌธ ๊ฐ์กฐ๋ฅผ ์ํํ๋ค๊ณ ํ๋ฉด, ์ฐ๋ฆฌ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ฝ๋๊ฐ ์ค์ ๋ก JS ๋ฒ๋ค์ ํฌํจ๋์ง ์์ผ๋ฏ๋ก ์ด๋ค ํํ๋ ํ ํ์๊ฐ ์์ต๋๋ค. ์ด๊ฒ์ด React Server Components์ ํจ๊ป ์๋ํ๋๋ก ์ค๊ณ๋ ํ๋์ ์ธ ๊ตฌ๋ฌธ ๊ฐ์กฐ ํจํค๊น์ธ Bright์ ํฐ ์์ด๋์ด์ ๋๋ค.
JS๋ฒ๋ค์ ํฌํจํ๊ธฐ์๋ ๋๋ฌด ๋ง์ ๋น์ฉ์ ์ง๋ถํด์ผ ํ๋ ๊ฒ๋ค์ด ์๋ฒ์์ ๋ฌด๋ฃ๋ก ์คํ๋ ์ ์์ผ๋ฉฐ, ๋ฒ๋ค์ ๋จ 1kb๋ ์ถ๊ฐํ์ง ์์ผ๋ฉด์ ์ฌ์ฉ์ ๊ฒฝํ์ ๊ฐ์ ํ ์ ์์ต๋๋ค.
์ฑ๋ฅ๊ณผ ์ฌ์ฉ์ ๊ฒฝํ๋งํผ ์ค์ํ ๊ฒ์ ์๋์ง๋ง Server Component๋ ๊ทธ ๋ฌธ๋ฒ์ด ๋งค์ฐ ๊ฐ๊ฒฐํ๊ณ ์ฝ์ต๋๋ค. ์ข ์์ฑ ๋ฐฐ์ด, ํด๋ก์ , ๋ฉ๋ชจ์ด์ ์ด์ ๋ฑ์ผ๋ก ๋ ์ด์ ๊ณ ๋ฏผํ์ง ์์๋ ๊ด์ฐฎ์ต๋๋ค. ๋ฌผ๋ก ์ง๊ธ์ ์์ง ์ด๊ธฐ๋จ๊ณ์ ๋๋ค. ์ปค๋ฎค๋ํฐ๊ฐ ์๋ก์ด ํจ๋ฌ๋ค์์ ํ์ฉํด Bright์ ๊ฐ์ ์๋ก์ด ์๋ฃจ์ ์ ์ง์์ ์ผ๋ก ๋ฐ๊ฒฌํด๋๊ฐ๊ธธ ๊ธฐ๋ํฉ๋๋ค.
๋ React Server Components๋ ๋งค์ฐ ํฅ๋ฏธ๋ก์ด ๋ฐ์ ์ ๋๋ค๋ง ์ค์ ๋ก๋ ๋ชจ๋ ๋ฆฌ์กํธ์ ์ผ๋ถ์ ๋๋ค. React Server Components๋ฅผ Suspense์ Streaming SSR ์ํคํ ์ฒ์ ๊ฒฐํฉํ ๋ ์ ๋ง ํฅ๋ฏธ๋ก์์ง ๊ฒ์ ๋๋ค.