08. ๐ŸŒ Next.js App Router์™€ ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ

2026๋…„ 4์›” 30์ผ ์ˆ˜์ •๋จ

๐Ÿ“‹ ๊ฐœ์š”

React Server Components(RSC)์˜ ์ฒ ํ•™๊ณผ App Router ์•„ํ‚คํ…์ฒ˜๋ฅผ ํ†ตํ•ด ํ˜„๋Œ€์ ์ธ ๋ Œ๋”๋ง ์ „๋žต์„ ๋งˆ์Šคํ„ฐํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ“Œ ์ด ๋ฉด์ ‘ ํ•ญ๋ชฉ์˜ ๋ชฉํ‘œ

โฑ๏ธ ์˜ˆ์ƒ ์ฝ๊ธฐ ์‹œ๊ฐ„: 26๋ถ„ (ํ•ต์‹ฌ ์š”์•ฝ: 13๋ถ„)

๐Ÿ—บ๏ธ ์ด ์ฑ•ํ„ฐ์˜ ํ๋ฆ„
[๊ฐœ๋… ์‚ฌ์ „] โ†’ [์งˆ๋ฌธ 1: App Router & RSC] โ†’ [์งˆ๋ฌธ 2: ๋ Œ๋”๋ง ์ „๋žต SSR/SSG/ISR] โ†’ [์‹ค์ „ ๋ณ€ํ˜• ์งˆ๋ฌธ]

๐ŸŽฏ ์ด ์ฑ•ํ„ฐ๋ฅผ ๋‹ค ์ฝ์œผ๋ฉด ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ

  • ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ(RSC)์™€ ํด๋ผ์ด์–ธํŠธ ์ปดํฌ๋„ŒํŠธ์˜ ์ฐจ์ด์™€ ์‚ฌ์šฉ ์‹œ์ ์„ ๊ตฌ๋ถ„ํ•ฉ๋‹ˆ๋‹ค.
  • App Router ํ™˜๊ฒฝ์—์„œ ๋ฐ์ดํ„ฐ ํŽ˜์นญ๊ณผ ์บ์‹ฑ์ด ์–ด๋–ป๊ฒŒ ๋ณ€ํ–ˆ๋Š”์ง€ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.
  • ๋น„์ฆˆ๋‹ˆ์Šค ์š”๊ตฌ์‚ฌํ•ญ์— ๋”ฐ๋ผ SSR, SSG, ISR ์ค‘ ์ตœ์ ์˜ ๋ Œ๋”๋ง ๋ฐฉ์‹์„ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ“š ํ•ต์‹ฌ ๊ฐœ๋… ์‚ฌ์ „ (Concept Glossary)

1. ๋ฆฌ์•กํŠธ ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ (React Server Components, RSC)

์„œ๋ฒ„ ๋˜๋Š” ๋นŒ๋“œ ํ™˜๊ฒฝ์—์„œ ์‹คํ–‰๋˜์–ด ๋ Œ๋”๋ง ๊ฒฐ๊ณผ๊ฐ€ RSC Payload๋กœ ์ „๋‹ฌ๋˜๋Š” ์ปดํฌ๋„ŒํŠธ์ž…๋‹ˆ๋‹ค. ์ปดํฌ๋„ŒํŠธ ์ฝ”๋“œ๊ฐ€ ํด๋ผ์ด์–ธํŠธ ๋ฒˆ๋“ค์— ํฌํ•จ๋˜์ง€ ์•Š์œผ๋ฏ€๋กœ ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ๋‹ค์šด๋กœ๋“œํ•˜๊ณ  ํ•˜์ด๋“œ๋ ˆ์ด์…˜ํ•ด์•ผ ํ•  JavaScript๋ฅผ ์ค„์ผ ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์„œ๋ฒ„ ํ™˜๊ฒฝ์˜ ๋ฐ์ดํ„ฐ ์†Œ์Šค์— ์ง์ ‘ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

2. ํ•˜์ด๋“œ๋ ˆ์ด์…˜ (Hydration)

์„œ๋ฒ„์—์„œ ๋งŒ๋“ค์–ด์ง„ ์ •์  HTML ์œ„์— ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ž…ํ˜€ ์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ๋ฅผ ๋‹ฌ๊ณ  ์ธํ„ฐ๋ž™ํ‹ฐ๋ธŒํ•œ ์ƒํƒœ๋กœ ๋งŒ๋“œ๋Š” '๋ถ€ํ™œ' ๊ณผ์ •์ž…๋‹ˆ๋‹ค. RSC๋Š” ํ•˜์ด๋“œ๋ ˆ์ด์…˜์ด ํ•„์š” ์—†๋Š” ๋ถ€๋ถ„์ด ๋Š˜์–ด๋‚œ๋‹ค๋Š” ์ ์ด ํ•ต์‹ฌ์ž…๋‹ˆ๋‹ค.

3. ISR (Incremental Static Regeneration)

๋นŒ๋“œ ์‹œ์ ์— ์ •์  ํŽ˜์ด์ง€๋ฅผ ์ƒ์„ฑ(SSG)ํ•˜๋˜, ์ผ์ • ์‹œ๊ฐ„์ด ์ง€๋‚˜๋ฉด ๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ ํ•ด๋‹น ํŽ˜์ด์ง€๋ฅผ ์ƒˆ๋กœ ์ƒ์„ฑํ•˜์—ฌ ์—…๋ฐ์ดํŠธํ•˜๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค. '์ •์  ํŽ˜์ด์ง€์˜ ์„ฑ๋Šฅ'๊ณผ '๋ฐ์ดํ„ฐ์˜ ์‹ค์‹œ๊ฐ„์„ฑ'์„ ๋ชจ๋‘ ์žก์€ ์ „๋žต์ž…๋‹ˆ๋‹ค.


