React์ Next.js์ Rendering ๋ฐฉ์
csr,ssr๋ง ์๋๊ฒ ์๋๋ผ๊ตฌ~
๐ต ๋ค์ด๊ฐ๋ฉฐ
๋ฆฌ์กํธ์ ๋ฅ์คํธ์ ์ฐจ์ด์ ์ด๋ผ ํ๋ฏ ๋ ๋๋ง์ ์ด๋์ ํ๋๋๋ฉฐ, CSR๊ณผ SSR ์ ์ฐจ์ด๋ผ๊ณ ๋ง ์๊ฐํ๋ค. ํ์ง๋ง SSR์๋ ์ข ๋ฅ๊ฐ ์ฌ๋ฌ๊ฐ์ง๊ฐ ์์๋๋ฐ,,! ์ ํํ๋ Next.js์ ๋ ๋๋ง ์ข ๋ฅ์ ์ฌ๋ฌ๊ฐ์ง๊ฐ ์๋๋ฐ,,! ๋ฅผ ๊นจ๋ซ๊ณ ์จ๋ณด๋ ์ค๋์ ํฌ์คํ ์ด๋ค.
๐ฅ ๊ธฐ๋ณธ ๊ฐ๋ ์ ๋ฆฌ
React์ Rendering
๋ฆฌ์กํธ์์๋ ๋ธ๋ผ์ฐ์ ๊ฐ ์๋ฒ์์ JavaScript, CSS, HTML ํ์ผ์ ๋ค์ด๋ก๋ํ ํ, JavaScript๊ฐ ์คํ๋์ด ํ๋ฉด์ ๋ ๋๋งํ๋ค. ์ด ๊ณผ์ ์์ ์ฌ์ฉ์๋ ์ด๊ธฐ์ ๋น ํ๋ฉด์ ๋ณด๊ฒ ๋๋ฉฐ, ์ด๊ธฐ ๋น ๊ป๋ฐ๊ธฐ์ธ html๋ก ์ธํด ๊ฒ์์์ง์ต์ ํ(SEO)๊ฐ ๋ถ๋ฆฌํ๋ค.
Next.js์ Pre-rendering
ํ์ด์ง์ HTML์ ๋ฏธ๋ฆฌ ์์ฑํ๋ ๊ธฐ๋ฅ์ผ๋ก, ์ฌ์ฉ์๊ฐ ์์ฒญํ๊ธฐ ์ ์ ์๋ฒ๋ ๋น๋ ๋จ๊ณ์์ HTML์ ์ค๋นํด ๋๋ ๊ฒ์ ๋ปํ๋ค. ๊ทธ๋ก์ธํด ์ด๋ฏธ ์ค๋น๋ HTML๋ก ์ฌ์ฉ์๋ ๊ธฐ๋ค๋ฆผ ์์ด ํ๋ฉด์ ๋ณผ ์ ์๊ณ , SEO๊ฐ ๊ฐ์ ๋๋ค.
Hydration
Next.js์์ Pre-rendering์ HTML๊ณผ CSS๋ง์ ์ค๋นํด๋ ์ํ๋ก ๋น ๊ป๋ฐ๊ธฐ์ ๋ถ๊ณผํ๋ค. ๋ธ๋ผ์ฐ์ ์์ JavaScript๊ฐ ์คํ๋๊ธฐ ์ ๊น์ง๋ ํ์ด์ง์ ์ฌ์ฉ์๊ฐ ์ํธ์์ฉํ ์ ์๋ค. ์๋ฅผ ๋ค์ด, ๋ฒํผ๊ณผ ๊ฐ์ ์ปดํฌ๋ํธ๋ ์ด๊ธฐ์๋ ๋์ํ์ง ์๋ ๊ฒ์ด๋ค. ๋ธ๋ผ์ฐ์ ๊ฐ JavaScript ์ฝ๋๋ฅผ ์คํํ์ฌ React ์ปดํฌ๋ํธ์ HTML์ ์ฐ๊ฒฐํ๊ณ , ๋์์ ํ์ฑํํ๋ ๊ณผ์ ์ด ์งํ๋๋๋ฐ, ์ด๋ฅผ Hydration์ด๋ผ๊ณ ํ๋ค.
๐ธ Next.js์ Rendering
์์ ๊ฐ๋ ์์ ์ ๋ฆฌํ๋ ๊ฒ ์ฒ๋ผ ํด๋ผ์ด์ธํธ(1)์ ์๋ฒ๋จ(3)์์ ๋ ๋๋ง ํ ์ ์๋ค. ๋ถ๋ฅ๋ฅผ ํ๋ฉด ์๋์ ์ด 4๊ฐ์ง์ ๋ ๋๋ง ๋ฐฉ์์ด ์กด์ฌํ๋ค. ์ด๋ Next.js 13 ๋ฒ์ ๊ธฐ์ค์ ๋ฐฉ์์ด๋ค.
CSR: Client Side Rendering
- ํด๋ผ์ด์ธํธ์์ ์ง์ ๋ฐ์ดํฐ๋ฅผ fetchํ๋ ๋ฐฉ์
- ์ฝ๋ ์๋จ์ โuse clientโ ๊ตฌ๋ฌธ์ ์ถ๊ฐํ๋ฉด ๊ธฐ์กด ๋ฆฌ์กํธ ๋ฐฉ์์ฒ๋ผ CSR ๋ฐฉ์์ ๊ตฌํํ ์ ์๋ค.
- ์๋ ๋ ๋๋ง ๊ฒฐ๊ณผ๋ ๋ ๋๋ง์์ ์๊ฐ์ ๊ทธ๋๋ก ์ถ๋ ฅํ๋ค. ์๋ก๊ณ ์นจ ๋ง๋ค ์๊ฐ์ด ๋ณ๊ฒฝ๋์ด ๋ฐ์ดํฐ๋ฅผ ๊ณ์ ์์ฒญํ๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
"use client";
import { useEffect, useState } from "react";
export default function CSRPage() {
const [time, setTime] = useState<string>("");
useEffect(() => {
const getTime = async () => {
const res = await fetch(
"http://worldtimeapi.org/api/timezone/Asia/Seoul",
{
cache: "no-store",
}
);
const data = await res.json();
setTime(data.datetime);
};
getTime();
}, []);
return <div>CSR: {time}</div>;
}
SSR: Server Side Rendering
- ์ฌ์ฉ์๊ฐ ์์ฒญํ์ ๋, ์๋ฒ์์ ๋ฐ๋ก ์์ฑํ์ฌ ์ ๊ณต๋๋ค.
- ์์ฒญ ๋ง๋ค ๋ค๋ฅธ ๋ฐ์ดํฐ๊ฐ ๋ณด์ฌ์ง๋ ํ์ด์ง์ ์ ํฉํ ๋ ๋๋ง ๋ฐฉ์ ์ด๋ค.
- SSR ๋ฐฉ์ ์ญ์, ๋ ๋๋ง์ ์์ฒญํ ์์ ์ ์๊ฐ์ ์ถ๋ ฅํ๋ฉฐ ๋งค๋ฒ ์๋ก์ด ๋ฐ์ดํฐ ํธ์ถ๋ก ์๊ฐ์ด ๋ณ๊ฒฝ๋๋ค.
export default async function SSRPage() {
const res = await fetch("http://worldtimeapi.org/api/timezone/Asia/Seoul", {
cache: "no-store",
});
const data = await res.json();
return <div>SSR: {data.datetime}</div>;
}
SSG: Static Site Generation
- ํ์ด์ง๊ฐ ๋น๋ ์์ ์ ๋ฏธ๋ฆฌ ์์ฑ๋์ด ์๋ฒ์ ์ ๊ณต๋ ๋, ๋ฏธ๋ฆฌ ๋ง๋ค์ด๋ HTML์ ์ฌ์ฌ์ฉํ๋ ๋ ๋๋ง ๋ฐฉ์์ด๋ค.
- ๋ณ๊ฒฝ๋์ง ์๋ ์ฝํ ์ธ ์ ์ ํฉํ๋ค.
- ํด๋น ์ด๋ฏธ์ง๋ฅผ ์ฐธ๊ณ ํ๋ฉด, ๋น๋ ์์ ์ ์ฅ๋ ์๊ฐ์ผ๋ก๋ง ๊ณ์ ์ถ๋ ฅํ์ฌ ์ ๋ฐ์ดํธํ์ง ์๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
export default async function SSGPage() {
const res = await fetch("https://worldtimeapi.org/api/timezone/Asia/Seoul");
const data = await res.json();
return <div>SSG: {data.datetime}</div>;
}
ISR: Incremental Static Regeneration
- SSG์ SSR์ ์ค๊ฐ ํํ๋ก, ํ์ด์ง๋ ๋น๋ ์ ์์ฑ๋์ง๋ง ํน์ ์๊ฐ๋ง๋ค ์๋ฒ์์ ๋ค์ ์์ฑํ์ฌ ์ฃผ๊ธฐ์ ์ผ๋ก ์ ๋ฐ์ดํธ๊ฐ ๊ฐ๋ฅํ๋ค.
- ์ฝ๋์์ 10์ด๋ง๋ค ๊ฐฑ์ ํ๋ ์ ๋ฐ์ดํธ ์ฃผ๊ธฐ๋ฅผ ์ต์ ์ผ๋ก ์ถ๊ฐํ์๋๋ฐ, ์๋ก๊ณ ์นจ ์ ๋ณ๋ํ๋ ์๊ฐ์ ํ์ธํ ์ ์๋ค.
export default async function ISRPage() {
const res = await fetch("http://worldtimeapi.org/api/timezone/Asia/Seoul", {
next: { revalidate: 10 },
}); // 10์ด๋ง๋ค ๊ฐฑ์
const data = await res.json();
return <div>ISR: {data.datetime}</div>;
}
๐ ๋ง๋ฌด๋ฆฌ
CSR ์์ฒด๋ ํด๋ผ์ด์ธํธ ๋จ์์ ๋๋ถ๋ถ์ ์์ ์ ์ํํ๊ธฐ ๋๋ฌธ์ ์๋ฒ๊ฐ ํ๋ ์ญํ ์ด ๊ฑฐ์ ์๋ค. ๋ฐ๋ฉด์ SSR์ ์๋ฒ์์ ๊ณ์ ์๋ก์ด HTML์ ๋ง๋ค์ด๋ด์ผ ํ๊ธฐ ๋๋ฌธ์ ์๋์ ์ผ๋ก ๋ถํ๊ฐ ์ฌ ์ ๋ฐ์ ์๋ค. ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ ์ฌ์ฉ์์๊ฒ ๋ณด์ฌ์ค ํ๋ฉด์ ๋ฐ๋ผ ๋ค๋ฅธ ๋ ๋๋ง ๋ฐฉ์์ ์ฑํํ๋ ๊ฒ์ ์ฌ์ฉ์ ๊ฒฝํ๊ณผ ์ฑ๋ฅ ์ธก๋ฉด์์ ๋งค์ฐ ์ด์ ์ด ์๋ค. ์ ์ด๊ฑธ ์ง๊ธ์์ผ ์ ๋ฆฌํ์๊น ๋ฐ์ฑ + ์ค๋ ์ ๋ฆฌํ ๊ฐ๋ ์ ๋ฐํ์ผ๋ก ๋ ๋์ ์ฌ์ดํธ๋ฅผ ๋ง๋ค ์ ์์ ๊ฒ ๊ฐ์ ์์ ๊ฐ๊ณผ ํจ๊ป,,,๋ฅ์คํธ๋ฅผ ๋ ์ ์ดํดํ ๋ฏ ํ ๋๋์ ๊ฐ์ ธ๊ฐ๋ฉฐ,, ์ค๋์ ํฌ์คํ ๋ง๋ฌด๋ฆฌํด๋ณด๊ฒ ๋ค.๐ค