๐ Next.js๋ก ์๋ฒ์ฌ์ด๋ ๋ ๋๋ง(SSR) ๊ตฌํํ๊ธฐ: ์ด๋ณด์๋ ์ฝ๊ฒ ๋ฐ๋ผํ๋ ๊ฐ์ด๋! ๐จ

์๋ ํ์ธ์, ์ฌ๋ฌ๋ถ! ์ค๋์ ์ ๋ง ํซํ ์ฃผ์ ๋ก ์ฐพ์์์ด์. ๋ฐ๋ก Next.js๋ฅผ ์ฌ์ฉํด์ ์๋ฒ์ฌ์ด๋ ๋ ๋๋ง(SSR)์ ๊ตฌํํ๋ ๋ฐฉ๋ฒ์ ๋ํด ์์๋ณผ ๊ฑฐ์์. ์ด๊ฑฐ ์์ ํธ๋ ๋ํ๊ณ ์ค์ฉ์ ์ธ ์คํฌ์ด๋ผ ๊ผญ ์์๋ฌ์ผ ํด์! ๐ฅ
์ฌ๋ฌ๋ถ, ํน์ ์น ๊ฐ๋ฐํ ๋ ํด๋ผ์ด์ธํธ ์ฌ์ด๋ ๋ ๋๋ง(CSR)๋ง ์ฌ์ฉํ๋ค๊ฐ "์ ์ด๊ฑฐ ์ข ๋๋ฆฐ๋ฐ?" ํ๊ณ ๊ณ ๋ฏผํด๋ณธ ์ ์๋์? ๊ทธ๋ ๋ค๋ฉด ์ค๋์ ์ฃผ์ ๊ฐ ์ฌ๋ฌ๋ถ์๊ฒ ๋ฑ์ด์์! SSR์ ํ์ด์ง ๋ก๋ฉ ์๋๋ฅผ ๋น ๋ฅด๊ฒ ๋ง๋ค์ด์ฃผ๋ ๋ง๋ฒ ๊ฐ์ ๊ธฐ์ ์ด๊ฑฐ๋ ์. โจ
๊ทธ๋ผ ์ด์ ๋ถํฐ Next.js๋ก SSR์ ๊ตฌํํ๋ ๋ฐฉ๋ฒ์ ํ๋ํ๋ ์์ธํ ์์๋ณผ๊ฒ์. ์ด๋ ค์ด ๋ด์ฉ๋ ์๊ฒ ์ง๋ง, ์ ๊ฐ ์ต๋ํ ์ฝ๊ณ ์ฌ๋ฏธ์๊ฒ ์ค๋ช ํด๋๋ฆด ํ ๋ ๋๊น์ง ํจ๊ปํด์!
๐ก ์ฐธ๊ณ : ์ด ๊ธ์์ ์๊ฐํ๋ ๊ธฐ์ ๋ค์ ์น ๊ฐ๋ฐ์ ๊ด์ฌ ์๋ ๋ถ๋ค์๊ฒ ๋งค์ฐ ์ ์ฉํ ๊ฑฐ์์. ๋ง์ฝ ์ฌ๋ฌ๋ถ์ด ์น ๊ฐ๋ฐ ๊ด๋ จ ์ฌ๋ฅ์ ์ฐพ๊ณ ๊ณ์๋ค๋ฉด, ์ฌ๋ฅ๋ท(https://www.jaenung.net)์์ ๋ค์ํ ๊ฐ๋ฐ์๋ค์ ์ฌ๋ฅ์ ๋ง๋๋ณด์ธ์! ์ฌ๋ฌ๋ถ์ ํ๋ก์ ํธ์ ๋ฑ ๋ง๋ ๊ฐ๋ฐ์๋ฅผ ์ฐพ์ ์ ์์ ๊ฑฐ์์. ๐
1. Next.js์ SSR: ๊ธฐ๋ณธ ๊ฐ๋ ์ดํดํ๊ธฐ ๐ง
์, ๋จผ์ Next.js์ SSR์ด ๋ญ์ง ๊ฐ๋จํ ์์๋ณผ๊น์?
- Next.js: React ๊ธฐ๋ฐ์ ํ๋ ์์ํฌ์์. ์ฝ๊ฒ ๋งํด์ React๋ก ์น ์ฑ์ ๋ง๋ค ๋ ๋ ํธ๋ฆฌํ๊ฒ ๋ง๋ค์ด์ฃผ๋ ๋๊ตฌ๋ผ๊ณ ์๊ฐํ๋ฉด ๋ผ์.
- SSR(Server-Side Rendering): ์๋ฒ์์ ํ์ด์ง์ ๋ด์ฉ์ ๋ฏธ๋ฆฌ ๋ง๋ค์ด์ ๋ธ๋ผ์ฐ์ ๋ก ๋ณด๋ด์ฃผ๋ ๋ฐฉ์์ด์์. ์ด๋ ๊ฒ ํ๋ฉด ์ฒซ ํ์ด์ง ๋ก๋ฉ์ด ๋นจ๋ผ์ง๊ณ , ๊ฒ์ ์์ง ์ต์ ํ(SEO)์๋ ์ข๋ต๋๋ค.
Next.js๋ SSR์ ์์ฃผ ์ฝ๊ฒ ๊ตฌํํ ์ ์๊ฒ ํด์ค์. ๊ทธ๋์ ๋ง์ ๊ฐ๋ฐ์๋ค์ด Next.js๋ฅผ ์ ํํ๋ ๊ฑฐ์ฃ . ํนํ ์ฑ๋ฅ๊ณผ SEO๊ฐ ์ค์ํ ํ๋ก์ ํธ์์๋ ๊ฑฐ์ ํ์๋ผ๊ณ ๋ณผ ์ ์์ด์!
๐ค ์ ๊น, ์ SSR์ด ์ค์ํ ๊น์?
1. ๋น ๋ฅธ ์ด๊ธฐ ๋ก๋ฉ: ์ฌ์ฉ์๊ฐ ์ฒซ ํ์ด์ง๋ฅผ ๋นจ๋ฆฌ ๋ณผ ์ ์์ด์.
2. SEO ํฅ์: ๊ฒ์ ์์ง์ด ์ฝํ ์ธ ๋ฅผ ๋ ์ ์ดํดํ ์ ์์ด์.
3. ๋ ๋์ ์ฌ์ฉ์ ๊ฒฝํ: ํนํ ๋คํธ์ํฌ ์๋๊ฐ ๋๋ฆฐ ํ๊ฒฝ์์ ์ ์ฉํด์.
์ด์ ๊ธฐ๋ณธ ๊ฐ๋ ์ ์์์ผ๋, ๋ณธ๊ฒฉ์ ์ผ๋ก Next.js๋ก SSR์ ๊ตฌํํ๋ ๋ฐฉ๋ฒ์ ์์๋ณผ๊น์? ์ค๋น๋์ จ๋์? ๊ทธ๋ผ ๊ณ ๊ณ ! ๐
2. Next.js ํ๋ก์ ํธ ์์ํ๊ธฐ ๐ฌ
Next.js ํ๋ก์ ํธ๋ฅผ ์์ํ๋ ๊ฑด ์ ๋ง ์ฌ์์. ํฐ๋ฏธ๋์ ์ด๊ณ ๋ค์ ๋ช ๋ น์ด๋ฅผ ์ ๋ ฅํด๋ณด์ธ์:
npx create-next-app my-ssr-app
cd my-ssr-app
npm run dev
์์ฐ! ์ด๋ ๊ฒ ํ๋ฉด ๊ธฐ๋ณธ์ ์ธ Next.js ์ฑ์ด ์์ฑ๋๊ณ ์คํ๋ผ์. localhost:3000์ผ๋ก ๊ฐ๋ณด๋ฉด "Welcome to Next.js!" ํ์ด์ง๊ฐ ๋ณด์ผ ๊ฑฐ์์. ์ง์~ ๐
์ด์ ์ฐ๋ฆฌ๋ง์ SSR ํ์ด์ง๋ฅผ ๋ง๋ค์ด๋ณผ ์ฐจ๋ก์์. pages ํด๋ ์์ ์๋ก์ด ํ์ผ์ ๋ง๋ค์ด๋ณด์ธ์. ์๋ฅผ ๋ค์ด, pages/ssr-example.js
๋ผ๊ณ ํด๋ณผ๊น์?
import React from 'react';
export default function SSRExample({ data }) {
return (
<div>
<h1>SSR ์์ ํ์ด์ง</h1>
<p>์๋ฒ์์ ๊ฐ์ ธ์จ ๋ฐ์ดํฐ: {data}</p>
</div>
);
}
export async function getServerSideProps() {
// ์ฌ๊ธฐ์ ์๋ฒ ์ฌ์ด๋ ๋ก์ง์ ์คํํด์
const data = "์ด ๋ฐ์ดํฐ๋ ์๋ฒ์์ ์์ฑ๋์์ด์!";
return { props: { data } };
}
์ด ์ฝ๋๊ฐ ๋ฐ๋ก SSR์ ํต์ฌ์ด์์! getServerSideProps
ํจ์๊ฐ ์๋ฒ์์ ์คํ๋๊ณ , ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ์ปดํฌ๋ํธ์ props๋ก ์ ๋ฌํด์ค์. ์์ ์ ๊ธฐํ์ง ์๋์? ๐ฒ
๐ก ๊ฟํ: getServerSideProps
๋ ๋งค ์์ฒญ๋ง๋ค ์คํ๋ผ์. ๊ทธ๋์ ์ค์๊ฐ ๋ฐ์ดํฐ๊ฐ ํ์ํ ํ์ด์ง์ ๋ฑ์ด์์!
์, ์ด์ ๋ธ๋ผ์ฐ์ ์์ http://localhost:3000/ssr-example
๋ก ์ ์ํด๋ณด์ธ์. ์๋ฒ์์ ์์ฑ๋ ๋ฐ์ดํฐ๊ฐ ํ๋ฉด์ ํ์๋ ๊ฑฐ์์. ์ถํํด์! ์ฌ๋ฌ๋ถ์ ์ฒซ SSR ํ์ด์ง๊ฐ ์์ฑ๋์ด์! ๐
3. SSR์ ์ฅ์ ๊ทน๋ํํ๊ธฐ ๐ช
SSR์ ์ ๋๋ก ํ์ฉํ๋ ค๋ฉด ์ด๋ป๊ฒ ํด์ผ ํ ๊น์? ๋ช ๊ฐ์ง ํ์ ์๋ ค๋๋ฆด๊ฒ์:
- ๋ฐ์ดํฐ fetching ์ต์ ํ: ์๋ฒ์์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ฌ ๋๋ ๊ฐ๋ฅํ ๋นจ๋ฆฌ ๊ฐ์ ธ์ค์ธ์. ์บ์ฑ์ ํ์ฉํ๋ ๊ฒ๋ ์ข์ ๋ฐฉ๋ฒ์ด์์.
- ์ฝ๋ ๋ถํ : Next.js์ ๋์ ์ํฌํธ ๊ธฐ๋ฅ์ ํ์ฉํด์ ํ์ํ ์ฝ๋๋ง ๋ก๋ํ์ธ์.
- ์ด๋ฏธ์ง ์ต์ ํ: Next.js์ Image ์ปดํฌ๋ํธ๋ฅผ ์ฌ์ฉํ๋ฉด ์ด๋ฏธ์ง ์ต์ ํ๋ ์ฝ๊ฒ ํ ์ ์์ด์.
์ด๋ฐ ๋ฐฉ๋ฒ๋ค์ ํ์ฉํ๋ฉด SSR์ ์ฅ์ ์ ๊ทน๋ํํ ์ ์์ด์. ํ์ด์ง ๋ก๋ฉ ์๋๊ฐ ๋นจ๋ผ์ง๊ณ , ์ฌ์ฉ์ ๊ฒฝํ๋ ์ข์์ง ๊ฑฐ์์!
๐ ์ฑ๋ฅ ํฅ์ ํ: Next.js์ getStaticProps
์ getStaticPaths
๋ฅผ ํ์ฉํ๋ฉด ์ ์ ์์ฑ(Static Generation)๋ ํ ์ ์์ด์. ์์ฃผ ๋ณ๊ฒฝ๋์ง ์๋ ํ์ด์ง์๋ ์ด ๋ฐฉ๋ฒ์ด ๋ ํจ์จ์ ์ผ ์ ์๋ต๋๋ค!
4. SSR๊ณผ SEO: ๊ฒ์ ์์ง์ ์ฌ๋์ ๋ฐ์๋ณด์ โค๏ธ
SSR์ ํฐ ์ฅ์ ์ค ํ๋๋ ๋ฐ๋ก SEO(๊ฒ์ ์์ง ์ต์ ํ)์์. ๊ฒ์ ์์ง ํฌ๋กค๋ฌ๊ฐ ์ฐ๋ฆฌ ํ์ด์ง๋ฅผ ๋ ์ฝ๊ฒ ์ดํดํ ์ ์๊ฑฐ๋ ์. ์ด๋ป๊ฒ ํ๋ฉด SSR๋ก SEO๋ฅผ ๊ฐ์ ํ ์ ์์๊น์?
- ๋ฉํ ํ๊ทธ ์ต์ ํ: Next.js์ Head ์ปดํฌ๋ํธ๋ฅผ ์ฌ์ฉํด์ ๊ฐ ํ์ด์ง์ ๋ฉํ ํ๊ทธ๋ฅผ ๋์ ์ผ๋ก ์ค์ ํ ์ ์์ด์.
- ๊ตฌ์กฐํ๋ ๋ฐ์ดํฐ: JSON-LD ํ์์ ๊ตฌ์กฐํ๋ ๋ฐ์ดํฐ๋ฅผ ์ถ๊ฐํด์ ๊ฒ์ ๊ฒฐ๊ณผ์ ๋ ๋ง์ ์ ๋ณด๋ฅผ ํ์ํ ์ ์์ด์.
- ์๋ฒ ์ฌ์ด๋์์ ๋์ OG ํ๊ทธ ์์ฑ: ์์ ๋ฏธ๋์ด ๊ณต์ ์ ๋ณด์ฌ์ง ์ด๋ฏธ์ง์ ์ค๋ช ์ ๋์ ์ผ๋ก ์์ฑํ ์ ์์ด์.
์ด๋ ๊ฒ ํ๋ฉด ๊ฒ์ ์์ง์ด ์ฌ๋ฌ๋ถ์ ์ฌ์ดํธ๋ฅผ ๋ ์ ์ดํดํ๊ณ , ๋ ๋์ ์์๋ก ๋ ธ์ถ์์ผ์ค ๊ฑฐ์์. SEO์ ๋ง๋ฒ์ฌ๊ฐ ๋๋ ๊ฑฐ์ฃ ! ๐งโโ๏ธ
๐ก ์ฌ๋ฅ๋ท ํ์ฉ ํ: SEO์ ๋ํด ๋ ์์ธํ ์๊ณ ์ถ๋ค๋ฉด, ์ฌ๋ฅ๋ท์์ SEO ์ ๋ฌธ๊ฐ๋ฅผ ์ฐพ์๋ณด์ธ์. ์ฌ๋ฌ๋ถ์ ์น์ฌ์ดํธ ์์๋ฅผ ๋์ด๋๋ฐ ํฐ ๋์์ด ๋ ๊ฑฐ์์!
5. SSR์ ๋จ์ ๊ณผ ํด๊ฒฐ ๋ฐฉ๋ฒ ๐ค
SSR์ด ์ฅ์ ๋ง ์๋ ๊ฑด ์๋์์. ๋ช ๊ฐ์ง ๋จ์ ๋ ์์ฃ . ํ์ง๋ง ๊ฑฑ์ ๋ง์ธ์! ํด๊ฒฐ ๋ฐฉ๋ฒ๋ ํจ๊ป ์๋ ค๋๋ฆด๊ฒ์.
- ์๋ฒ ๋ถํ ์ฆ๊ฐ
- ๋ฌธ์ : ๋ชจ๋ ์์ฒญ์ ์๋ฒ์์ ์ฒ๋ฆฌํ๋ฏ๋ก ์๋ฒ ๋ถํ๊ฐ ์ฆ๊ฐํ ์ ์์ด์.
- ํด๊ฒฐ: ์บ์ฑ ์ ๋ต์ ์ฌ์ฉํ๊ฑฐ๋, CDN์ ํ์ฉํด ๋ถํ๋ฅผ ๋ถ์ฐ์ํฌ ์ ์์ด์.
- TTFB(Time To First Byte) ์ฆ๊ฐ
- ๋ฌธ์ : ์๋ฒ์์ ํ์ด์ง๋ฅผ ์์ฑํ๋ ์๊ฐ ๋๋ฌธ์ ์ฒซ ๋ฐ์ดํธ ์์ ์๊ฐ์ด ๋์ด๋ ์ ์์ด์.
- ํด๊ฒฐ: ์๋ฒ ์ฑ๋ฅ ์ต์ ํ, ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฟผ๋ฆฌ ์ต์ ํ ๋ฑ์ผ๋ก ๊ฐ์ ํ ์ ์์ด์.
- ๋ณต์กํ ์ํ ๊ด๋ฆฌ
- ๋ฌธ์ : ์๋ฒ์ ํด๋ผ์ด์ธํธ ๊ฐ์ ์ํ ๋๊ธฐํ๊ฐ ์ด๋ ค์ธ ์ ์์ด์.
- ํด๊ฒฐ: Next.js์ getInitialProps๋ Redux์ ๊ฐ์ ์ํ ๊ด๋ฆฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ํ์ฉํ์ธ์.
์ด๋ฐ ๋จ์ ๋ค์ ์ ์ดํดํ๊ณ ๋๋นํ๋ค๋ฉด, SSR์ ์ฅ์ ์ ์ต๋ํ ํ์ฉํ ์ ์์ ๊ฑฐ์์. ๊ฐ๋ฐ์ ํญ์ ํธ๋ ์ด๋์คํ์ ์ฐ์์ด๋๊น์! ๐
6. ์ค์ ์์ : SSR๋ก ๋ธ๋ก๊ทธ ๋ง๋ค๊ธฐ ๐
์, ์ด์ ๋ฐฐ์ด ๋ด์ฉ์ ํ์ฉํด์ ๊ฐ๋จํ ๋ธ๋ก๊ทธ๋ฅผ ๋ง๋ค์ด๋ณผ๊น์? SSR์ ์ฅ์ ์ ์ญ๋ถ ํ์ฉํ ์ ์๋ ์ข์ ์์ ๊ฐ ๋ ๊ฑฐ์์.
๋จผ์ , ๋ธ๋ก๊ทธ ํฌ์คํธ ๋ชฉ๋ก ํ์ด์ง๋ฅผ ๋ง๋ค์ด๋ณผ๊ฒ์:
// pages/index.js
import Link from 'next/link';
export default function Home({ posts }) {
return (
<div>
<h1>My Awesome Blog</h1>
<ul>
{posts.map((post) => (
<li key="{post.id}">
<link href="%7B%60/post/%24%7Bpost.id%7D%60%7D">
<a>{post.title}</a>
</li>
))}
</ul>
</div>
);
}
export async function getServerSideProps() {
// ์ฌ๊ธฐ์๋ ์์๋ก ํ๋์ฝ๋ฉํ์ง๋ง, ์ค์ ๋ก๋ API๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ๊ฐ์ ธ์์ผ ํด์
const posts = [
{ id: 1, title: "Next.js ์์ํ๊ธฐ" },
{ id: 2, title: "SSR์ ์ฅ์ " },
{ id: 3, title: "React vs Next.js" },
];
return { props: { posts } };
}
์ด์ ๊ฐ ํฌ์คํธ์ ์์ธ ํ์ด์ง๋ฅผ ๋ง๋ค์ด๋ณผ๊ฒ์:
// pages/post/[id].js
import { useRouter } from 'next/router';
export default function Post({ post }) {
const router = useRouter();
// ํด๋ฐฑ ํ์ด์ง๋ฅผ ์ํ ์ฒ๋ฆฌ
if (router.isFallback) {
return <div>Loading...</div>;
}
return (
<div>
<h1>{post.title}</h1>
<p>{post.content}</p>
</div>
);
}
export async function getServerSideProps({ params }) {
// ์ค์ ๋ก๋ API๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์์ผ ํด์
const post = {
id: params.id,
title: `ํฌ์คํธ ${params.id}์ ์ ๋ชฉ`,
content: `์ด๊ฒ์ ํฌ์คํธ ${params.id}์ ๋ด์ฉ์
๋๋ค. SSR๋ก ๋ ๋๋ง๋์์ด์!`,
};
return { props: { post } };
}
์! ์ด๋ ๊ฒ ํ๋ฉด ๊ธฐ๋ณธ์ ์ธ SSR ๋ธ๋ก๊ทธ๊ฐ ์์ฑ๋ผ์. ๊ฐ ํ์ด์ง๋ ์๋ฒ์์ ๋ ๋๋ง๋์ด SEO์ ์ต์ ํ๋๊ณ , ์ด๊ธฐ ๋ก๋ฉ ์๋๋ ๋น ๋ฅด๋ต๋๋ค. ๐
๐ก Pro Tip: ์ค์ ํ๋ก์ ํธ์์๋ ๋ฐ์ดํฐ๋ฅผ API๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ๊ฐ์ ธ์์ผ ํด์. Next.js๋ API ๋ผ์ฐํธ ๊ธฐ๋ฅ๋ ์ ๊ณตํ๋, ๋ฐฑ์๋ API๋ฅผ ์ง์ ๋ง๋ค ์๋ ์์ด์!
7. SSR๊ณผ CSR์ ํ์ด๋ธ๋ฆฌ๋: Next.js์ ๊ฐ์ ๐ช
Next.js์ ๋ ๋ค๋ฅธ ๊ฐ์ ์ SSR๊ณผ CSR(Client-Side Rendering)์ ์ ์ ํ ์์ด ์ฌ์ฉํ ์ ์๋ค๋ ๊ฑฐ์์. ์ด๊ฒ ๋ฐ๋ก Next.js๊ฐ "ํ์ด๋ธ๋ฆฌ๋" ์ฑ์ ๋ง๋ค ์ ์๋ค๊ณ ํ๋ ์ด์ ์ฃ !
์๋ฅผ ๋ค์ด, ๋ธ๋ก๊ทธ์ ๋ฉ์ธ ํ์ด์ง์ ํฌ์คํธ ์์ธ ํ์ด์ง๋ SSR๋ก ์ฒ๋ฆฌํ๊ณ , ๋๊ธ ๊ธฐ๋ฅ์ CSR๋ก ๊ตฌํํ ์ ์์ด์. ์ด๋ ๊ฒ ํ๋ฉด ์ด๊ธฐ ๋ก๋ฉ์ ๋น ๋ฅด๊ฒ ํ๋ฉด์๋, ๋์ ์ธ ๊ธฐ๋ฅ์ ํด๋ผ์ด์ธํธ์์ ์ฒ๋ฆฌํ ์ ์๋ต๋๋ค.
๊ฐ๋จํ ์์ ๋ฅผ ๋ณผ๊น์?
// pages/post/[id].js
import { useState } from 'react';
export default function Post({ post }) {
const [comments, setComments] = useState([]);
const [newComment, setNewComment] = useState('');
const handleSubmit = (e) => {
e.preventDefault();
setComments([...comments, newComment]);
setNewComment('');
};
return (
<div>
<h1>{post.title}</h1>
<p>{post.content}</p>
{/* ๋๊ธ ์น์
(CSR) */}
<h2>๋๊ธ</h2>
<ul>
{comments.map((comment, index) => (
<li key="{index}">{comment}</li>
))}
</ul>
<form onsubmit="{handleSubmit}">
<input type="text" value="{newComment}" onchange="{(e)"> setNewComment(e.target.value)}
placeholder="๋๊ธ์ ์
๋ ฅํ์ธ์"
/>
<button type="submit">๋๊ธ ์์ฑ</button>
</form>
</div>
);
}
export async function getServerSideProps({ params }) {
// SSR๋ก ํฌ์คํธ ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ
const post = {
id: params.id,
title: `ํฌ์คํธ ${params.id}์ ์ ๋ชฉ`,
content: `์ด๊ฒ์ ํฌ์คํธ ${params.id}์ ๋ด์ฉ์
๋๋ค. SSR๋ก ๋ ๋๋ง๋์์ด์!`,
};
return { props: { post } };
}
์ด ์์ ์์ ํฌ์คํธ ๋ด์ฉ์ SSR๋ก ์ฒ๋ฆฌ๋๊ณ , ๋๊ธ ๊ธฐ๋ฅ์ CSR๋ก ๊ตฌํ๋์์ด์. ์์ ์ฉ์ง ์๋์? ๐
๐ ์ฑ๋ฅ ์ต์ ํ ํ: CSR๋ก ๊ตฌํ๋ ๋ถ๋ถ์ ๋ํด์๋ ์ฝ๋ ๋ถํ (Code Splitting)์ ์ ์ฉํด๋ณด์ธ์. Next.js์ dynamic import๋ฅผ ์ฌ์ฉํ๋ฉด ์ฝ๊ฒ ๊ตฌํํ ์ ์์ด์!
8. SSR๊ณผ ๋ฐ์ดํฐ fetching: SWR์ ๋ง๋ฒ โจ
Next.js๋ก SSR์ ๊ตฌํํ ๋ ๋ฐ์ดํฐ fetching์ ์ ๋ง ์ค์ํ ๋ถ๋ถ์ด์์. ์ฌ๊ธฐ์ SWR์ด๋ผ๋ ๋ง๋ฒ ๊ฐ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์๊ฐํด๋๋ฆด๊ฒ์!
SWR์ "stale-while-revalidate"์ ์ฝ์๋ก, Vercel ํ์ด ๋ง๋ ๋ฐ์ดํฐ fetching ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์. SSR๊ณผ ํจ๊ป ์ฌ์ฉํ๋ฉด ์ ๋ง ๊ฐ๋ ฅํ ๊ธฐ๋ฅ์ ๋ฐํํ๋ต๋๋ค.
SWR์ ์ฌ์ฉํ ๊ฐ๋จํ ์์ ๋ฅผ ๋ณผ๊น์?
// pages/users.js
import useSWR from 'swr';
const fetcher = (url) => fetch(url).then((res) => res.json());
export default function Users({ initialData }) {
const { data } = useSWR('/api/users', fetcher, { initialData });
return (
<div>
<h1>์ฌ์ฉ์ ๋ชฉ๋ก</h1>
<ul>
{data.map((user) => (
<li key="{user.id}">{user.name}</li>
))}
</ul>
</div>
);
}
export async function getServerSideProps() {
const initialData = await fetcher('https://api.example.com/users');
return { props: { initialData } };
}
์ด ์์ ์์๋ ์๋ฒ์์ ์ด๊ธฐ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๊ณ , ํด๋ผ์ด์ธํธ์์ SWR์ ์ฌ์ฉํด ๋ฐ์ดํฐ๋ฅผ ๊ณ์ ์ต์ ์ํ๋ก ์ ์งํด์. ์์ ์ฉ์ด! ๐
๐ก SWR์ ์ฅ์ :
- ์๋์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ์ฌ๊ฒ์ฆ(revalidate)ํด์.
- ์บ์ฑ์ ์ง์ํด์ ์ฑ๋ฅ์ด ์ข์์.
- ์๋ฌ ๋ฐ์ ์ ์๋์ผ๋ก ์ฌ์๋ํด์.
- ์ค์๊ฐ ๋ฐ์ดํฐ ์ ๋ฐ์ดํธ๋ฅผ ์ฝ๊ฒ ๊ตฌํํ ์ ์์ด์.
9. SSR๊ณผ ์คํ์ผ๋ง: CSS-in-JS์ ์ธ๊ณ ๐จ
SSR์ ๊ตฌํํ ๋ ์คํ์ผ๋ง๋ ์ค์ํ ๊ณ ๋ ค์ฌํญ์ด์์. Next.js์์๋ CSS-in-JS ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฝ๊ฒ ์ฌ์ฉํ ์ ์๋ต๋๋ค. ํนํ styled-components๋ emotion ๊ฐ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์ธ๊ธฐ ์์ด์.
styled-components๋ฅผ ์ฌ์ฉํ ์์ ๋ฅผ ๋ณผ๊น์?
// pages/_document.js
import Document from 'next/document';
import { ServerStyleSheet } from 'styled-components';
export default class MyDocument extends Document {
static async getInitialProps(ctx) {
const sheet = new ServerStyleSheet();
const originalRenderPage = ctx.renderPage;
try {
ctx.renderPage = () =>
originalRenderPage({
enhanceApp: (App) => (props) =>
sheet.collectStyles(<app></app>),
});
const initialProps = await Document.getInitialProps(ctx);
return {
...initialProps,
styles: (
<>
{initialProps.styles}
{sheet.getStyleElement()}
>
),
};
} finally {
sheet.seal();
}
}
}
// pages/index.js
import styled from 'styled-components';
const Title = styled.h1`
font-size: 50px;
color: ${({ theme }) => theme.colors.primary};
`;
export default function Home() {
return <title>์๋
ํ์ธ์, Next.js + styled-components!</title>;
}
์ด๋ ๊ฒ ํ๋ฉด ์๋ฒ์์ ๋ ๋๋ง๋ ๋๋ ์คํ์ผ์ด ์ ๋๋ก ์ ์ฉ๋ผ์. CSS-in-JS์ ์ฅ์ ์ SSR์์๋ ๋๋ฆด ์ ์๋ ๊ฑฐ์ฃ ! ๐
๐จ ์คํ์ผ๋ง ํ: CSS-in-JS ์ธ์๋ Next.js๋ CSS Modules, Sass ๋ฑ ๋ค์ํ ์คํ์ผ๋ง ๋ฐฉ์์ ์ง์ํด์. ํ๋ก์ ํธ์ ํน์ฑ์ ๋ง๋ ๋ฐฉ์์ ์ ํํ์ธ์!
10. SSR๊ณผ ์ฑ๋ฅ ์ต์ ํ: ๋ ๋น ๋ฅด๊ฒ, ๋ ํจ์จ์ ์ผ๋ก! โก
- ์ง์์ธ์ ์ฒ - ์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
- ์ ์๊ถ ๋ฐ ์์ ๊ถ: ๋ณธ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ๋ ์ AI ๊ธฐ์ ๋ก ์์ฑ๋์์ผ๋ฉฐ, ๋ํ๋ฏผ๊ตญ ์ ์๊ถ๋ฒ ๋ฐ ๊ตญ์ ์ ์๊ถ ํ์ฝ์ ์ํด ๋ณดํธ๋ฉ๋๋ค.
- AI ์์ฑ ์ปจํ ์ธ ์ ๋ฒ์ ์ง์: ๋ณธ AI ์์ฑ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ์ง์ ์ฐฝ์๋ฌผ๋ก ์ธ์ ๋๋ฉฐ, ๊ด๋ จ ๋ฒ๊ท์ ๋ฐ๋ผ ์ ์๊ถ ๋ณดํธ๋ฅผ ๋ฐ์ต๋๋ค.
- ์ฌ์ฉ ์ ํ: ์ฌ๋ฅ๋ท์ ๋ช ์์ ์๋ฉด ๋์ ์์ด ๋ณธ ์ปจํ ์ธ ๋ฅผ ๋ณต์ , ์์ , ๋ฐฐํฌ, ๋๋ ์์ ์ ์ผ๋ก ํ์ฉํ๋ ํ์๋ ์๊ฒฉํ ๊ธ์ง๋ฉ๋๋ค.
- ๋ฐ์ดํฐ ์์ง ๊ธ์ง: ๋ณธ ์ปจํ ์ธ ์ ๋ํ ๋ฌด๋จ ์คํฌ๋ํ, ํฌ๋กค๋ง, ๋ฐ ์๋ํ๋ ๋ฐ์ดํฐ ์์ง์ ๋ฒ์ ์ ์ฌ์ ๋์์ด ๋ฉ๋๋ค.
- AI ํ์ต ์ ํ: ์ฌ๋ฅ๋ท์ AI ์์ฑ ์ปจํ ์ธ ๋ฅผ ํ AI ๋ชจ๋ธ ํ์ต์ ๋ฌด๋จ ์ฌ์ฉํ๋ ํ์๋ ๊ธ์ง๋๋ฉฐ, ์ด๋ ์ง์ ์ฌ์ฐ๊ถ ์นจํด๋ก ๊ฐ์ฃผ๋ฉ๋๋ค.
์ฌ๋ฅ๋ท์ ์ต์ AI ๊ธฐ์ ๊ณผ ๋ฒ๋ฅ ์ ๊ธฐ๋ฐํ์ฌ ์์ฌ์ ์ง์ ์ฌ์ฐ๊ถ์ ์ ๊ทน์ ์ผ๋ก ๋ณดํธํ๋ฉฐ,
๋ฌด๋จ ์ฌ์ฉ ๋ฐ ์นจํด ํ์์ ๋ํด ๋ฒ์ ๋์์ ํ ๊ถ๋ฆฌ๋ฅผ ๋ณด์ ํฉ๋๋ค.
ยฉ 2025 ์ฌ๋ฅ๋ท | All rights reserved.
๋๊ธ 0๊ฐ