๐Ÿ—บ๏ธ ์ด ๋ฌธ์„œ์˜ ๋ฐฐ๊ฒฝ ์„ธ๊ณ„๊ด€: '์˜์ˆ˜๋„ค ์ปค๋ฎค๋‹ˆํ‹ฐ'

  • ๐Ÿฃ ์˜์ฒ  (ํ›„๋ฐ˜): "์˜ํ˜ธ ๋‹˜! '์˜์ˆ˜๋„ค ๋ฉ”์ธ ํŽ˜์ด์ง€'์—์„œ ๋‚ ์งœ ํฌ๋งท, ๋งˆํฌ๋‹ค์šด ๋ณ€ํ™˜, ์ถ”์ฒœ ๊ธ€ ๊ณ„์‚ฐ์„ ๋‹ค ํด๋ผ์ด์–ธํŠธ์—์„œ ์ฒ˜๋ฆฌํ–ˆ๋”๋‹ˆ ์ดˆ๊ธฐ ๋กœ๋”ฉ์ด ๋А๋ฆฝ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ๊ธฐ๋Šฅ์„ ๋นผ๊ธฐ๋Š” ์–ด๋ ต์Šต๋‹ˆ๋‹ค."
  • ๐Ÿฆ ์˜ํ˜ธ (๋ฆฌ๋“œ): "์˜์ฒ  ๋‹˜, ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๊ทธ ์ผ์„ ๋ชจ๋‘ ๋งก์„ ํ•„์š”๋Š” ์—†์–ด์š”. ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ(RSC)๋ฅผ ์“ฐ๋ฉด ๋ฌด๊ฑฐ์šด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์™€ ๋ฐ์ดํ„ฐ ๊ฐ€๊ณต์€ ์„œ๋ฒ„์— ๋‚จ๊ธฐ๊ณ , ๋ธŒ๋ผ์šฐ์ €์—๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ์ƒํ˜ธ์ž‘์šฉํ•ด์•ผ ํ•˜๋Š” ์–‡์€ ๊ฒฝ๊ณ„๋งŒ ๋ณด๋‚ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค."

๋ฉด์ ‘ ์งˆ๋ฌธ 1. ๋ฆฌ์•กํŠธ ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ(RSC)์™€ ํด๋ผ์ด์–ธํŠธ ์ปดํฌ๋„ŒํŠธ์˜ ๊ฒฐ์ •์ ์ธ ์ฐจ์ด์™€, ๊ฐ๊ฐ ์–ธ์ œ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š”์ง€ ์„ค๋ช…ํ•ด ๋ณด์„ธ์š”.

๐ŸŽฏ ์ถœ์ œ ์˜๋„

๋ชจ๋˜ ๋ฆฌ์•กํŠธ์˜ ๊ฐ€์žฅ ํฐ ํŒจ๋Ÿฌ๋‹ค์ž„ ๋ณ€ํ™”์ธ '์„œ๋ฒ„ ์ธก ์‹คํ–‰'์„ ์ดํ•ดํ•˜๊ณ  ์žˆ๋Š”์ง€, ๊ทธ๋ฆฌ๊ณ  ํด๋ผ์ด์–ธํŠธ ๋ฒˆ๋“ค ํฌ๊ธฐ๋ฅผ ์ตœ์ ํ™”ํ•˜๋ ค๋Š” ์•„ํ‚คํ…์ฒ˜์  ๊ณ ๋ฏผ์ด ์žˆ๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

๐Ÿฃ ์˜์ฒ ์ด์˜ Naive ๊ตฌํ˜„ (Bad Case)

์˜์ฒ ์ด๋Š” ์—๋Ÿฌ๋ฅผ ๋นจ๋ฆฌ ์—†์• ๊ธฐ ์œ„ํ•ด ๋ชจ๋“  ํŒŒ์ผ ์ตœ์ƒ๋‹จ์— 'use client'๋ฅผ ๋ถ™์ด๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

'use client'; // ๐Ÿฃ ์˜์ฒ : "์ด๊ฒŒ ์—†์œผ๋ฉด ๋‹ค ์—๋Ÿฌ ๋‚˜๋”๋ผ๊ณ ์š”. ๊ทธ๋ƒฅ ๋‹ค ํด๋ผ์ด์–ธํŠธ ์ปดํฌ๋„ŒํŠธ๋กœ ํ•˜๋ฉด ์•ˆ ๋˜๋‚˜์š”?"
 
import { format } from 'date-fns'; // โš ๏ธ ๊ฑฐ๋Œ€ํ•œ ๋‚ ์งœ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ํด๋ผ์ด์–ธํŠธ ๋ฒˆ๋“ค์— ํฌํ•จ๋จ
 
export function PostItem({ post }) {
  // ๋ณ„๋‹ค๋ฅธ ์ธํ„ฐ๋ž™์…˜(onClick ๋“ฑ)์ด ์—†๋Š”๋ฐ๋„ ํด๋ผ์ด์–ธํŠธ ์ปดํฌ๋„ŒํŠธ๋กœ ์„ ์–ธํ•จ
  return <div>{format(new Date(post.createdAt), 'yyyy-MM-dd')}</div>;
}

๐Ÿฆ ์˜ํ˜ธ์˜ ๋ฆฌ๋ทฐ ํฌ์ธํŠธ
"์˜์ฒ  ๋‹˜, 'use client'๋Š” ํด๋ผ์ด์–ธํŠธ ๋ฒˆ๋“ค ๊ฒฝ๊ณ„๋ฅผ ์—ฌ๋Š” ์„ ์–ธ์ž…๋‹ˆ๋‹ค. onClick, useState, window์ฒ˜๋Ÿผ ๋ธŒ๋ผ์šฐ์ € ์‹คํ–‰์ด ํ•„์š”ํ•œ ๋ถ€๋ถ„์—๋งŒ ๋‘๊ณ , ๋ฐ์ดํ„ฐ ๊ฐ€๊ณต์ด๋‚˜ ๋ฌด๊ฑฐ์šด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํ™œ์šฉ์€ ์„œ๋ฒ„์—์„œ ๋๋‚ด๋Š” ํŽธ์ด RSC์˜ ์žฅ์ ์„ ์‚ด๋ฆฝ๋‹ˆ๋‹ค."

