Page Router vs App Router vs React Server Components
React ์ํ๊ณ๊ฐ ์งํํจ์ ๋ฐ๋ผ Next.js๋ ๊ฐ๋ฐ์๋ค์๊ฒ ๋ค์ํ ๋ ๋๋ง ์ต์ ์ ์ ๊ณตํ๊ณ ์์ต๋๋ค. ํนํ NextJS์ Page Router SSR(Server Side Rendering)๊ณผ React Server Components(RSC)๊ฐ ์์ฃ . ์ด๋ฒ ๊ธ์์๋ ์ ํต์ ์ธ Next.js Page Router ๊ธฐ๋ฐ์ SSR๊ณผ Next.js App Router ๊ธฐ๋ฐ์ SSR, ๊ทธ๋ฆฌ๊ณ React Server Components์ ์ฐจ์ด์ ์ ์ดํด๋ด ์๋ค.
NextJS App Router Server Component = React Server Component?
๊ฒฐ๋ก ๋ถํฐ ๋ง์๋๋ฆฌ๋ฉด NextJS App Router์ Server Component๋ React์ Server Component๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๋ง๋ค์ด์ก์ต๋๋ค. React ํ์ด ์ค๊ณํ Server Component์ ํต์ฌ ์์ด๋์ด๋ฅผ Next.js๊ฐ ๋ฐ์๋ค์ฌ, App Router๋ฅผ ํตํด ์ด์ ๋ง๋ ์ํ๊ณ๋ฅผ ๋น ๋ฅด๊ฒ ๊ตฌํํ ๊ฒ์ ๋๋ค.
๋ค๋ง, Page Router์ SSR์ ์กฐ๊ธ ๋ค๋ฆ ๋๋ค. React Server Component๊ฐ ๋์ค๊ธฐ ์ด์ ์ ๋จผ์ NextJS์์ React์ SSR์ ํจ๊ป ์ฌ์ฉํ ์ ์๋๋ก ํ๊ธฐ ์ํ ๋ ์์ ์ธ ๊ธฐ์ ์ด๊ธฐ ๋๋ฌธ์ ๋๋ค. ๐ค
์ ์ผ๋จ Page Router๋ฅผ ํ ๋ฒ ๋ณด๋๋ก ํฉ์๋ค !
Next.js Page Router ๊ธฐ๋ฐ์ SSR
Next.js Page Router์์ SSR์ getServerSideProps๋ผ๋ ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ๊ตฌํ๋ฉ๋๋ค. ์ด ๋ฉ์๋๋ ํ์ด์ง ์์ฒญ ์ ์๋ฒ์์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๋ ์ญํ ์ ํฉ๋๋ค. ์ด๋ฅผ ํตํด ์ฌ์ฉ์๋ ์์ฒญ ์์ ์ ์ต์ ๋ฐ์ดํฐ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๋ ๋๋ง๋ HTML์ ๋ฐ์ ์ ์์ผ๋ฉฐ, ์ด๋ SEO ์ต์ ํ์ ๋์ ๋ฐ์ดํฐ ์ฒ๋ฆฌ๊ฐ ์ค์ํ ํ๋ก์ ํธ์์ ์ ์ฉํฉ๋๋ค.
Page Router์์์ SSR์ ์ฃผ๋ ํน์ง์ ํ์ด์ง ๋จ์์ ๋ฐ์ดํฐ ์์ฒญ๊ณผ ์ฒ๋ฆฌ์ ๋๋ค. ์ด๋ ๊ฐ๊ฐ์ ํ์ด์ง๊ฐ ๋ ๋ฆฝ์ ์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๊ณ ๋ ๋๋งํ๋๋ก ์ค๊ณ๋์ด ์์ด, ๊ตฌ์ฑ๊ณผ ๋ฐ์ดํฐ ์์ฒญ ๋ก์ง์ด ๋ช ํํ๊ฒ ๋ถ๋ฆฌ๋ฉ๋๋ค. ๊ทธ๋ฌ๋ ๋ชจ๋ ํ์ด์ง ์์ฒญ๋ง๋ค ์๋ฒ์์ ์ ์ฒ๋ฆฌ๋ฅผ ์ํํ๊ธฐ ๋๋ฌธ์ ํธ๋ํฝ์ด ๋ง์ ์ ํ๋ฆฌ์ผ์ด์ ์์๋ ์๋ฒ ๋ถํ๊ฐ ์ฆ๊ฐํ ์ ์๋ ๋จ์ ์ด ์์ต๋๋ค.
์์ ๋ฅผ ํตํด ์ดํด๋ณด๋ฉด, ์๋๋ getServerSideProps๋ฅผ ์ด์ฉํ ๊ธฐ๋ณธ์ ์ธ SSR ๊ตฌํ์
๋๋ค:
export async function getServerSideProps(context) {
const res = await fetch('https://api.example.com/data');
const data = await res.json();
return {
props: { data },
};
}
export default function Page({ data }) {
return <div>{data.title}</div>;
}
์์ ์ฝ๋์์ ๋ฐ์ดํฐ๋ฅผ ํ์ด์ง ๋ก๋ ์ ์๋ฒ์์ ๊ฐ์ ธ์ค๋ฉฐ, ์ด ๋ฐ์ดํฐ๋ ํด๋ผ์ด์ธํธ์ HTML๋ก ๋ณด๋ด์ง๋๋ค. ์ด์ฒ๋ผ Page Router ๊ธฐ๋ฐ์ SSR์ ๋ช ํํ ๋ฐ์ดํฐ ํ๋ฆ๊ณผ SEO ์นํ์ ์ํคํ ์ฒ๋ฅผ ์ ๊ณตํฉ๋๋ค.
Next.js App Router์ React Server Components
Next.js 13์์ App Router๊ฐ ๋์ ๋๋ฉฐ React Server Components(RSC)๋ฅผ ๊ธฐ๋ณธ์ผ๋ก ์ฌ์ฉํ๋ ๊ตฌ์ฑ์ด ๊ฐ๋ฅํด์ก์ต๋๋ค. RSC๋ ํด๋ผ์ด์ธํธ์ ์๋ฒ ๊ฐ์ ๊ฒฝ๊ณ๋ฅผ ๋ ํจ๊ณผ์ ์ผ๋ก ์ค์ ํ์ฌ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฑ๋ฅ ์ต์ ํ๋ฅผ ๋ชฉํ๋ก ํฉ๋๋ค. App Router ๊ธฐ๋ฐ์ SSR์ ๊ธฐ์กด Page Router๋ณด๋ค ๋ ์ธ๋ถ์ ์ด๊ณ ์ปดํฌ๋ํธ ์ค์ฌ์ ์ธ ์ ๊ทผ ๋ฐฉ์์ ์ ๊ณตํฉ๋๋ค.
App Router๋ ๋ฐ์ดํฐ ์์ฒญ๊ณผ ๋ ๋๋ง์ ์ ์ฐ์ฑ์ ์ ๊ณตํ๋ฉฐ, ํน์ ์ปดํฌ๋ํธ๋ฅผ ์๋ฒ์์ ๋ ๋๋งํ๊ณ ๋๋จธ์ง๋ ํด๋ผ์ด์ธํธ์์ ์ฒ๋ฆฌํ ์ ์์ต๋๋ค. ์ด๋ฌํ ๋ฐฉ์์ ํตํด ์ด๊ธฐ ๋ก๋ ์๊ฐ์ ์ค์ด๋ฉด์๋ ์๋ฒ์ ๊ณ์ฐ ๋ถํ๋ฅผ ํจ์จ์ ์ผ๋ก ๋ถ์ฐํ ์ ์์ต๋๋ค. RSC๋ React์ ์ฒ ํ์ธ ์ ์ธ์ UI์ ์๋ฒ ์ค์ฌ ๋ ๋๋ง์ ๊ฒฐํฉํ์ฌ ๊ฐ๋ฐ์๋ค์ด ํด๋ผ์ด์ธํธ์ ์๋ฒ์ ์ฑ๋ฅ์ ๊ทน๋ํํ ์ ์๋๋ก ํฉ๋๋ค.
RSC์ ์ฃผ์ ์ฅ์ ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
- ์ปดํฌ๋ํธ ๋จ์์ ๋ฐ์ดํฐ ํ์นญ: ํ์ํ ๋ฐ์ดํฐ๋ง ์๋ฒ์์ ๊ฐ์ ธ์ค๋ฏ๋ก ํธ๋ํฝ ๋น์ฉ์ด ๊ฐ์ํฉ๋๋ค.
- ํด๋ผ์ด์ธํธ์ ๋ฒ๋ค ํฌ๊ธฐ ๊ฐ์: ๋ถํ์ํ ํด๋ผ์ด์ธํธ ์๋ฐ์คํฌ๋ฆฝํธ๋ฅผ ์ ๊ฑฐํฉ๋๋ค.
- ์ ์ฐํ ์ํ ๊ด๋ฆฌ: ํด๋ผ์ด์ธํธ์ ์๋ฒ ๊ฐ ์ํ๋ฅผ ํจ์จ์ ์ผ๋ก ๊ณต์ ํ ์ ์์ต๋๋ค.
๋ค์ ์น์ ์์๋ App Router์ RSC๋ฅผ ์ฌ์ฉํ๋ ์ฝ๋ฉ ํจํด๊ณผ ๊ณ ๋ คํด์ผ ํ ์ค๋ฌด์ ์ธ ์ด์๋ค์ ์์๋ณด๊ฒ ์ต๋๋ค.
Next.js Page Router ๊ธฐ๋ฐ SSR vs App Router ๊ธฐ๋ฐ SSR
Next.js๋ Page Router(๊ธฐ์กด ๋ฐฉ์)์ App Router(React Server Components ๊ธฐ๋ฐ)๋ผ๋ ๋ ๊ฐ์ง ํต์ฌ ๋ผ์ฐํ ๋ฐฉ์์ ์ ๊ณตํฉ๋๋ค. ๋ ๋ฐฉ์ ๋ชจ๋ SSR์ ์ง์ํ์ง๋ง, ์๋ ๋ฐฉ์๊ณผ ์ฒ ํ์ ์์ ํ ๋ค๋ฆ ๋๋ค.
1. Page Router ๊ธฐ๋ฐ SSR
Page Router๋ Next.js์ ์ ํต์ ์ธ ๋ผ์ฐํ
๋ฐฉ์์ผ๋ก, ์ฃผ๋ก getServerSideProps๋ฅผ ํตํด ์๋ฒ ์ฌ์ด๋ ๋ ๋๋ง์ ์ง์ํฉ๋๋ค. ์ด ๋ฐฉ์์ React ์ปดํฌ๋ํธ๋ฅผ ์๋ฒ์์ HTML๋ก ๋ ๋๋งํ ๋ค, ํด๋ผ์ด์ธํธ๋ก ์ ์กํ๊ณ ํ์ด๋๋ ์ด์
๊ณผ์ ์ ํตํด ์ธํฐ๋์
์ ํ์ฑํํฉ๋๋ค.
ํน์ง๊ณผ ์๋ ์๋ฆฌ
- ๋ฐ์ดํฐ ํ์นญ:
getServerSideProps๋ฅผ ์ฌ์ฉํด ์๋ฒ์์ ๋ฐ์ดํฐ๋ฅผ ๋ฏธ๋ฆฌ ๊ฐ์ ธ์ต๋๋ค. - HTML ๋ ๋๋ง: React ์ปดํฌ๋ํธ๋ฅผ ์๋ฒ์์ HTML ๋ฌธ์์ด๋ก ๋ณํํฉ๋๋ค.
- ํ์ด๋๋ ์ด์ : ํด๋ผ์ด์ธํธ์์ JavaScript๊ฐ ์ด๋ฒคํธ ํธ๋ค๋ฌ์ ์ํ๋ฅผ ํ์ฑํํฉ๋๋ค.
- SEO ์นํ์ : ๊ฒ์ ์์ง ํฌ๋กค๋ฌ๊ฐ HTML ์ฝํ ์ธ ๋ฅผ ์ฆ์ ์ ๊ทผ ๊ฐ๋ฅํ๊ฒ ํฉ๋๋ค.
// Page Router ๊ธฐ๋ฐ SSR ์์
export async function getServerSideProps() {
const data = await fetch('https://api.example.com/data');
return {
props: { data },
};
}
export default function Page({ data }) {
return <div>{data.title}</div>;
}
ํ๊ณ์
- ๋ฒ๋ค ํฌ๊ธฐ ์ฆ๊ฐ: ๋ชจ๋ JavaScript๊ฐ ํด๋ผ์ด์ธํธ๋ก ์ ์ก๋๊ธฐ ๋๋ฌธ์ ์ด๊ธฐ ๋ก๋ฉ ์๋๊ฐ ๋๋ ค์ง ์ ์์.
- ๋ณต์กํ ๋ฐ์ดํฐ ํ๋ฆ: ๋ฐ์ดํฐ ํ์นญ ๋ก์ง์ด ์ปดํฌ๋ํธ ์ธ๋ถ์ ์์นํ์ฌ ๊ฐ๋ ์ฑ์ด ๋จ์ด์ง ์ ์์.
2. App Router ๊ธฐ๋ฐ SSR (React Server Components ํ์ฉ)
Next.js 13๋ถํฐ ๋์ ๋ App Router๋ React Server Components๋ฅผ ์ค์ฌ์ผ๋ก ์ค๊ณ๋์ด ์์ ํ ๋ค๋ฅธ SSR ์ ๊ทผ ๋ฐฉ์์ ์ ๊ณตํฉ๋๋ค. App Router ๊ธฐ๋ฐ์ SSR์ React Server Components(RSC)๋ฅผ ํ์ฉํด ์๋ฒ์์๋ง ์คํ๋๋ ์ปดํฌ๋ํธ์ ํด๋ผ์ด์ธํธ์์ ์คํ๋๋ ์ปดํฌ๋ํธ๋ฅผ ํจ์จ์ ์ผ๋ก ๋ถ๋ฆฌํฉ๋๋ค.
ํน์ง๊ณผ ์๋ ์๋ฆฌ
- React Server Components ํ์ฉ: ์๋ฒ์์๋ง ์คํ๋๋ ์ปดํฌ๋ํธ๋ฅผ HTML ๋์ RSC Payload๋ผ๋ ์ง๋ ฌํ๋ ๋ฐ์ดํฐ๋ก ๋ ๋๋งํฉ๋๋ค.
- ํด๋ผ์ด์ธํธ ๊ฒฝ๊ณ:
'use client'๋ฅผ ์ฌ์ฉํด ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ๋ฅผ ๋ช ์์ ์ผ๋ก ์ ์ธํฉ๋๋ค. - ๋ฒ๋ค ํฌ๊ธฐ ์ต์ ํ: ์๋ฒ ์ ์ฉ ๋ก์ง์ ํด๋ผ์ด์ธํธ๋ก ์ ์ก๋์ง ์์ผ๋ฏ๋ก JavaScript ๋ฒ๋ค์ด ์์์ง๋๋ค.
- ์ ์ง์ ์คํธ๋ฆฌ๋ฐ: ์๋ฒ์์ ๋ ๋๋ง๋ ์ฝํ ์ธ ๋ฅผ ์ฒญํฌ ๋จ์๋ก ์คํธ๋ฆฌ๋ฐํด ์ด๊ธฐ ๋ก๋ฉ ์๋๋ฅผ ๊ฐ์ ํฉ๋๋ค.
// App Router ๊ธฐ๋ฐ SSR ์์
// app/page.js (Server Component)
export default async function Page() {
const data = await fetch('https://api.example.com/data');
return <div>{data.title}</div>;
}
// components/Button.js (Client Component)
'use client';
export default function Button() {
return <button>Click Me</button>;
}
์ด์
- ์ฑ๋ฅ ์ต์ ํ: ์๋ฒ ์ ์ฉ ์ปดํฌ๋ํธ๋ฅผ ํตํด ํด๋ผ์ด์ธํธ์ JavaScript ๋ก๋๋ฅผ ์ต์ํ.
- ๋ฐ์ดํฐ ํ์นญ ๋จ์ํ: ์ปดํฌ๋ํธ ์์ฒด์์ ๋ฐ์ดํฐ๋ฅผ ์ง์ ํ์นญ.
- ์ ์ง์ ๋ ๋๋ง: ๋ฐ์ดํฐ๊ฐ ๋์ฐฉํ๋ ๋๋ก ์ฝํ ์ธ ๋ฅผ ๋ ๋๋งํด ์ฌ์ฉ์ ๊ฒฝํ ํฅ์.
ํ๊ณ์
- ํ์ต ๊ณก์ : ๊ธฐ์กด Page Router ๋ฐฉ์์ ์ต์ํ ๊ฐ๋ฐ์๋ค์๊ฒ๋ ์๋ก์ด ํจ๋ฌ๋ค์.
- ์ ํ๋ ํด๋ผ์ด์ธํธ ์ํ ๊ด๋ฆฌ: ์๋ฒ ์ปดํฌ๋ํธ ๋ด์์๋ ์ํ ๊ด๋ฆฌ ํ
(
useState,useEffect) ์ฌ์ฉ ๋ถ๊ฐ.
React Server Components (RSC)
React Server Components๋ React 18์์ ๋์ ๋ ์๋ก์ด ๊ฐ๋ ์ผ๋ก, Next.js App Router์ ํต์ฌ ๊ธฐ๋ฐ์ด ๋ฉ๋๋ค. RSC๋ ์๋ฒ์์๋ง ์คํ๋๋ ์ปดํฌ๋ํธ๋ฅผ ์ ์ํ๊ณ , ํด๋ผ์ด์ธํธ๋ก๋ ํด๋น ์ปดํฌ๋ํธ์ ๊ฒฐ๊ณผ ๋ฐ์ดํฐ๋ฅผ ์ง๋ ฌํ๋ ํํ๋ก ์ ์กํฉ๋๋ค.
RSC์ ํน์ง
- ์๋ฒ ์ ์ฉ ์คํ: ์ปดํฌ๋ํธ๊ฐ ์๋ฒ์์๋ง ๋ ๋๋ง๋๊ณ ํด๋ผ์ด์ธํธ๋ก๋ ์ ์ก๋์ง ์์.
- ์ํ ์์: ์ํ ๊ด๋ฆฌ ํ ์ฌ์ฉ ๋ถ๊ฐ, ์์ ๋ ๋๋ง ๋ก์ง์ ์ง์ค.
- ์ง์ ๋ฐ์ดํฐ ํ์นญ: ๋ฐ์ดํฐ๋ฒ ์ด์ค, ํ์ผ ์์คํ ๋ฑ์ ๋ฆฌ์์ค์ ์ง์ ์ ๊ทผ ๊ฐ๋ฅ.
// React Server Component ์์
async function Post({ id }) {
const post = await fetch(`https://api.example.com/posts/${id}`);
return <div>{post.title}</div>;
}
RSC์ ๊ฐ์
- ๋ฒ๋ค ํฌ๊ธฐ ๊ฐ์: ์๋ฒ ์ ์ฉ ์ฝ๋๊ฐ ํด๋ผ์ด์ธํธ ๋ฒ๋ค์์ ์ ์ธ.
- ๋ฐ์ดํฐ ์ ๊ทผ ๋จ์ํ: ๋ณ๋์ API ๊ณ์ธต ์์ด ๋ฐ์ดํฐ ์์ค์ ์ง์ ์ ๊ทผ ๊ฐ๋ฅ.
- ์คํธ๋ฆฌ๋ฐ ์ง์: ๋๊ท๋ชจ ํ์ด์ง๋ฅผ ์ ์ง์ ์ผ๋ก ๋ ๋๋ง ๊ฐ๋ฅ.
์ฌ๊ฒฌ ๋ฐ ๋ง๋ฌด๋ฆฌ
Next.js๊ฐ 2025๋ ์๋ ์ฌ์ ํ ์น ํ์คํ ํ๋ ์์ํฌ 1์๋ฅผ ์ ์งํ๊ณ ์๋ ์ด์ ๋ ๋ฐ๋ก ์ด๋ฌํ ๊ธฐ์ ํ์ ์ ๋ํ ๋ฏผ์ฒฉ์ฑ๊ณผ ์ค์ฉ์ฑ ๋๋ฌธ์ด๋ผ๊ณ ์๊ฐ๋ฉ๋๋ค. ๋น ๋ฅด๊ฒ ๋ณํํ๋ IT ํธ๋ ๋์ ๋ฐ๋ง์ถ ์ง์์ ์ธ ์ ๋ฐ์ดํธ, ์ค๋ฌด ์ค์ฌ์ ๊ธฐ๋ฅ ์ ๊ณต, ๊ทธ๋ฆฌ๊ณ ๊ฐ๋ฐ ์์ฐ์ฑ์ ๊ทน๋ํํ๋ ์ฒ ํ์ด ๊ฒฐํฉ๋์ด ๋ง์ ๊ฐ๋ฐ์๋ค์ด ๋ฏฟ๊ณ ์ ํํ๋ ํ๋ ์์ํฌ๋ก ์๋ฆฌ ์ก์๋ค๊ณ ์๊ฐ๋๋ค์ !