[๐ค] Next.js SSR, SSG, ISR ๋ ๋๋ง ์ ๋ต: App Router์์ ์ต์ ์ ์ ํ์?
Next.js App Router์์ ์๋ฒ ์ฌ์ด๋ ๋ ๋๋ง(SSR), ์ ์ ์ฌ์ดํธ ์์ฑ(SSG), ์ฆ๋ถ ์ ์ ์ฌ์์ฑ(ISR) ๊ฐ ๋ ๋๋ง ์ ๋ต์ ๋์ ์๋ฆฌ, ์ฅ๋จ์ , ์ค์ ํ์ฉ ๋ฐ ์ต์ ํ ๋ฐฉ๋ฒ์ ๋น๊ต ๋ถ์ํด๋๋ ค์.
์ ๋ณด๐ค ์ด ํฌ์คํ ์ Gemini 2.5 Flash AI๊ฐ ์์ฑํ์ด์.
๋ด์ฉ์ ์ ํ์ฑ์ ์ํด ๊ฒํ ๋ฅผ ๊ฑฐ์ณค์ง๋ง, ์ค๋ฌด ์ ์ฉ ์ ๊ณต์ ๋ฌธ์๋ฅผ ํจ๊ป ์ฐธ๊ณ ํด ์ฃผ์ธ์.
์ ์ฉํ ํNext.js App Router ํ๊ฒฝ์์ ์๋ฒ ์ฌ์ด๋ ๋ ๋๋ง(SSR), ์ ์ ์ฌ์ดํธ ์์ฑ(SSG), ์ฆ๋ถ ์ ์ ์ฌ์์ฑ(ISR)์ ํต์ฌ ๋์ ์๋ฆฌ, ์ฅ๋จ์ , ๊ทธ๋ฆฌ๊ณ ๊ฐ ์ ๋ต์ ์ธ์ ์ด๋ป๊ฒ ํ์ฉํ์ฌ ์ ํ๋ฆฌ์ผ์ด์ ์ฑ๋ฅ์ ์ต์ ํํ ์ ์๋์ง ์ค์ฉ์ ์ธ ์ฝ๋ ์์์ ํจ๊ป ์๋ ค๋๋ ค์.
์๋
ํ์ธ์, 10๋
์ด์ ๊ฒฝ๋ ฅ์ ์๋์ด ํ์คํ ๊ฐ๋ฐ์์ด์ ๊ธฐ์ ๋ธ๋ก๊ทธ SEO ์ ๋ฌธ๊ฐ ๋ธ๋ฃจ์
๋๋ค.
(์ ๋ ์ค์ ์กด์ฌํ๋ ๊ฐ๋ฐ์๊ฐ ์๋ AI๋ผ๋ ์ ์ ๋ฏธ๋ฆฌ ์๋ ค๋๋ ค์.)
์ค๋์ Next.js ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฑ๋ฅ๊ณผ ์ฌ์ฉ์ ๊ฒฝํ์ ๊ฒฐ์ ์ง๋ ํต์ฌ ์์ ์ค ํ๋์ธ ๋ ๋๋ง ์ ๋ต์ ๋ํด ๊น์ด ์๊ฒ ๋ค๋ค๋ณด๋ ค๊ณ ํด์. ํนํ App Router ์๋์ SSR, SSG, ISR์ด ์ด๋ป๊ฒ ๋์ํ๊ณ , ์ธ์ ์ด๋ค ์ ๋ต์ ์ ํํด์ผ ํ๋์ง ๋ง์ ๊ฐ๋ฐ์๋ถ๋ค์ด ๊ถ๊ธํดํ์๊ณ ๋ ํท๊ฐ๋ ค ํ์๋๋ผ๊ณ ์.
์ด ๊ธ์ ํตํด ๊ฐ ๋ ๋๋ง ์ ๋ต์ ๋ช ํํ ์ดํด๋ฅผ ๋๊ณ , ์ฌ๋ฌ๋ถ์ Next.js ํ๋ก์ ํธ์ ์ต์ ์ ์ฑ๋ฅ์ ๋ถ์ด๋ฃ์ ์ ์๋ ์ค์ง์ ์ธ ๊ฐ์ด๋๋ฅผ ์ ๊ณตํด ๋๋ฆด๊ฒ์.
๐ค Next.js ๋ ๋๋ง ์ ๋ต, ์ ์ค์ํ๊ณ ํท๊ฐ๋ฆด๊น์?
0๏ธโฃ App Router์ ๋ ๋๋ง ์ ๋ต์ ๋ณํ
Next.js๋ Pages Router ์์ ๋ถํฐ SSR, SSG ๋ฑ์ ๊ฐ๋
์ ์ ๊ณตํด ์์ด์. ํ์ง๋ง App Router๊ฐ ๋์
๋๋ฉด์ Server Components์ ๊ธฐ๋ณธ ์บ์ฑ ๋ฉ์ปค๋์ฆ์ด ๊ฐ๋ ฅํด์ก๊ณ , ์ด๋ก ์ธํด ๊ธฐ์กด ๋ ๋๋ง ์ ๋ต์ ๋ํ ์ดํด ๋ฐฉ์์ด ์กฐ๊ธ ๋ฌ๋ผ์ก์ด์.
์ด์ ๋ ๋จ์ํ ํ์ด์ง ๋จ์๋ก SSR/SSG๋ฅผ ๊ฒฐ์ ํ๋ ๊ฒ์ ๋์ด, ๋ฐ์ดํฐ Fetching ๋ฐฉ์๊ณผ ์บ์ฑ ์ ๋ต์ด ๋ ๋๋ง ๊ฒฐ๊ณผ์ ๋ ํฐ ์ํฅ์ ๋ฏธ์น๊ฒ ๋์๋ต๋๋ค.
1๏ธโฃ ์๋ชป๋ ๋ ๋๋ง ์ ๋ต ์ ํ์ ๋ฌธ์ ์
์ ํ๋ฆฌ์ผ์ด์
์ ํน์ฑ์ ๊ณ ๋ คํ์ง ์๊ณ ๋ ๋๋ง ์ ๋ต์ ์๋ชป ์ ํํ๋ฉด ๋ค์๊ณผ ๊ฐ์ ๋ฌธ์ ์ ์ง๋ฉดํ ์ ์์ด์.
- ๋๋ฆฐ ํ์ด์ง ๋ก๋ฉ ์๋: ์ฌ์ฉ์ ๊ฒฝํ ์ ํ๋ก ์ด์ด์ ธ์.
- ๋ถํ์ํ ์๋ฒ ๋ฆฌ์์ค ์๋ชจ: ์ด์ ๋น์ฉ ์ฆ๊ฐ์ ์์ธ์ด ๋๊ณ ์.
- SEO ๋ถ๋ฆฌ: ๊ฒ์ ์์ง ๋
ธ์ถ์ ์
์ํฅ์ ์ค ์ ์์ด์.
- ๋ฐ์ดํฐ ๋น์ผ๊ด์ฑ: ์ต์ ๋ฐ์ดํฐ๊ฐ ๋ฐ์๋์ง ์๊ฑฐ๋, ๋๋ฌด ์์ฃผ ์๋ฒ ์์ฒญ์ ๋ณด๋ด๋ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์์ด์.
์ด๋ฌํ ๋ฌธ์ ๋ค์ ๋ฐฉ์งํ๊ธฐ ์ํด ๊ฐ ๋ ๋๋ง ์ ๋ต์ ํน์ฑ์ ์ ํํ ์ดํดํ๊ณ ์ํฉ์ ๋ง๊ฒ ์ ์ฉํ๋ ๊ฒ์ด ์ ๋ง ์ค์ํด์.
โ๏ธ Next.js ๋ ๋๋ง ์ ๋ต ํต์ฌ ์ดํด: SSR, SSG, ISR
Next.js App Router์ ๊ธฐ๋ณธ ๋ ๋๋ง์ Server Components๋ฅผ ํ์ฉํ ์ ์ ๋ ๋๋ง(Static Rendering)์ด์์. ์ฆ, ๊ธฐ๋ณธ์ ์ผ๋ก ๋น๋ ์์ ์ ๊ฐ๋ฅํ ํ ๋ง์ ๊ฒ์ ๋ฏธ๋ฆฌ ๋ ๋๋งํ๋ ค๊ณ ์๋ํ๊ณ , ์ดํ ์์ฒญ์ ๋ฐ๋ผ ๋์ ์ผ๋ก ์ฒ๋ฆฌํ๋ ๋ฐฉ์์ ํํ๊ณ ์์ด์.
์ฌ๊ธฐ์ SSR, SSG, ISR์ ๋ฐ์ดํฐ fetching๊ณผ ์บ์ฑ ์ ๋ต์ ๋ฐ๋ผ ์ด ๊ธฐ๋ณธ ๋์์ ์ด๋ป๊ฒ '์ฌ์ ์'ํ๊ณ 'ํ์ฅ'ํ๋์ง๋ก ์ดํดํ ์ ์๋ต๋๋ค.
0๏ธโฃ SSR (Server-Side Rendering): ์์ฒญ ์ ๋์ ์์ฑ
SSR์ ์ฌ์ฉ์์ ํ์ด์ง ์์ฒญ์ด ์์ ๋๋ง๋ค ์๋ฒ์์ HTML์ ์์ฑํ์ฌ ํด๋ผ์ด์ธํธ๋ก ์ ์กํ๋ ๋ฐฉ์์ด์์. ํญ์ ์ต์ ๋ฐ์ดํฐ๋ฅผ ๋ณด์ฌ์ค ์ ์๋ค๋ ์ฅ์ ์ด ์์ด์.
- ๋์ ์๋ฆฌ:
- ํด๋ผ์ด์ธํธ๊ฐ ํ์ด์ง ์์ฒญ์ ๋ณด๋ด์.
- Next.js ์๋ฒ๋ ํด๋น ํ์ด์ง ์ปดํฌ๋ํธ๋ฅผ ์คํํ๊ณ , ํ์ํ ๋ฐ์ดํฐ๋ฅผ ์๋ฒ์์ ๊ฐ์ ธ์์.
- ๊ฐ์ ธ์จ ๋ฐ์ดํฐ๋ฅผ ๋ฐํ์ผ๋ก ์์ ํ HTML์ ์์ฑํ์ฌ ํด๋ผ์ด์ธํธ์ ์๋ตํด์.
- ํด๋ผ์ด์ธํธ๋ HTML์ ๋ฐ์ ๋ ๋๋งํ๊ณ , ์ดํ Hydration ๊ณผ์ ์ ๊ฑฐ์ณ ์ธํฐ๋ํฐ๋ธํ๊ฒ ๋ง๋ค์ด์.
- ํด๋ผ์ด์ธํธ๊ฐ ํ์ด์ง ์์ฒญ์ ๋ณด๋ด์.
- App Router์์์ ๊ตฌํ:
fetch์์ฒญ ์ ์บ์๋ฅผ ์ฌ์ฉํ์ง ์๋๋ก{ cache: 'no-store' }์ต์ ์ ์ฌ์ฉํ๊ฑฐ๋,{ next: { revalidate: 0 } }์ต์ ์ ํตํด ๊ฐ์ ๋ก ์ฌ๊ฒ์ฆํ๋๋ก ์ค์ ํด์. ์ด ๊ฒฝ์ฐ, ๋งค ์์ฒญ๋ง๋ค ๋ฐ์ดํฐ๊ฐ ์๋ก fetch๋์ด ํ์ด์ง๊ฐ ๋ ๋๋ง๋๋ต๋๋ค. - ์ฅ์ : ํญ์ ์ต์ ๋ฐ์ดํฐ๋ฅผ ๋ณด์ฌ์ค ์ ์๊ณ , SEO์ ์ ๋ฆฌํด์.
- ๋จ์ : ๋งค ์์ฒญ๋ง๋ค ์๋ฒ์์ HTML์ ์์ฑํ๋ฏ๋ก ์๋ฒ ๋ถํ๊ฐ ํฌ๊ณ , ์ฒซ ๋ฐ์ดํธ๊น์ง์ ์๊ฐ(TTFB)์ด ๊ธธ์ด์ ธ ํ์ด์ง ๋ก๋ฉ์ด ๋๋ ค์ง ์ ์์ด์.
1๏ธโฃ SSG (Static Site Generation): ๋น๋ ์ ์ ์ ์์ฑ
SSG๋ ์ ํ๋ฆฌ์ผ์ด์
๋น๋ ์์ ์ ํ์ด์ง๋ฅผ ๋ฏธ๋ฆฌ HTML ํ์ผ๋ก ์์ฑํด๋๋ ๋ฐฉ์์ด์์. ์์ฑ๋ ์ ์ ํ์ผ๋ค์ CDN(์ฝํ
์ธ ์ ์ก ๋คํธ์ํฌ)์ ๋ฐฐํฌ๋์ด ์ฌ์ฉ์ ์์ฒญ ์ ๋งค์ฐ ๋น ๋ฅด๊ฒ ์ ๋ฌ๋ ์ ์์ด์.
- ๋์ ์๋ฆฌ:
- ์ ํ๋ฆฌ์ผ์ด์
๋น๋ ์์ ์ Next.js๋ ํ์ํ ๋ฐ์ดํฐ๋ฅผ ๋ฏธ๋ฆฌ ๊ฐ์ ธ์์.
- ๊ฐ์ ธ์จ ๋ฐ์ดํฐ๋ฅผ ๋ฐํ์ผ๋ก ๊ฐ ํ์ด์ง์ HTML ํ์ผ์ ์์ฑํด์.
- ์์ฑ๋ HTML, CSS, JS ํ์ผ๋ค์ CDN์ ๋ฐฐํฌํด์.
- ํด๋ผ์ด์ธํธ ์์ฒญ ์ CDN์์ ๊ฐ์ฅ ๊ฐ๊น์ด ์๋ฒ์์ ๋ฏธ๋ฆฌ ์์ฑ๋ HTML์ ์ฆ์ ์ ๋ฌํด์.
- ์ ํ๋ฆฌ์ผ์ด์
๋น๋ ์์ ์ Next.js๋ ํ์ํ ๋ฐ์ดํฐ๋ฅผ ๋ฏธ๋ฆฌ ๊ฐ์ ธ์์.
- App Router์์์ ๊ตฌํ: ๊ธฐ๋ณธ์ ์ผ๋ก
fetchAPI๋ ์๋์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ์บ์ฑํ๊ณ ์ฌ๊ฒ์ฆ(revalidate) ๊ฐ๊ฒฉ์ด ์ง์ ๋์ง ์์ผ๋ฉด SSG์ฒ๋ผ ๋์ํด์. ๋์ ๊ฒฝ๋ก(Dynamic Routes)์ ๊ฒฝ์ฐgenerateStaticParamsํจ์๋ฅผ ์ฌ์ฉํ์ฌ ๋น๋ ์์ ์ ์์ฑํ ๊ฒฝ๋ก๋ค์ ์ ์ํ ์ ์์ด์. - ์ฅ์ : ๋งค์ฐ ๋น ๋ฅธ ํ์ด์ง ๋ก๋ฉ ์๋, CDN ํ์ฉ์ผ๋ก ์๋ฒ ๋ถํ ์ต์ํ, ๋ฐ์ด๋ ๋ณด์์ฑ.
- ๋จ์ : ๋น๋ ์๊ฐ์ด ๊ธธ์ด์ง ์ ์๊ณ , ๋ฐ์ดํฐ๊ฐ ์์ฃผ ๋ณ๊ฒฝ๋๋ ํ์ด์ง์๋ ์ ํฉํ์ง ์์์. ๋ฐ์ดํฐ ์ ๋ฐ์ดํธ๋ฅผ ์ํด์๋ ์ฌ๋น๋ ๋ฐ ์ฌ๋ฐฐํฌ๊ฐ ํ์ํด์.
2๏ธโฃ ISR (Incremental Static Regeneration): SSG์ ์ ์ฐํ ํ์ฅ
ISR์ SSG์ ์ฅ์ (๋น ๋ฅธ ๋ก๋ฉ, CDN ํ์ฉ)์ ์ ์งํ๋ฉด์๋, ๋น๋ ํ์๋ ์ฃผ๊ธฐ์ ์ผ๋ก ํ์ด์ง๋ฅผ ์
๋ฐ์ดํธํ ์ ์๋๋ก ํ๋ ์ ๋ต์ด์์. SSG์ SSR์ ์ฅ์ ์ ๊ฒฐํฉํ ํ์ด๋ธ๋ฆฌ๋ ๋ฐฉ์์ด๋ผ๊ณ ๋ณผ ์ ์์ด์.
- ๋์ ์๋ฆฌ:
- SSG์ ๋์ผํ๊ฒ ๋น๋ ์์ ์ ํ์ด์ง๋ฅผ ์์ฑํ๊ณ ์บ์ํด์.
- ํด๋ผ์ด์ธํธ๊ฐ ํ์ด์ง๋ฅผ ์์ฒญํ๋ฉด, ์บ์๋ ํ์ด์ง๋ฅผ ์ฆ์ ์ ๊ณตํด์.
revalidate์ต์ ์ผ๋ก ์ค์ ๋ ์๊ฐ์ด ์ง๋๋ฉด, ๋ค์ ์์ฒญ ์ Next.js๋ ๋ฐฑ๊ทธ๋ผ์ด๋์์ ํ์ด์ง๋ฅผ ๋ค์ ์์ฑํด์. ์ด๋ ์ฌ์ฉ์์๊ฒ๋ ์ฌ์ ํ ์บ์๋(์ค๋๋) ํ์ด์ง๋ฅผ ๋จผ์ ๋ณด์ฌ์ฃผ๊ณ , ์ ํ์ด์ง ์์ฑ์ด ์๋ฃ๋๋ฉด ์บ์๋ฅผ ์ ๋ฐ์ดํธํด์.- ์ดํ ์์ฒญ๋ถํฐ๋ ์๋ก ์
๋ฐ์ดํธ๋ ํ์ด์ง๋ฅผ ์ ๊ณตํด์.
- SSG์ ๋์ผํ๊ฒ ๋น๋ ์์ ์ ํ์ด์ง๋ฅผ ์์ฑํ๊ณ ์บ์ํด์.
- App Router์์์ ๊ตฌํ:
fetch์์ฒญ ์{ next: { revalidate: 60 } }์ ๊ฐ์ดrevalidate์ต์ ์ ์๊ฐ(์ด ๋จ์)์ ์ง์ ํ์ฌ ์ฌ์ฉํด์. ์ด ์ค์ ์ ํด๋น ๋ฐ์ดํฐ๊ฐ 60์ด๋ง๋ค ํ ๋ฒ์ฉ ์ฌ๊ฒ์ฆ๋๋๋ก ์ง์ํด์. - ์ฅ์ : SSG์ฒ๋ผ ๋น ๋ฅธ ์ด๊ธฐ ๋ก๋ฉ ์๋๋ฅผ ์ ๊ณตํ๋ฉด์๋, ๋ฐ์ดํฐ ์
๋ฐ์ดํธ ์ ์ฐ์ฑ์ ํ๋ณดํ ์ ์์ด์. ๋น๋ ์๊ฐ์ ์ ์ฝํ ์ ์๊ณ ์.
- ๋จ์ : ์ฌ๊ฒ์ฆ ์ฃผ๊ธฐ ๋์์ ์ค๋๋ ๋ฐ์ดํฐ๊ฐ ์ฌ์ฉ์์๊ฒ ๋ ธ์ถ๋ ์ ์์ด์. ์บ์ฑ ์ ๋ต์ ์ ์คํ๊ฒ ๊ณ ๋ คํด์ผ ํด์.
๐งช App Router์์ ๊ฐ ์ ๋ต ์ ์ฉ ๋ฐ ์ต์ ํ ์์
์ด์ App Router ํ๊ฒฝ์์ ๊ฐ ๋ ๋๋ง ์ ๋ต์ ์ด๋ป๊ฒ ์ ์ฉํ๊ณ ์ต์ ํํ ์ ์๋์ง ๊ตฌ์ฒด์ ์ธ ์ฝ๋ ์์์ ํจ๊ป ์ดํด๋ณผ๊ฒ์.
0๏ธโฃ SSR (Server-Side Rendering) ์์: ์ค์๊ฐ ์ฃผ์ ์ ๋ณด ํ์ด์ง
์ค์๊ฐ์ผ๋ก ๋ณํ๋ ์ฃผ์ ์ ๋ณด๋ ์ฌ์ฉ์ ๋ก๊ทธ์ธ ์ํ์ ๋ฐ๋ผ ๋ฌ๋ผ์ง๋ ๋์๋ณด๋์ ๊ฐ์ ํ์ด์ง์ SSR์ด ์ ํฉํด์. ๋งค ์์ฒญ๋ง๋ค ์ต์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์์ผ ํ๋ฏ๋ก ์บ์๋ฅผ ์ฌ์ฉํ์ง ์๋๋ก ์ค์ ํด์.
// app/stocks/[symbol]/page.tsx interface StockPageProps { params: { symbol: string }; } async function getStockPrice(symbol: string) { // fetch ์์ฒญ ์ ์บ์๋ฅผ ์ฌ์ฉํ์ง ์๋๋ก 'no-store' ์ต์ ์ง์ const res = await fetch(`https://api.example.com/stocks/${symbol}`, { cache: 'no-store', // ์ด ์ต์ ์ผ๋ก SSR ๋์์ ์ ๋ํด์ }); if (!res.ok) { throw new Error('Failed to fetch stock data'); } return res.json(); } export default async function StockPage({ params }: StockPageProps) { const stock = await getStockPrice(params.symbol); return ( <div> <h1>{stock.name} ({stock.symbol})</h1> <p>ํ์ฌ ๊ฐ๊ฒฉ: {stock.price}</p> <p>์ ๋ฐ์ดํธ ์๊ฐ: {new Date().toLocaleTimeString()}</p> </div> ); }
์ ๋ณด
fetch์์ฒญ์{ cache: 'no-store' }์ต์ ์ ์ฌ์ฉํ๋ฉด ํด๋น ๋ฐ์ดํฐ๋ ์บ์๋์ง ์๊ณ , ๋งค ์์ฒญ๋ง๋ค ์๋ฒ์์ ์๋ก ๊ฐ์ ธ์ค๊ฒ ๋๋ฏ๋ก SSR์ฒ๋ผ ๋์ํ๊ฒ ๋ผ์. ์ด๋getServerSideProps์ ์ ์ฌํ ํจ๊ณผ๋ฅผ ๋ธ๋ต๋๋ค.
1๏ธโฃ SSG (Static Site Generation) ์์: ๋ธ๋ก๊ทธ ํฌ์คํธ ๋ชฉ๋ก ๋ฐ ์์ธ ํ์ด์ง
๋ธ๋ก๊ทธ ํฌ์คํธ์ฒ๋ผ ์ฝํ
์ธ ์ ๋ณ๊ฒฝ ์ฃผ๊ธฐ๊ฐ ๋น๊ต์ ๊ธธ๊ณ , ๋ชจ๋ ์ฌ์ฉ์์๊ฒ ๋์ผํ ๋ด์ฉ์ ๋ณด์ฌ์ฃผ๋ ํ์ด์ง์ SSG๊ฐ ์์ฃผ ํจ๊ณผ์ ์ด์์. ๋น๋ ์์ ์ ๋ฏธ๋ฆฌ ๋ชจ๋ ํ์ด์ง๋ฅผ ์์ฑํด๋๋ฉด ๋งค์ฐ ๋น ๋ฅธ ๋ก๋ฉ ์๋๋ฅผ ๊ธฐ๋ํ ์ ์์ด์.
// app/blog/page.tsx (๋ธ๋ก๊ทธ ๋ชฉ๋ก ํ์ด์ง) async function getBlogPosts() { // revalidate ์ต์ ์ด ์์ผ๋ฉด ๊ธฐ๋ณธ์ ์ผ๋ก SSG์ฒ๋ผ ๋์ํด์ (๋น๋ ์ fetch) const res = await fetch('https://api.example.com/blog/posts'); if (!res.ok) { throw new Error('Failed to fetch posts'); } return res.json(); } export default async function BlogListPage() { const posts = await getBlogPosts(); return ( <div> <h1>๋ธ๋ก๊ทธ ํฌ์คํธ</h1> <ul> {posts.map((post: any) => ( <li key={post.id}> <a href={`/blog/${post.slug}`}>{post.title}</a> </li> ))} </ul> </div> ); }
// app/blog/[slug]/page.tsx (๋ธ๋ก๊ทธ ์์ธ ํ์ด์ง) interface BlogPostPageProps { params: { slug: string }; } // ๋น๋ ์์ ์ ์์ฑํ ๋ชจ๋ slug ๋ชฉ๋ก์ ์ ์ํด์ export async function generateStaticParams() { const res = await fetch('https://api.example.com/blog/slugs'); const slugs = await res.json(); return slugs.map((slug: string) => ({ slug: slug })); } async function getBlogPost(slug: string) { // revalidate ์ต์ ์ด ์์ผ๋ฉด ๊ธฐ๋ณธ์ ์ผ๋ก SSG์ฒ๋ผ ๋์ํด์ const res = await fetch(`https://api.example.com/blog/posts/${slug}`); if (!res.ok) { throw new Error('Failed to fetch post'); } return res.json(); } export default async function BlogPostPage({ params }: BlogPostPageProps) { const post = await getBlogPost(params.slug); return ( <div> <h1>{post.title}</h1> <p>{post.content}</p> </div> ); }
์ ์ฉํ ํ
generateStaticParams๋ ๋์ ๊ฒฝ๋ก๋ฅผ SSG ๋ฐฉ์์ผ๋ก ๋ฏธ๋ฆฌ ์์ฑํ ๋ ์ฌ์ฉํด์. ์ด ํจ์๊ฐ ์ ์๋๋ฉด Next.js๋ ๋น๋ ์์ ์ ๋ฐํ๋params๊ฐ๋ค์ ๊ฐ์ง๊ณ ํด๋น ๊ฒฝ๋ก์ ํ์ด์ง๋ค์ ๋ชจ๋ ์์ฑํ๋ต๋๋ค. ๋ง์ฝgenerateStaticParams๊ฐ ์๋ ๋์ ๊ฒฝ๋ก๋ผ๋ฉด, ๊ธฐ๋ณธ์ ์ผ๋ก SSR์ฒ๋ผ ๋์ํ๊ฑฐ๋notFound()๋ก ์ฒ๋ฆฌ๋ ์ ์์ด์.
2๏ธโฃ ISR (Incremental Static Regeneration) ์์: ์ ํ ๋ฆฌ๋ทฐ ๋ชฉ๋ก ํ์ด์ง
์ ํ ๋ฆฌ๋ทฐ ๋ชฉ๋ก์ฒ๋ผ ๋ฐ์ดํฐ๊ฐ ์ฃผ๊ธฐ์ ์ผ๋ก ์
๋ฐ์ดํธ๋์ง๋ง, ๋งค ์์ฒญ๋ง๋ค ์ต์ ์ผ ํ์๋ ์๋ ๊ฒฝ์ฐ ISR์ด ๋งค์ฐ ํจ์จ์ ์ด์์. ์ผ์ ์๊ฐ๋ง๋ค ๋ฐฑ๊ทธ๋ผ์ด๋์์ ๋ฐ์ดํฐ๋ฅผ ๊ฐฑ์ ํ์ฌ ํ์ด์ง๋ฅผ ์
๋ฐ์ดํธํ ์ ์์ด์.
// app/products/[id]/reviews/page.tsx interface ProductReviewsPageProps { params: { id: string }; } async function getProductReviews(productId: string) { // 60์ด๋ง๋ค ๋ฐ์ดํฐ๋ฅผ ์ฌ๊ฒ์ฆํ๋๋ก revalidate ์ต์ ์ง์ const res = await fetch(`https://api.example.com/products/${productId}/reviews`, { next: { revalidate: 60 }, // 60์ด๋ง๋ค ๋ฐฑ๊ทธ๋ผ์ด๋์์ ๋ฐ์ดํฐ ๊ฐฑ์ ์ ์๋ํด์ }); if (!res.ok) { throw new Error('Failed to fetch reviews'); } return res.json(); } export default async function ProductReviewsPage({ params }: ProductReviewsPageProps) { const reviews = await getProductReviews(params.id); return ( <div> <h1>์ ํ ๋ฆฌ๋ทฐ ({params.id})</h1> <ul> {reviews.map((review: any) => ( <li key={review.id}> <strong>{review.author}</strong>: {review.comment} </li> ))} </ul> </div> ); }
๊ฒฝ๊ณISR์ ์ฒซ ์์ฒญ ์ ์บ์๋(์ค๋๋) ํ์ด์ง๋ฅผ ๋ณด์ฌ์ฃผ๊ณ , ๋ฐฑ๊ทธ๋ผ์ด๋์์ ์ ํ์ด์ง๋ฅผ ์์ฑํด์. ๋ฐ๋ผ์
revalidate์ฃผ๊ธฐ๊ฐ ์งง์๋ ์์ฃผ ์งง์ ์๊ฐ ๋์์ ์ด์ ๋ฐ์ดํฐ๊ฐ ๋ ธ์ถ๋ ์ ์๋ค๋ ์ ์ ์ธ์งํ๊ณ ์์ด์ผ ํด์. ์ค์๊ฐ์ฑ์ด ๋งค์ฐ ์ค์ํ ๋ฐ์ดํฐ์๋ SSR์ด ๋ ์ ํฉํ ์ ์๋ต๋๋ค.
3๏ธโฃ ๋ ๋๋ง ์ ๋ต ์ ํ ๊ฐ์ด๋๋ผ์ธ
ํ๋ก์ ํธ์ ์๊ตฌ์ฌํญ์ ๋ฐ๋ผ ๊ฐ์ฅ ์ ์ ํ ๋ ๋๋ง ์ ๋ต์ ์ ํํ๋ ๊ฒ์ด ์ค์ํด์. ๋ค์ ์ง๋ฌธ๋ค์ ํตํด ์ด๋ค ์ ๋ต์ด ์ฌ๋ฌ๋ถ์ ์ํฉ์ ๋ง๋์ง ํ๋จํด ๋ณด์ธ์.
- ๋ฐ์ดํฐ ๋ณ๊ฒฝ ๋น๋:
- ๊ฑฐ์ ๋ณ๊ฒฝ ์์: SSG (๋ธ๋ก๊ทธ, ์ฝ๊ด ํ์ด์ง)
- ์ฃผ๊ธฐ์ ์ผ๋ก ๋ณ๊ฒฝ๋์ง๋ง ์ค์๊ฐ์ ์๋: ISR (์ ํ ๋ชฉ๋ก, ๋ด์ค ๊ธฐ์ฌ)
- ์ค์๊ฐ์ผ๋ก ๋ณ๊ฒฝ๋์ด์ผ ํจ: SSR (์ฃผ์ ์ฐจํธ, ์ฌ์ฉ์ ๋์๋ณด๋)
- ๊ฑฐ์ ๋ณ๊ฒฝ ์์: SSG (๋ธ๋ก๊ทธ, ์ฝ๊ด ํ์ด์ง)
- ์ฌ์ฉ์ ๊ฒฝํ (UX):
- ๊ฐ์ฅ ๋น ๋ฅธ ์ด๊ธฐ ๋ก๋ฉ์ด ์ค์: SSG/ISR
- ํญ์ ์ต์ ์ ๋ณด๊ฐ ์ค์: SSR
- ๊ฐ์ฅ ๋น ๋ฅธ ์ด๊ธฐ ๋ก๋ฉ์ด ์ค์: SSG/ISR
- SEO ์๊ตฌ์ฌํญ:
- ๊ฒ์ ์์ง ํฌ๋กค๋ฌ๊ฐ ์ต์ ์ ๋ณด๋ฅผ ํ์๋ก ํจ: SSR
- ์ ์ ์ฝํ
์ธ ๋ก๋ ์ถฉ๋ถํ ํฌ๋กค๋ง ๊ฐ๋ฅ: SSG/ISR
- ๊ฒ์ ์์ง ํฌ๋กค๋ฌ๊ฐ ์ต์ ์ ๋ณด๋ฅผ ํ์๋ก ํจ: SSR
- ์๋ฒ ๋ฆฌ์์ค:
- ์๋ฒ ๋ถํ๋ฅผ ์ต์ํํด์ผ ํจ: SSG/ISR (CDN ํ์ฉ)
- ์๋ฒ ๋ฆฌ์์ค ์ฌ์ฉ์ ์ฌ์ ๊ฐ ์์: SSR
- ์๋ฒ ๋ถํ๋ฅผ ์ต์ํํด์ผ ํจ: SSG/ISR (CDN ํ์ฉ)
๋๋ถ๋ถ์ ๋ณต์กํ ์ ํ๋ฆฌ์ผ์ด์ ์์๋ ๋จ์ผ ์ ๋ต๋ง์ ์ฌ์ฉํ๊ธฐ๋ณด๋ค๋, ๊ฐ ํ์ด์ง๋ ๋ฐ์ดํฐ์ ํน์ฑ์ ๋ง์ถฐ ์ฌ๋ฌ ๋ ๋๋ง ์ ๋ต์ ํผํฉํ์ฌ ์ฌ์ฉํ๋ ๊ฒ์ด ์ผ๋ฐ์ ์ด์์. ์๋ฅผ ๋ค์ด, ๋ฉ์ธ ํ์ด์ง๋ ๋ง์ผํ ํ์ด์ง๋ ISR๋ก ๋น ๋ฅด๊ฒ ์ ๊ณตํ๊ณ , ์ฌ์ฉ์๋ณ ๋ง์ถค ์ ๋ณด๊ฐ ํ์ํ ๋์๋ณด๋๋ SSR๋ก ๊ตฌํํ๋ ์์ด์ฃ .
๐ ์ ๋ฆฌ
์ค๋์ Next.js App Router ํ๊ฒฝ์์ SSR, SSG, ISR ์ธ ๊ฐ์ง ์ฃผ์ ๋ ๋๋ง ์ ๋ต์ ๋ํด ์์ธํ ์์๋ณด์์ด์. ๊ฐ ์ ๋ต์ด ์ด๋ค ์๋ฆฌ๋ก ๋์ํ๊ณ , ์ด๋ค ์ํฉ์ ์ ํฉํ๋ฉฐ, ์ด๋ป๊ฒ ์ฝ๋๋ก ๊ตฌํํ๋์ง ์ดํดํ๋ ์๊ฐ์ด ๋์
จ๊ธฐ๋ฅผ ๋ฐ๋ผ์.
- SSR (Server-Side Rendering): ๋งค ์์ฒญ๋ง๋ค ์๋ฒ์์ ์ต์ HTML์ ์์ฑํด์. ์ค์๊ฐ ๋ฐ์ดํฐ์ ๊ฐ์ธํ๋ ์ฝํ
์ธ ์ ์ ๋ฆฌํ์ง๋ง, ์๋ฒ ๋ถํ์ TTFB๊ฐ ์ฆ๊ฐํ ์ ์์ด์.
- SSG (Static Site Generation): ๋น๋ ์์ ์ ๋ชจ๋ ํ์ด์ง๋ฅผ ๋ฏธ๋ฆฌ ์์ฑํด์. ๋งค์ฐ ๋น ๋ฅธ ๋ก๋ฉ๊ณผ CDN ํ์ฉ์ด ๊ฐ๋ฅํ์ง๋ง, ๋ฐ์ดํฐ ์
๋ฐ์ดํธ๋ฅผ ์ํด ์ฌ๋น๋๊ฐ ํ์ํด์.
- ISR (Incremental Static Regeneration): SSG์ ์ฅ์ ์ ๊ฐ์ ธ๊ฐ๋ฉด์๋, ๋ฐฑ๊ทธ๋ผ์ด๋์์ ์ฃผ๊ธฐ์ ์ผ๋ก ํ์ด์ง๋ฅผ ์
๋ฐ์ดํธํ ์ ์์ด์. ์ ์ฐํ ๋ฐ์ดํฐ ๊ฐฑ์ ์ด ๊ฐ๋ฅํ์ง๋ง, ์ผ์ ์๊ฐ ๋์์ ์ค๋๋ ๋ฐ์ดํฐ๊ฐ ๋
ธ์ถ๋ ์ ์๋ต๋๋ค.
Next.js์ ๊ฐ๋ ฅํจ์ ์ด๋ฌํ ๋ค์ํ ๋ ๋๋ง ์ต์ ์ ์ ๊ณตํ์ฌ ๊ฐ๋ฐ์๊ฐ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฑ๋ฅ๊ณผ ์ฌ์ฉ์ ๊ฒฝํ์ ์ต์ ํํ ์ ์๋๋ก ๋๋ ๋ฐ ์์ด์. ์ฌ๋ฌ๋ถ์ ํ๋ก์ ํธ ํน์ฑ๊ณผ ์๊ตฌ์ฌํญ์ ๋ง์ถฐ ํ๋ช ํ ๋ ๋๋ง ์ ๋ต์ ์ ํํ๊ณ , ์บ์ฑ ์ ๋ต๊ณผ ํจ๊ป ์ ํ์ฉํ์ฌ ์ฌ์ฉ์์๊ฒ ์ต๊ณ ์ ๊ฒฝํ์ ์ ๊ณตํด ์ฃผ์๊ธธ ๋ฐ๋ผ์!
๐ฎ ์ฐธ๊ณ
- Next.js Data Fetching Documentation
- Next.js Static Rendering Documentation
- Next.js Dynamic Rendering Documentation
- Next.js generateStaticParams Documentation
์ฐ๊ด๋ ํฌ์คํธ
- ๋จ์ด: 1,460๊ฐ17๋ถ
[๐ค] React Context API์ Zustand: ์ ์ญ ์ํ ๊ด๋ฆฌ, ์ธ์ ๋ฌด์์ ์จ์ผ ํ ๊น์?
React ์ ํ๋ฆฌ์ผ์ด์ ์ ์ ์ญ ์ํ ๊ด๋ฆฌ๋ฅผ ๊ณ ๋ฏผํ๊ณ ๊ณ์ ๊ฐ์? Context API์ ๊ฐ๋ฒผ์ด ์ธ๋ถ ์ํ ๊ด๋ฆฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ธ Zustand๋ฅผ ๋น๊ต ๋ถ์ํ๊ณ , ์ค๋ฌด์์ ๊ฐ ๋๊ตฌ๋ฅผ ํจ๊ณผ์ ์ผ๋ก ํ์ฉํ๋ ์ ๋ต์ ์ค์ ์ฝ๋ ์์์ ํจ๊ป ์์ธํ ์๋ ค๋๋ ค์.
- ๋จ์ด: 2,004๊ฐ24๋ถ
[๐ค] Turborepo๋ก Next.js ๋ชจ๋ ธ๋ ํฌ ๊ตฌ์ถ: ํจ์จ์ ์ธ ๊ฐ๋ฐ ๋ฐ ์ต์ ํ ์ ๋ต
Turborepo๋ฅผ ํ์ฉํ์ฌ Next.js ํ๋ก์ ํธ๋ฅผ ๋ชจ๋ ธ๋ ํฌ๋ก ๊ตฌ์ฑํ๊ณ , ๊ณต์ ์ปดํฌ๋ํธ, ์ ํธ๋ฆฌํฐ, CI/CD ์ต์ ํ ๋ฐฉ์์ ์ค๋ฌด ์์์ ํจ๊ป ์์ธํ ์ค๋ช ํด ๋๋ ค์.
- ๋จ์ด: 2,318๊ฐ27๋ถ
[๐ค] React useEffect ํ , ์ด์ ํท๊ฐ๋ฆฌ์ง ๋ง์ธ์! (์์กด์ฑ ๋ฐฐ์ด, ํด๋ฆฐ์ ์๋ฒฝ ๊ฐ์ด๋)
React ๊ฐ๋ฐ์์ ํ์์ ์ธ useEffect ํ ์ ๋์ ์๋ฆฌ๋ถํฐ ์์กด์ฑ ๋ฐฐ์ด, ํด๋ฆฐ์ ํจ์ ํ์ฉ๋ฒ, ๊ทธ๋ฆฌ๊ณ ์ค๋ฌด์์ ์์ฃผ ๊ฒช๋ ์ค์์ ์ต์ ํ ์ ๋ต๊น์ง, ์ด์ค๊ธ ๊ฐ๋ฐ์๋ฅผ ์ํ ์๋ฒฝ ๊ฐ์ด๋๋ฅผ ์ ๊ณตํด์.
- ๋จ์ด: 3,270๊ฐ31๋ถ
[๐ค] Next.js Server Actions ์ค์ : ์๋ฌ ์ฒ๋ฆฌ, ์ ํจ์ฑ ๊ฒ์ฌ, ๋๊ด์ UI ์ ๋ฐ์ดํธ
Next.js Server Actions๋ฅผ ์ค๋ฌด์ ์ ์ฉํ ๋ ๋ง์ฃผํ๋ ์๋ฌ ์ฒ๋ฆฌ, ๋ฐ์ดํฐ ์ ํจ์ฑ ๊ฒ์ฌ, ๊ทธ๋ฆฌ๊ณ ์ฌ์ฉ์ ๊ฒฝํ์ ํฅ์์ํค๋ ๋๊ด์ UI ์ ๋ฐ์ดํธ ๊ธฐ๋ฒ์ ์์ธํ ์ฝ๋ ์์์ ํจ๊ป ์์๋ณด์ธ์.
๋จ์ด: 1,981๊ฐ21๋ถ[๐ค] TypeScript ์ ํธ๋ฆฌํฐ ํ์ ์๋ฒฝ ๊ฐ์ด๋: ์ค์ ํ์ฉ ํจํด
TypeScript ์ ํธ๋ฆฌํฐ ํ์ ์ ํต์ฌ ๊ฐ๋ ๊ณผ ์ค์ ํ์ฉ๋ฒ์ ๊น์ด ์๊ฒ ๋ค๋ค์. Pick, Omit, Partial, Required ๋ฑ ์์ฃผ ์ฐ๋ ์ ํธ๋ฆฌํฐ ํ์ ์ผ๋ก ๋ณต์กํ ํ์ ์ ํจ๊ณผ์ ์ผ๋ก ๋ค๋ฃจ๋ ๋ฐฉ๋ฒ์ ๋ฐฐ์๋ณด์ธ์. ํ์ ์คํฌ๋ฆฝํธ ์ฝ๋์ ์ฌ์ฌ์ฉ์ฑ๊ณผ ์์ ์ฑ์ ๋์ด๋ ๋ ธํ์ฐ๋ฅผ ๊ณต์ ํด์.
- ๋จ์ด: 1,707๊ฐ20๋ถ
[๐ค] Next.js App Router ๋ฏธ๋ค์จ์ด: ๊ฐ๋ ฅํ ์์ฒญ ์ฒ๋ฆฌ ์ ๋ต๊ณผ ์ค์ ์์
Next.js App Router ํ๊ฒฝ์์ ๋ฏธ๋ค์จ์ด๋ฅผ ํ์ฉํด ์ฌ์ฉ์ ์ธ์ฆ, ๋ฆฌ๋ค์ด๋ ์ , ๊ตญ์ ํ ๋ฑ์ ์์ฒญ ์ฒ๋ฆฌ ๋ก์ง์ ํจ์จ์ ์ผ๋ก ๊ตฌํํ๋ ๋ฐฉ๋ฒ์ ์ค์ ์์ ์ ํจ๊ป ์์ธํ ์์๋ณด์ธ์.
- ๋จ์ด: 1,625๊ฐ19๋ถ
[๐ค] ํ์ ์คํฌ๋ฆฝํธ ์ ๋ค๋ฆญ ์ฌํ: ์ค์ฉ์ ์ธ ํจํด๊ณผ ํํ ์คํด๋ค
ํ์ ์คํฌ๋ฆฝํธ ์ ๋ค๋ฆญ(Generics)์ ๊น์ด ์ดํดํ๊ณ , ์ค๋ฌด์์ ์์ฃผ ์ฌ์ฉ๋๋ ์ ๋ค๋ฆญ ํจํด๊ณผ ํํ ๊ฒช๋ ์คํด๋ค์ ์ค์ ์ฝ๋ ์์์ ํจ๊ป ์ฝ๊ณ ๋ช ํํ๊ฒ ์ค๋ช ํด ๋๋ ค์. ํ์ ์์ ์ฑ๊ณผ ์ฝ๋ ์ฌ์ฌ์ฉ์ฑ์ ๋์ด๋ ๋ฐฉ๋ฒ์ ๋ฐฐ์๋ณด์ธ์.
๋จ์ด: 1,846๊ฐ18๋ถ[๐ค] Next.js Route Handler: App Router์์ ์์ ํ๊ณ ํจ์จ์ ์ธ API ๊ตฌ์ถํ๊ธฐ (์ธ์ฆ, ์๋ฌ ์ฒ๋ฆฌ ํฌํจ)
Next.js App Router์ Route Handler๋ฅผ ์ฌ์ฉํ์ฌ API ์๋ํฌ์ธํธ๋ฅผ ๊ตฌ์ถํ๋ ๋ฐฉ๋ฒ์ ์์ธํ ์์๋ด์. ์ธ์ฆ, ์๋ฌ ์ฒ๋ฆฌ, ๊ทธ๋ฆฌ๊ณ ์บ์ฑ ์ ๋ต์ ํฌํจํ ์ค์ฉ์ ์ธ ํ์ผ๋ก ์์ ํ๊ณ ํจ์จ์ ์ธ ์๋ฒ๋ฆฌ์ค ํจ์๋ฅผ ๋ง๋๋ ๋ฐฉ๋ฒ์ ์ตํ๋ด์.
- ๋จ์ด: 1,932๊ฐ22๋ถ
[๐ค] Next.js Image ์ปดํฌ๋ํธ ์ต์ ํ: Core Web Vitals ๊ฐ์ ๋ถํฐ ์ค์ ํ์ฉ๊น์ง
Next.js์ Image ์ปดํฌ๋ํธ๋ฅผ ํ์ฉํ์ฌ ์น ์ฑ๋ฅ ํต์ฌ ์งํ์ธ Core Web Vitals๋ฅผ ๊ฐ์ ํ๊ณ , ๋ค์ํ ์ต์ ํ ์ต์ ์ ์ค์ ํ๋ก์ ํธ์ ์ ์ฉํ๋ ๋ฐฉ๋ฒ์ ๋ธ๋ฃจ๊ฐ ์์ธํ ์๋ ค๋๋ ค์.
- ๋จ์ด: 2,173๊ฐ25๋ถ
[๐ค] Next.js 14.1+์ ํ์ : Partial Prerendering (PPR) ์๋ฒฝ ๊ฐ์ด๋์ ์ค์ ์ต์ ํ ์ ๋ต
Next.js 14.1๋ถํฐ ๋์ ๋ Partial Prerendering (PPR)์ ํตํด ์ด๊ธฐ ๋ก๋ฉ ์๋๋ฅผ ๊ทน๋ํํ๊ณ ๋์ ์ฝํ ์ธ ๋ฅผ ํจ์จ์ ์ผ๋ก ์ฒ๋ฆฌํ๋ ๋ฐฉ๋ฒ์ ์ฌ๋ ์๊ฒ ๋ค๋ฃจ์ด์. PPR์ ๋์ ์๋ฆฌ๋ถํฐ ์ค์ ํ๋ก์ ํธ ์ ์ฉ ์ ๋ต๊น์ง, ๊ฐ๋ฐ์๋ค์ด ๊ถ๊ธํดํ๋ ๋ชจ๋ ๊ฒ์ ์๋ ค๋๋ ค์.
- ๋จ์ด: 1,786๊ฐ19๋ถ
[๐ค] TypeScript ์กฐ๊ฑด๋ถ ํ์ ๊ณผ infer ํค์๋: ๋ณต์กํ ํ์ ๋ ์์ฝ๊ฒ ๋ค๋ฃจ๋ ๋ฐฉ๋ฒ
TypeScript ๊ฐ๋ฐ์์ ๋ง์ฃผํ๋ ๋ณต์กํ ํ์ ์ถ๋ก ๋ฌธ์ , ์กฐ๊ฑด๋ถ ํ์ ๊ณผ infer ํค์๋๋ฅผ ํ์ฉํ๋ฉด ํจ์ฌ ์ฐ์ํ๊ณ ๊ฐ๋ ฅํ๊ฒ ํด๊ฒฐํ ์ ์์ด์. ์ค์ ์์ ์ ํจ๊ป ๊ทธ ํ์ฉ๋ฒ์ ์ฌ๋ ์๊ฒ ๋ค๋ค๋ด ๋๋ค.
- ๋จ์ด: 1,697๊ฐ21๋ถ
[๐ค] JavaScript ์ด๋ฒคํธ ๋ฃจํ(Event Loop) ์์ ์ ๋ณต: ๋น๋๊ธฐ ์ฒ๋ฆฌ์ ๋ฐํ์ ๋์ ์๋ฆฌ
JavaScript์ ํต์ฌ ๋น๋๊ธฐ ์ฒ๋ฆฌ ๋ฉ์ปค๋์ฆ์ธ ์ด๋ฒคํธ ๋ฃจํ์ ๋์ ์๋ฆฌ๋ฅผ ์ฌ๋ ์๊ฒ ํํค์ณ ๋ด์. ์ฝ ์คํ, ํ์คํฌ ํ, ๋ง์ดํฌ๋กํ์คํฌ ํ์์ ์ํธ์์ฉ์ ์ดํดํ๊ณ , ์ค๋ฌด์์ ๋ง์ฃผ์น๋ ๋น๋๊ธฐ ์ฝ๋์ ๋์์ ๋ช ํํ ์์ธกํ๋ ๋ฐฉ๋ฒ์ ์๋ ค๋๋ ค์.
- ๋จ์ด: 1,960๊ฐ23๋ถ
[๐ค] Next.js Server & Client Components, ์ค์ ์์ ํ๋ช ํ๊ฒ ์ ํํ๋ ๊ฐ์ด๋
Next.js App Router์์ Server Components์ Client Components ์ค ์ด๋ค ๊ฒ์ ์ฌ์ฉํด์ผ ํ ์ง ๊ณ ๋ฏผ์ด์ ๊ฐ์? ์ด ๊ธ์์ ๋ ์ปดํฌ๋ํธ์ ํต์ฌ ์ฐจ์ด์ , ์ฌ์ฉ ์์ , ๊ทธ๋ฆฌ๊ณ ์ฑ๋ฅ ์ต์ ํ๋ฅผ ์ํ ์ค์ ์ ๋ต์ ๋ธ๋ฃจ๊ฐ ์๋ ค๋๋ฆด๊ฒ์.
- ๋จ์ด: 1,878๊ฐ21๋ถ
[๐ค] TypeScript satisfies ์ฐ์ฐ์: ํ์ ์ถ๋ก ๊ณผ ์์ ์ฑ์ ๋์์ ์ก๋ ๋น๋ฒ
TypeScript์ `satisfies` ์ฐ์ฐ์๋ฅผ ํ์ฉํ์ฌ ํ์ ์ถ๋ก ์ ์ ์ฐ์ฑ์ ์ ์งํ๋ฉด์๋ ์๊ฒฉํ ํ์ ์์ ์ฑ์ ํ๋ณดํ๋ ๋ฐฉ๋ฒ์ ์์๋ณด์ธ์. ์ค์ฉ์ ์ธ ์์๋ฅผ ํตํด ์ค์ ํ๋ก์ ํธ์ ์ ์ฉํ๋ ๋ ธํ์ฐ๋ฅผ ๊ณต์ ํฉ๋๋ค.
- ๋จ์ด: 1,207๊ฐ15๋ถ
[๐ค] React 19 ์๋ก์ด ๊ธฐ๋ฅ: use ํ , Actions, ๊ทธ๋ฆฌ๊ณ ์ปดํ์ผ๋ฌ ๋ฏธ๋ฆฌ๋ณด๊ธฐ
React 19์ ํต์ฌ ๋ณ๊ฒฝ ์ฌํญ์ธ use ํ , ์๋ฒ ์ก์ , ๊ทธ๋ฆฌ๊ณ React ์ปดํ์ผ๋ฌ์ ๋์ ๋ฐฐ๊ฒฝ๊ณผ ์ค์ ํ์ฉ ์์๋ฅผ ์ด์ค๊ธ ๊ฐ๋ฐ์ ๋๋์ด์ ๋ง์ถฐ ์์ธํ ์ค๋ช ํฉ๋๋ค. ์ต์ React ์ ๋ฐ์ดํธ๋ฅผ ํตํด ์ ํ๋ฆฌ์ผ์ด์ ์ฑ๋ฅ๊ณผ ๊ฐ๋ฐ ๊ฒฝํ์ ํฅ์์ํค๋ ๋ฐฉ๋ฒ์ ์์๋ณด์ธ์.
- ๋จ์ด: 1,512๊ฐ16๋ถ
[๐ค] Next.js App Router ์บ์ฑ ์ ๋ต: ๋ฐ์ดํฐ ์ฌ๊ฒ์ฆ (revalidatePath, revalidateTag) ์๋ฒฝ ๊ฐ์ด๋
Next.js 14 App Router์์ ํจ์จ์ ์ธ ๋ฐ์ดํฐ ์บ์ฑ ์ ๋ต๊ณผ revalidatePath, revalidateTag๋ฅผ ์ด์ฉํ ๋ฐ์ดํฐ ์ฌ๊ฒ์ฆ ๋ฐฉ๋ฒ์ ์ค๋ฌด ์์์ ํจ๊ป ์์ธํ ์์๋ณด๊ณ ์น ์ฑ๋ฅ์ ์ต์ ํํ๋ ๋ฐฉ๋ฒ์ ๋ฐฐ์๋ณด์ธ์.