๐Ÿฆ ์˜ํ˜ธ์˜ ์•„ํ‚คํ…์ฒ˜ ๊ฐ€์ด๋“œ (Good Case)

์˜ํ˜ธ ๋ฆฌ๋“œ๊ฐ€ ์„œ๋ฒ„์™€ ํด๋ผ์ด์–ธํŠธ์˜ ํ˜‘์—… ๊ตฌ์กฐ๋ฅผ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.

// app/posts/PostList.jsx
// ๐Ÿฆ ์˜ํ˜ธ: "์„œ๋ฒ„๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์ค€๋น„ํ•˜๊ณ , ํด๋ผ์ด์–ธํŠธ๋Š” ์ƒํ˜ธ์ž‘์šฉ๋งŒ ๋‹ด๋‹นํ•˜๊ฒŒ ๋‚˜๋ˆ•๋‹ˆ๋‹ค."
 
// ๐Ÿข Server Component (๊ธฐ๋ณธ๊ฐ’)
// - DB ์ง์ ‘ ์ ‘๊ทผ ๊ฐ€๋Šฅ
// - ๊ฑฐ๋Œ€ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ(date-fns ๋“ฑ)๋ฅผ ์จ๋„ ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ์ „์†ก ์•ˆ ๋จ!
async function PostList() {
  const posts = await db.post.findMany(); // โœ… ์„œ๋ฒ„๋‹ˆ๊นŒ ์ง์ ‘ fetch!
 
  return (
    <div>
      {posts.map(post => (
        <PostItem key={post.id} post={post} />
      ))}
    </div>
  );
}
// app/posts/LikeButton.jsx
// ๐Ÿ“ฑ Client Component ('use client')
// - ์ธํ„ฐ๋ž™์…˜์ด ํ•„์š”ํ•œ ๋ถ€๋ถ„๋งŒ ์ตœ์†Œํ™”ํ•˜์—ฌ ๋ถ„๋ฆฌ
'use client';
 
function LikeButton() {
  const [liked, setLiked] = useState(false);
  return <button onClick={() => setLiked(!liked)}>์ข‹์•„์š”</button>;
}

'use client'๋Š” ํŒŒ์ผ ๋‹จ์œ„ ๊ฒฝ๊ณ„์ž…๋‹ˆ๋‹ค. ํ•œ ํŒŒ์ผ์— ์„ ์–ธํ•˜๋ฉด ๊ทธ ํŒŒ์ผ์ด importํ•˜๋Š” ๋ชจ๋“ˆ๋„ ํด๋ผ์ด์–ธํŠธ ๋ฒˆ๋“ค์— ํฌํ•จ๋  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ, ์ƒํ˜ธ์ž‘์šฉ์ด ํ•„์š”ํ•œ leaf ์ปดํฌ๋„ŒํŠธ ๊ทผ์ฒ˜์— ์ตœ๋Œ€ํ•œ ์ข๊ฒŒ ๋‘๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

๐Ÿ“Š ๋ ˆ๋ฒจ๋ณ„ ๋‹ต๋ณ€ ๊ฐ€์ด๋“œ (Self-Check)

  • Level 1 (Junior): "์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ๋Š” ์„œ๋ฒ„์—์„œ ์‹คํ–‰๋˜๊ณ , ํด๋ผ์ด์–ธํŠธ ์ปดํฌ๋„ŒํŠธ๋Š” ๋ธŒ๋ผ์šฐ์ €์—์„œ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. ํ›…(useState ๋“ฑ)์„ ์“ฐ๋ ค๋ฉด ํด๋ผ์ด์–ธํŠธ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์จ์•ผ ํ•ฉ๋‹ˆ๋‹ค."
  • Level 2 (Senior): "ํด๋ผ์ด์–ธํŠธ ๋ฒˆ๋“ค ์‚ฌ์ด์ฆˆ(Zero-bundle size) ๊ด€์ ์—์„œ์˜ ์ด์ ์„ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค. ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ๋Š” ๋ณด์•ˆ์ƒ ๋ฏผ๊ฐํ•œ ์ •๋ณด๋ฅผ ์ˆจ๊ธธ ์ˆ˜ ์žˆ๊ณ  ์„œ๋ฒ„ ์ž์›์„ ํ™œ์šฉํ•ด ๋ฐ์ดํ„ฐ ํŽ˜์นญ์„ ๊ฐ€์†ํ™”ํ•  ์ˆ˜ ์žˆ์Œ์„ ๊ฐ•์กฐํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ ๋‘ ์ปดํฌ๋„ŒํŠธ ๊ฐ„์˜ '์ง๋ ฌํ™”(Serialization)' ์ œ์•ฝ ์กฐ๊ฑด์„ ์–ธ๊ธ‰ํ•ฉ๋‹ˆ๋‹ค."
  • Level 3 (Specialist): "RSC ํŽ˜์ด๋กœ๋“œ(Payload)์˜ ๊ตฌ์กฐ๋ฅผ ๋ถ„์„ํ•˜๊ณ , ํ•˜์ด๋“œ๋ ˆ์ด์…˜ ๋น„์šฉ์„ ์ค„์ด๋Š” ๋ฉ”์ปค๋‹ˆ์ฆ˜์„ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค. 'Boundary'๋ฅผ ์–ด๋–ป๊ฒŒ ์„ค์ •ํ•˜๋А๋ƒ์— ๋”ฐ๋ผ ์‚ฌ์šฉ์ž ๊ฒฝํ—˜(LCP ๋“ฑ)์ด ์–ด๋–ป๊ฒŒ ๋ณ€ํ•˜๋Š”์ง€ ์‹ค์ œ ํ”„๋กœ์ ํŠธ ๊ฒฝํ—˜์„ ๋ฐ”ํƒ•์œผ๋กœ ๋…ผ๋ฆฌ์ ์œผ๋กœ ๋ถ„์„ํ•ฉ๋‹ˆ๋‹ค."

๋ฉด์ ‘ ์งˆ๋ฌธ 2. SSR, SSG, ISR์˜ ์ฐจ์ด์ ์„ ์„ค๋ช…ํ•˜๊ณ , ์„œ๋น„์Šค์˜ ์„ฑ๊ฒฉ์— ๋”ฐ๋ผ ์–ด๋–ค ์ „๋žต์„ ์„ ํƒํ• ์ง€ ๊ธฐ์ค€์„ ์ œ์‹œํ•ด ๋ณด์„ธ์š”.

๐ŸŽฏ ์ถœ์ œ ์˜๋„

๋‹ค์–‘ํ•œ ๋ Œ๋”๋ง ์ „๋žต์˜ ์žฅ๋‹จ์ ์„ ๋น„์ฆˆ๋‹ˆ์Šค ์ƒํ™ฉ์— ๋งคํ•‘ํ•  ์ˆ˜ ์žˆ๋Š” ์‹ค๋ฌด ๋Šฅ๋ ฅ์„ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. ์„ฑ๋Šฅ(Speed)๊ณผ ์ตœ์‹ ์„ฑ(Freshness) ์‚ฌ์ด์˜ ํŠธ๋ ˆ์ด๋“œ์˜คํ”„๋ฅผ ์ดํ•ดํ•˜๋Š”์ง€๊ฐ€ ํ•ต์‹ฌ์ž…๋‹ˆ๋‹ค.

๐Ÿฃ ์˜์ฒ ์ด์˜ Naive ๊ตฌํ˜„ (Bad Case)

์˜์ฒ ์ด๋Š” '๊ฒ€์ƒ‰ ์—”์ง„ ์ตœ์ ํ™”(SEO)'๊ฐ€ ์ค‘์š”ํ•˜๋‹ค๊ณ  ํ•ด์„œ ๋ชจ๋“  ํŽ˜์ด์ง€๋ฅผ SSR๋กœ ๊ตฌํ˜„ํ–ˆ์Šต๋‹ˆ๋‹ค.

// ๐Ÿฃ ์˜์ฒ : "์„œ๋ฒ„์—์„œ ๋‹ค ๊ทธ๋ ค์„œ ์ฃผ๋‹ˆ๊นŒ ํ•ญ์ƒ SSR์ด ์ข‹์€ ๊ฑฐ ์•„๋‹Œ๊ฐ€์š”?"
export async function getServerSideProps() { // โš ๏ธ Pages Router ๋ฐฉ์‹์˜ ์š”์ฒญ๋ณ„ SSR ์˜ˆ์‹œ
  const data = await fetchLargeData();
  return { props: { data } };
}
 
// โš ๏ธ ๋ฌธ์ œ: ์‚ฌ์šฉ์ž๊ฐ€ ์ ‘์†ํ•  ๋•Œ๋งˆ๋‹ค ์„œ๋ฒ„๊ฐ€ ๋งค๋ฒˆ ํฐ ๋ฐ์ดํ„ฐ๋ฅผ ํŽ˜์นญํ•˜๋А๋ผ
// ์‘๋‹ต ์†๋„(TTFB)๊ฐ€ ๋А๋ ค์ง€๊ณ  ์„œ๋ฒ„ ๋น„์šฉ์ด ํฌ๊ฒŒ ๋Š˜์–ด๋‚จ

๐Ÿฆ ์˜ํ˜ธ์˜ ๋ฆฌ๋ทฐ ํฌ์ธํŠธ
"์˜์ฒ  ๋‹˜, ์•ˆ ๋ณ€ํ•˜๋Š” ํŽ˜์ด์ง€๋ฅผ ์™œ ๋งค๋ฒˆ ์ƒˆ๋กœ ๊ทธ๋ฆฌ๋‚˜์š”? ์ •์  ํŽ˜์ด์ง€(SSG)๋กœ ๋ฏธ๋ฆฌ ๊ตฌ์›Œ๋‘๋ฉด CDN์„ ํƒ€๊ณ  ๋น›์˜ ์†๋„๋กœ ์ „๋‹ฌ๋  ํ…๋ฐ ๋ง์ด์ฃ . SSR์€ '๋‚˜๋งŒ์„ ์œ„ํ•œ ๋ฐ์ดํ„ฐ'๊ฐ€ ์žˆ์„ ๋•Œ๋งŒ ์“ฐ๋Š” ๋„๊ตฌ์˜ˆ์š”."

๐Ÿฆ ์˜ํ˜ธ์˜ ์•„ํ‚คํ…์ฒ˜ ๊ฐ€์ด๋“œ (Good Case)

์˜ํ˜ธ ๋ฆฌ๋“œ๊ฐ€ ์ƒํ™ฉ๋ณ„ ์ตœ์  ๋ Œ๋”๋ง ๋งคํŠธ๋ฆญ์Šค๋ฅผ ์ œ์•ˆํ•ฉ๋‹ˆ๋‹ค.

// ๐Ÿฆ ์˜ํ˜ธ: "์‚ฌ์šฉ์ž๋ณ„๋กœ ๋‹ฌ๋ผ์ง€๋Š”์ง€, ์–ผ๋งˆ๋‚˜ ์ž์ฃผ ๋ฐ”๋€Œ๋Š”์ง€ ๋จผ์ € ๋ณด์„ธ์š”."
 
// 1. SSG (Static Site Generation): ์„œ๋น„์Šค ์†Œ๊ฐœ, ๋ธ”๋กœ๊ทธ ๊ธ€
// - ๋นŒ๋“œ ์‹œ์ ์— ๋”ฑ ํ•œ ๋ฒˆ ์ƒ์„ฑ. ๊ฐ€์žฅ ๋น ๋ฆ„.
export const dynamic = 'force-static';
 
// 2. ISR (Incremental Static Regeneration): ์‡ผํ•‘๋ชฐ ์ƒํ’ˆ ๋ชฉ๋ก, ์‹ค์‹œ๊ฐ„์„ฑ ๊ด‘๊ณ 
// - ์ •์  ํŽ˜์ด์ง€์˜ ์žฅ์ ์„ ๊ฐ€์ง€๋ฉด์„œ๋„ ์ผ์ • ์‹œ๊ฐ„๋งˆ๋‹ค ์ž๋™ ๊ฐฑ์‹ .
export const revalidate = 60; // 60์ดˆ๋งˆ๋‹ค ๊ฐฑ์‹ 
 
// 3. SSR (Server Side Rendering): ๋งˆ์ดํŽ˜์ด์ง€, ์žฅ๋ฐ”๊ตฌ๋‹ˆ
// - ์‚ฌ์šฉ์ž๋งˆ๋‹ค ๊ฒฐ๊ณผ๊ฐ€ ๋‹ค๋ฅผ ๋•Œ. ์ตœ์‹ ์„ฑ 100% ๋ณด์žฅ.
export const dynamic = 'force-dynamic';

๐Ÿ“Š ๋ ˆ๋ฒจ๋ณ„ ๋‹ต๋ณ€ ๊ฐ€์ด๋“œ (Self-Check)

  • Level 1 (Junior): "SSR์€ ์ ‘์†ํ•  ๋•Œ๋งˆ๋‹ค ์„œ๋ฒ„๊ฐ€ ๊ทธ๋ฆฌ๊ณ , SSG๋Š” ๋นŒ๋“œํ•  ๋•Œ ๋ฏธ๋ฆฌ ๋งŒ๋“ญ๋‹ˆ๋‹ค. ISR์€ ์ฃผ๊ธฐ์ ์œผ๋กœ ๋‹ค์‹œ ๋งŒ๋“ญ๋‹ˆ๋‹ค."
  • Level 2 (Senior): "๊ฐ ์ „๋žต์ด ์›น ์ง€ํ‘œ(Core Web Vitals) ์ค‘ ํŠนํžˆ TTFB์™€ LCP์— ์–ด๋–ค ์˜ํ–ฅ์„ ์ฃผ๋Š”์ง€ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ์˜ ์‹ค์‹œ๊ฐ„์„ฑ๊ณผ ์„œ๋ฒ„ ๋ถ€ํ•˜ ๊ฐ„์˜ ํŠธ๋ ˆ์ด๋“œ์˜คํ”„๋ฅผ ๊ณ ๋ คํ•˜์—ฌ ์ „๋žต์„ ์„ ํƒํ•˜๋Š” ๋…ผ๋ฆฌ๋ฅผ ์ œ์‹œํ•ฉ๋‹ˆ๋‹ค."
  • Level 3 (Specialist): "App Router์—์„œ์˜ 'Full Route Cache'์™€ 'Request Memoization' ๊ฐœ๋…์„ ์—ฐ๊ฒฐํ•ฉ๋‹ˆ๋‹ค. ๋‹จ์ˆœํžˆ ํŽ˜์ด์ง€ ๋‹จ์œ„์˜ ์ „๋žต์„ ๋„˜์–ด, ํ•˜๋‚˜์˜ ํŽ˜์ด์ง€ ์•ˆ์—์„œ ํŠน์ • ์ปดํฌ๋„ŒํŠธ๋Š” ISR๋กœ, ์–ด๋–ค ๋ถ€๋ถ„์€ Streaming์„ ํ†ตํ•œ SSR๋กœ ๊ตฌ์„ฑํ•˜๋Š” 'ํ•˜์ด๋ธŒ๋ฆฌ๋“œ ์•„ํ‚คํ…์ฒ˜' ์„ค๊ณ„ ์—ญ๋Ÿ‰์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค."

๋ฉด์ ‘ ์งˆ๋ฌธ 112. Next.js์˜ 'Streaming'๊ณผ 'Suspense'๊ฐ€ ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์„ ๊ฐœ์„ ํ•˜๋Š” ์›๋ฆฌ๋Š” ๋ฌด์—‡์ธ๊ฐ€์š”?

  • ๐ŸŽฏ ์ถœ์ œ ์˜๋„: ๋ฐ์ดํ„ฐ ํŽ˜์นญ์ด ์™„๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ์ „์ฒด ํŽ˜์ด์ง€ ๋ Œ๋”๋ง์„ ์ฐจ๋‹จํ•˜์ง€ ์•Š๊ณ , ๋น„์–ด์žˆ๋Š” ํ™”๋ฉด์„ ์ตœ์ ํ™”ํ•˜๋Š” ๊ธฐ์ˆ ์„ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.
  • ๐Ÿ’ก ํ•ต์‹ฌ ์›๋ฆฌ & ๋‹ต๋ณ€: ๊ธฐ์กด SSR์€ ๋ฐ์ดํ„ฐ๊ฐ€ ๋ชจ๋‘ ์ค€๋น„๋  ๋•Œ๊นŒ์ง€ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋นˆ ํ™”๋ฉด๋งŒ ๋ณด์—ฌ์ฃผ๊ธฐ ์‰ฌ์› ์ง€๋งŒ(All-or-nothing), ์ŠคํŠธ๋ฆฌ๋ฐ์€ ์ค€๋น„๋œ ๋ถ€๋ถ„(๋ฐ์ดํ„ฐ๊ฐ€ ํ•„์š” ์—†๋Š” ์ •์  ๋ ˆ์ด์•„์›ƒ ๋“ฑ)๋ถ€ํ„ฐ ๋จผ์ € ๋ธŒ๋ผ์šฐ์ €์— ์ „์†กํ•ฉ๋‹ˆ๋‹ค. ๋А๋ฆฐ ์ปดํฌ๋„ŒํŠธ๋Š” Suspense ๋ฐ”์šด๋”๋ฆฌ๋กœ ๊ฐ์‹ธ ์Šค์ผˆ๋ ˆํ†ค UI๋ฅผ ๋ณด์—ฌ์ฃผ๊ณ , ๋ฐ์ดํ„ฐ๊ฐ€ ๋„์ฐฉํ•˜๋Š” ๋Œ€๋กœ ํ•ด๋‹น ๋ถ€๋ถ„์„ ์ ์ง„์ ์œผ๋กœ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ์‚ฌ์šฉ์ž์—๊ฒŒ ํŽ˜์ด์ง€๊ฐ€ ๋” ๋นจ๋ฆฌ ๋ฐ˜์‘ํ•œ๋‹ค๋Š” ๋А๋‚Œ(Perceived Performance)์„ ์ค๋‹ˆ๋‹ค.

๋ฉด์ ‘ ์งˆ๋ฌธ 120. next/image ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋‹จ์ˆœํ•œ <img> ํƒœ๊ทธ๋ณด๋‹ค ๋‚˜์€ ์ด์œ ๋Š” ๋ฌด์—‡์ธ๊ฐ€์š”?

  • ๐ŸŽฏ ์ถœ์ œ ์˜๋„: ์ด๋ฏธ์ง€ ์ตœ์ ํ™”๋ผ๋Š” ๊ตฌ์ฒด์ ์ธ ์„ฑ๋Šฅ ๊ฐœ์„  ๋„๊ตฌ์˜ ๋‚ด๋ถ€ ๋™์ž‘์„ ์ดํ•ดํ•˜๊ณ  ์žˆ๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.
  • ๐Ÿ’ก ํ•ต์‹ฌ ์›๋ฆฌ & ๋‹ต๋ณ€: ์ฒซ์งธ, ์ž๋™ ์ด๋ฏธ์ง€ ์ตœ์ ํ™”์ž…๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž์˜ ๊ธฐ๊ธฐ์— ๋งž์ถฐ WebP ๊ฐ™์€ ํ˜„๋Œ€์ ์ธ ํฌ๋งท์œผ๋กœ ๋ณ€ํ™˜ํ•˜๊ณ  ํฌ๊ธฐ๋ฅผ ๋ฆฌ์‚ฌ์ด์ง•ํ•ฉ๋‹ˆ๋‹ค. ๋‘˜์งธ, Lazy Loading์„ ๊ธฐ๋ณธ ์ ์šฉํ•˜์—ฌ ํ™”๋ฉด์— ๋ณด์ด์ง€ ์•Š๋Š” ์ด๋ฏธ์ง€๋Š” ๋‚˜์ค‘์— ๋กœ๋”ฉํ•ฉ๋‹ˆ๋‹ค. ์…‹์งธ, Layout Shift ๋ฐฉ์ง€์ž…๋‹ˆ๋‹ค. ์ด๋ฏธ์ง€ ๋กœ๋”ฉ ์ „์—๋„ ์ •ํ™•ํ•œ ์ž๋ฆฌ๋ฅผ ํ™•๋ณดํ•˜์—ฌ LCP์™€ CLS ์ง€ํ‘œ๋ฅผ ๊ฐœ์„ ํ•ฉ๋‹ˆ๋‹ค. ๋งˆ์ง€๋ง‰์œผ๋กœ CDN ์บ์‹ฑ์„ ํ†ตํ•ด ์›๋ณธ ์„œ๋ฒ„์˜ ๋ถ€ํ•˜๋ฅผ ์ค„์—ฌ์ค๋‹ˆ๋‹ค.

๋ฉด์ ‘ ์งˆ๋ฌธ 135. ๋ฏธ๋“ค์›จ์–ด(Middleware)๋ฅผ ํ™œ์šฉํ•˜์—ฌ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋Š” ์‹ค๋ฌด์ ์ธ ์‚ฌ๋ก€๋ฅผ ๋“ค์–ด๋ณด์„ธ์š”.

  • ๐ŸŽฏ ์ถœ์ œ ์˜๋„: ์š”์ฒญ๊ณผ ์‘๋‹ต ์‚ฌ์ด์˜ ๊ณตํ†ต ๋กœ์ง์„ ํšจ์œจ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฐ€๋กœ์ฑ„๊ธฐ(Interceptor) ํŒจํ„ด์„ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.
  • ๐Ÿ’ก ํ•ต์‹ฌ ์›๋ฆฌ & ๋‹ต๋ณ€: ๊ฐ€์žฅ ๋Œ€ํ‘œ์ ์ธ ์‚ฌ๋ก€๋Š” **์ธ์ฆ ๋ฐ ๊ถŒํ•œ ์ฒดํฌ(Auth Guard)**์ž…๋‹ˆ๋‹ค. ๋กœ๊ทธ์ธ์ด ๋˜์ง€ ์•Š์€ ์‚ฌ์šฉ์ž๊ฐ€ ๋ณดํ˜ธ๋œ ํŽ˜์ด์ง€์— ์ ‘๊ทผํ•  ๋•Œ ๋ Œ๋”๋ง์ด ์‹œ์ž‘๋˜๊ธฐ๋„ ์ „์— ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ ์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ ์‚ฌ์šฉ์ž์˜ ๊ตญ๊ฐ€ ์ •๋ณด์— ๋”ฐ๋ฅธ ๊ตญ์ œํ™”(i18n) ๋ผ์šฐํŒ…, A/B ํ…Œ์ŠคํŠธ๋ฅผ ์œ„ํ•œ ์ฟ ํ‚ค ๊ธฐ๋ฐ˜ ๋ถ„๊ธฐ ์ฒ˜๋ฆฌ, ํ˜น์€ ๋ด‡ ์ฐจ๋‹จ๊ณผ ๊ฐ™์€ ๋ณด์•ˆ ๋กœ์ง์„ ํŽ˜์ด์ง€ ๋ Œ๋”๋ง ์„ฑ๋Šฅ์— ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š์œผ๋ฉด์„œ ์ „์—ญ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๐Ÿ“ ๋งˆ๋ฌด๋ฆฌ ํ€ด์ฆˆ

Q1. 'use client'๋ฅผ ๋ชจ๋“  ์ปดํฌ๋„ŒํŠธ์— ๋ถ™์ด๋Š” ๋ฐฉ์‹์ด ์™œ RSC ๊ด€์ ์—์„œ ์ข‹์ง€ ์•Š์€๊ฐ€์š”?

โœ… ์ •๋‹ต: ์„œ๋ฒ„์—์„œ ๋๋‚ผ ์ˆ˜ ์žˆ๋Š” ๋ฐ์ดํ„ฐ ์กฐํšŒ์™€ ๋ฌด๊ฑฐ์šด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊นŒ์ง€ ํด๋ผ์ด์–ธํŠธ ๋ฒˆ๋“ค๋กœ ๋ณด๋‚ด ์ดˆ๊ธฐ JS ๋น„์šฉ์„ ํ‚ค์šฐ๊ธฐ ๋•Œ๋ฌธ

๐Ÿ’ก ์ƒ์„ธ ํ•ด์„ค:

  • ์›๋ฆฌ ์„ค๋ช…: ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ์˜ ๊ธฐ๋ณธ ๊ฐ€์น˜๋Š” ๋ธŒ๋ผ์šฐ์ €์— ๋ณด๋‚ผ ์ผ์„ ์ค„์ด๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. DB ์ ‘๊ทผ, ๋ฐ์ดํ„ฐ ๊ฐ€๊ณต, ๋ฌด๊ฑฐ์šด ๋ชจ๋“ˆ ์‚ฌ์šฉ์€ ์„œ๋ฒ„์—์„œ ๋๋‚ด๊ณ , ์ƒํ˜ธ์ž‘์šฉ์ด ํ•„์š”ํ•œ ์ž‘์€ ๊ฒฝ๊ณ„๋งŒ ํด๋ผ์ด์–ธํŠธ๋กœ ๋„˜๊ธฐ๋Š” ๊ฒƒ์ด ํ•ต์‹ฌ์ž…๋‹ˆ๋‹ค.
  • ์˜ค๋‹ต ํ”ผ๋“œ๋ฐฑ: ์—๋Ÿฌ๊ฐ€ ์‚ฌ๋ผ์ง„๋‹ค๋Š” ์ด์œ ๋กœ 'use client'๋ฅผ ๋„“ํžˆ๋ฉด, ๋ฌธ์ œ ํ•ด๊ฒฐ์ด ์•„๋‹ˆ๋ผ ์„œ๋ฒ„/ํด๋ผ์ด์–ธํŠธ ์ฑ…์ž„ ๊ฒฝ๊ณ„๋ฅผ ๋ฌด๋„ˆ๋œจ๋ฆฐ ๊ฒƒ์ž…๋‹ˆ๋‹ค.
  • ๐Ÿ“Œ ํ•ต์‹ฌ ๊ธฐ์–ต๋ฒ•: ํด๋ผ์ด์–ธํŠธ ์ปดํฌ๋„ŒํŠธ๋Š” ๊ธฐ๋ณธ๊ฐ’์ด ์•„๋‹ˆ๋ผ ํ•„์š”ํ•œ ๊ฒฝ๊ณ„์ž…๋‹ˆ๋‹ค.

Q2. App Router์—์„œ layout, page, loading, error ํŒŒ์ผ์„ ์ดํ•ดํ•ด์•ผ ํ•˜๋Š” ์ด์œ ๋Š” ๋ฌด์—‡์ธ๊ฐ€์š”?

โœ… ์ •๋‹ต: ๋ผ์šฐํŠธ ์„ธ๊ทธ๋จผํŠธ๋งˆ๋‹ค ๋ฐ์ดํ„ฐ, UI ๊ณตํ†ต ๊ตฌ์กฐ, ์ŠคํŠธ๋ฆฌ๋ฐ, ์—๋Ÿฌ ๋ณต๊ตฌ ๊ฒฝ๊ณ„๋ฅผ ๋‚˜๋ˆŒ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ

๐Ÿ’ก ์ƒ์„ธ ํ•ด์„ค:

  • ์›๋ฆฌ ์„ค๋ช…: App Router๋Š” ๋‹จ์ˆœ ํŒŒ์ผ ๋ผ์šฐํŒ…์ด ์•„๋‹ˆ๋ผ UI์™€ ๋ฐ์ดํ„ฐ ๋กœ๋”ฉ์˜ ๊ฒฝ๊ณ„๋ฅผ ํŒŒ์ผ ์‹œ์Šคํ…œ์œผ๋กœ ํ‘œํ˜„ํ•ฉ๋‹ˆ๋‹ค. ๋ฉด์ ‘์—์„œ๋Š” ์ด ๊ตฌ์กฐ๊ฐ€ UX์™€ ์žฅ์•  ๊ฒฉ๋ฆฌ๋ฅผ ์–ด๋–ป๊ฒŒ ๊ฐœ์„ ํ•˜๋Š”์ง€ ๋งํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • ์˜ค๋‹ต ํ”ผ๋“œ๋ฐฑ: pages ํด๋”์™€ ์ด๋ฆ„๋งŒ ๋‹ค๋ฅธ ๋ผ์šฐํŒ… ๋ฐฉ์‹์ด๋ผ๊ณ  ๋‹ตํ•˜๋ฉด RSC์™€ streaming์˜ ์žฅ์ ์„ ๋†“์นฉ๋‹ˆ๋‹ค.
  • ๐Ÿ“Œ ํ•ต์‹ฌ ๊ธฐ์–ต๋ฒ•: App Router์˜ ํŒŒ์ผ์€ URL๋ณด๋‹ค UI ๊ฒฝ๊ณ„๋ฅผ ๋” ๋งŽ์ด ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.

Q3. ์˜์ฒ ์ด์˜ ํ…Œ์ŠคํŠธ ํƒ€์ž„: ๊ฒŒ์‹œ๊ธ€ ๋ชฉ๋ก์€ ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ, ์ข‹์•„์š” ๋ฒ„ํŠผ์€ ํด๋ผ์ด์–ธํŠธ ์ปดํฌ๋„ŒํŠธ๋กœ ๋‚˜๋ˆˆ ์ด์œ ๋Š” ๋ฌด์—‡์ธ๊ฐ€์š”?

โœ… ์ •๋‹ต: ๋ชฉ๋ก ๋ฐ์ดํ„ฐ ์กฐํšŒ์™€ ๋ Œ๋”๋ง์€ ์„œ๋ฒ„์—์„œ ์ฒ˜๋ฆฌํ•˜๊ณ , ํด๋ฆญ ์ƒํƒœ์™€ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ํ•„์š”ํ•œ ์ตœ์†Œ ๋ถ€๋ถ„๋งŒ ํด๋ผ์ด์–ธํŠธ๋กœ ๋ณด๋‚ด๊ธฐ ์œ„ํ•ด์„œ

๐Ÿ’ก ์ƒ์„ธ ํ•ด์„ค:

  • ์›๋ฆฌ ์„ค๋ช…: RSC์˜ ์„ค๊ณ„ ํŒ๋‹จ์€ "๋ฌด์—‡์ด ๋ธŒ๋ผ์šฐ์ €์—์„œ ๊ผญ ์‹คํ–‰๋˜์–ด์•ผ ํ•˜๋Š”๊ฐ€"๋ฅผ ๋ฌป๋Š” ์ผ์ž…๋‹ˆ๋‹ค. ์ƒํ˜ธ์ž‘์šฉ์ด ์—†๋Š” ๋ฐ์ดํ„ฐ UI๋Š” ์„œ๋ฒ„์— ๋‚จ๊ธฐ๊ณ , ์ด๋ฒคํŠธ๊ฐ€ ํ•„์š”ํ•œ leaf๋งŒ ํด๋ผ์ด์–ธํŠธ๋กœ ๋ณด๋ƒ…๋‹ˆ๋‹ค.
  • ์˜ค๋‹ต ํ”ผ๋“œ๋ฐฑ: ํ•˜๋‚˜์˜ ํŽ˜์ด์ง€๋ผ์„œ ์ „๋ถ€ ๊ฐ™์€ ์‹คํ–‰ ํ™˜๊ฒฝ์— ์žˆ์–ด์•ผ ํ•œ๋‹ค๋Š” ์ƒ๊ฐ์€ ์„œ๋ฒ„/ํด๋ผ์ด์–ธํŠธ ์ปดํฌ๋„ŒํŠธ ๋ชจ๋ธ๊ณผ ๋งž์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  • ๐Ÿ“Œ ํ•ต์‹ฌ ๊ธฐ์–ต๋ฒ•: ๋ธŒ๋ผ์šฐ์ €์—๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ๋งŒ์ง€๋Š” ๋ถ€๋ถ„๋งŒ ์ตœ๋Œ€ํ•œ ์–‡๊ฒŒ ๋ณด๋ƒ…๋‹ˆ๋‹ค.

๐Ÿฃ ์˜์ฒ ์ด์˜ ํ‡ด๊ทผ ์ผ๊ธฐ

์˜ค๋Š˜์€ 'use client'๊ฐ€ ๋ฌธ์ œ ํ•ด๊ฒฐ ์ฃผ๋ฌธ์ด ์•„๋‹ˆ๋ผ ๋น„์šฉ์ด ๋ถ™๋Š” ๊ฒฝ๊ณ„ ์„ ์–ธ์ด๋ผ๋Š” ๊ฑธ ๋ฐฐ์› ๋‹ค. ์˜ˆ์ „ ๊ฐ™์œผ๋ฉด ์—๋Ÿฌ๊ฐ€ ๋‚˜๋ฉด ์ผ๋‹จ ๋ถ™์ด๊ณ  ๋ดค์„ ํ…๋ฐ, ์ด์ œ๋Š” ์ด ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ •๋ง ๋ธŒ๋ผ์šฐ์ €์—์„œ ์‹คํ–‰๋˜์–ด์•ผ ํ•˜๋Š”์ง€ ๋จผ์ € ๋ฌผ์–ด๋ด์•ผ ํ•œ๋‹ค.

๐Ÿ’ก "์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ์˜ ํ•ต์‹ฌ์€ ์ƒˆ ๊ธฐ๋Šฅ์„ ๋”ํ•˜๋Š” ๊ฒŒ ์•„๋‹ˆ๋ผ, ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ํ•˜์ง€ ์•Š์•„๋„ ๋˜๋Š” ์ผ์„ ๋œ์–ด๋‚ด๋Š” ๊ฒƒ์ด๋‹ค."

๋‹ค์Œ ์„ค๊ณ„์—์„œ๋Š” page, layout, loading, error๋ฅผ ๋‹จ์ˆœ ํŒŒ์ผ๋ช…์œผ๋กœ ๋ณด์ง€ ์•Š๊ณ  ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์˜ ๊ฒฝ๊ณ„๋กœ ๋ด์•ผ๊ฒ ๋‹ค. ์˜์ฒ ์ด ์ด์ œ "์–ด๋””์— ์ฝ”๋“œ๋ฅผ ๋‘˜๊นŒ"๋ณด๋‹ค "์–ด๋””์„œ ์‹คํ–‰๋˜์–ด์•ผ ํ• ๊นŒ"๋ฅผ ๋จผ์ € ๋ฌป๊ธฐ ์‹œ์ž‘ํ–ˆ๋‹ค.