๋ฆฌ์•กํŠธ์˜ SSR[ Server Side Rendering ]์„
์‰ฝ๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ฃผ๋Š” ๊ฐ„๋‹จํ•œ ํ”„๋ ˆ์ž„์›Œํฌ
๐Ÿ”ฅ

๋ฆฌ์•กํŠธ๋กœ ๊ฐœ๋ฐœํ•  ๋•Œ SPA[ Single Page Application ] ์ด์šฉํ•˜๋ฉฐ
CSR[ Client Side Rendering ]์„ ํ•˜๊ธฐ์— ์ข‹์€ ์ ๋„ ์žˆ์ง€๋งŒ
๐Ÿ‘Ž๋‹จ์  : ๊ฒ€์ƒ‰์—”์ง„ ์ตœ์ ํ™”( SEO )๐Ÿ”
๐Ÿ‘‰ CSR์„ ํ•˜๋ฉด ์ฒซ ํŽ˜์ด์ง€์—์„œ ๋นˆ html์„ ๊ฐ€์ ธ์™€์„œ JS ํŒŒ์ผ ํ•ด์„ํ•˜์—ฌ
ํ™”๋ฉด์„ ๊ตฌ์„ฑํ•˜๊ธฐ์— ํฌํ„ธ ๊ฒ€์ƒ‰์— ๊ฑฐ์˜ ๋…ธ์ถœ ๋  ์ผ ์—†์Œ๐Ÿ˜ข

Next.jsโžกPre-Rendering์„ ํ†ตํ•ด์„œ
ํŽ˜์ด์ง€๋ฅผ ๋ฏธ๋ฆฌ ๋ Œ๋”๋งํ•˜๋ฉฐ ์™„์„ฑ๋œ HTML์„ ๊ฐ€์ ธ์˜ค๊ธฐ์—
์‚ฌ์šฉ์ž์™€ ๊ฒ€์ƒ‰ ์—”์ง„ ํฌ๋กค๋Ÿฌ์—๊ฒŒ ๋ฐ”๋กœ ๋ Œ๋”๋ง ๋œ ํŽ˜์ด์ง€๋ฅผ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋จโœจ


๐Ÿ’ก ์šฉ์–ด ์ •๋ฆฌ ๐Ÿ’ก

๐Ÿ“ฐํฌ๋กค๋Ÿฌ : ์ธํ„ฐ๋„ท์„ ๋Œ์•„๋‹ค๋‹ˆ๋ฉด์„œ ์›นํŽ˜์ด์ง€์˜ ์ •๋ณด ์ˆ˜์ง‘ํ•˜๋Š” ํ”„๋กœ๊ทธ๋žจ

๊ตฌ๊ธ€ ๊ฐ™์€ ๊ฒ€์ƒ‰ ์—”์ง„์€ ํฌ๋กค๋Ÿฌ ์‚ฌ์šฉํ•ด์„œ ์›น์‚ฌ์ดํŠธ์˜ ๋‚ด์šฉ์„ ์ฝ๊ณ , ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ์— ๋ณด์—ฌ์ค„ ์ •๋ณด๋ฅผ ์ •๋ฆฌํ•จ

๐Ÿ—๏ธPre-Rendering : ๋ณดํ†ต ์›นํŽ˜์ด์ง€ ๋งŒ๋“ค ๋•Œ ๋ธŒ๋ผ์šฐ์ €๊ฐ€ JS๋ฅผ ์‹คํ–‰ํ•ด์„œ ํ™”๋ฉด์„ ๋งŒ๋“ค์ง€๋งŒ
๐Ÿ‘‰ ํŽ˜์ด์ง€๋ฅผ ๋ฏธ๋ฆฌ ์™„์„ฑ๋œ HTML ํ˜•ํƒœ๋กœ ๋งŒ๋“ค์–ด๋‘๋Š” ๊ฒƒ๐Ÿ”ฅ

์ฆ‰, ์„œ๋ฒ„์—์„œ ๋ฏธ๋ฆฌ ํŽ˜์ด์ง€๋ฅผ ๋งŒ๋“ค์–ด ๋†“๊ณ  ์‚ฌ์šฉ์ž๊ฐ€ ์š”์ฒญํ•˜๋ฉด ๋ฐ”๋กœ ๋ณด์—ฌ์ฃผ๋Š” ๋ฐฉ์‹

๐Ÿง ๊ทธ๋Ÿผ ์™œ ์ข‹์•„ โ“

โœ… ๋” ๋น ๋ฆ„โ†’์‚ฌ์šฉ์ž๊ฐ€ ๋“ค์–ด์˜ค์ž๋งˆ์ž ์™„์„ฑ๋œ ํŽ˜์ด์ง€๋ฅผ ๋ณผ ์ˆ˜ ์žˆ์Œ
โœ… ๊ฒ€์ƒ‰ ์—”์ง„ ์ตœ์ ํ™”( SEO ) ๊ฐ€๋Šฅโ†’ํฌ๋กค๋Ÿฌ๊ฐ€ HTML ์‰ฝ๊ฒŒ ์ฝ์„ ์ˆ˜ ์žˆ์–ด ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ์— ์ž˜ ๋…ธ์ถœ๋จ


๐ŸŒCSR[ Client Side Rendering ]

๐Ÿ‘‰ ๋ธŒ๋ผ์šฐ์ €์—์„œ ํ™”๋ฉด์„ ๊ทธ๋ฆฌ๋Š” ๋ฐฉ์‹

1๏ธโƒฃ ์‚ฌ์šฉ์ž๊ฐ€ ์›น์‚ฌ์ดํŠธ์— ์ ‘์†โ†’ex ) localhost:3000/

2๏ธโƒฃ ๋ธŒ๋ผ์šฐ์ €๊ฐ€ HTML์„ ๋ฐ›์Œ โ†’ ๋น„์–ด ์žˆ๋Š” HTML

3๏ธโƒฃ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ( JS ) ํŒŒ์ผ ๋‹ค์šด๋กœ๋“œ ํ›„ ์‹คํ–‰

4๏ธโƒฃ JS๊ฐ€ ์‹คํ–‰๋˜๋ฉด์„œ ํ™”๋ฉด์„ ๊ทธ๋ฆผ ( React, Vue ๋“ฑ์œผ๋กœ ๋ Œ๋”๋ง๋จ๐Ÿ’ป )

5๏ธโƒฃ ์™„์„ฑ๋œ ํ™”๋ฉด์ด ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ณด์ž„

๐Ÿ“Œ ํŠน์ง•

๐Ÿ”น ์ฒ˜์Œ ๋กœ๋”ฉ ๋А๋ฆผ๐Ÿข,, ( JS ํŒŒ์ผ ๋‹ค ๋ฐ›์•„์•ผ ํ™”๋ฉด์ด ๋ณด์ž„ )
๐Ÿ”น ์ดํ›„๋Š” ๋น ๋ฆ„๐Ÿ‡ ( ํ•œ ๋ฒˆ ๋กœ๋”ฉํ•˜๋ฉด ํŽ˜์ด์ง€ ์ด๋™์ด ๋น ๋ฆ„ )
๐Ÿ”น ๊ฒ€์ƒ‰ ์—”์ง„ ํฌ๋กค๋Ÿฌ๊ฐ€ HTML์„ ์ œ๋Œ€๋กœ ๋ชป ์ฝ์„ ์ˆ˜ ์žˆ์Œ ( ๐Ÿ”SEO ๋ถˆ๋ฆฌ๐Ÿ‘Ž )

๐Ÿ–ฅSSR[ Server Side Rendering ]

๐Ÿ‘‰ ์„œ๋ฒ„์—์„œ ํ™”๋ฉด์„ ๊ทธ๋ ค์„œ ๋ณด๋‚ด๋Š” ๋ฐฉ์‹ ( Next.js ์—์„œ ์‚ฌ์šฉ ๊ฐ€๋Šฅ๐Ÿ˜Ž )

1๏ธโƒฃ ์‚ฌ์šฉ์ž๊ฐ€ ์›น์‚ฌ์ดํŠธ์— ์ ‘์†

2๏ธโƒฃ ์„œ๋ฒ„์—์„œ ์š”์ฒญ์„ ๋ฐ›์Œ

3๏ธโƒฃ ์„œ๋ฒ„์—์„œ HTML์„ ๋ฏธ๋ฆฌ ๋งŒ๋“ค์–ด์„œ ์™„์„ฑ๋œ ํŽ˜์ด์ง€๋ฅผ ๋ณด๋ƒ„

4๏ธโƒฃ ์‚ฌ์šฉ์ž๋Š” ๋ฐ”๋กœ ํ™”๋ฉด์„ ๋ณผ ์ˆ˜ ์žˆ์Œ

5๏ธโƒฃ JS๊ฐ€ ์‹คํ–‰๋˜๋ฉด์„œ ์ถ”๊ฐ€ ๊ธฐ๋Šฅ ํ™œ์„ฑํ™” ( ๋ฒ„ํŠผ ํด๋ฆญ, ์• ๋‹ˆ๋ฉ”์ด์…˜ ๋“ฑ )

๐Ÿ“Œ ํŠน์ง•

โœ… ์ฒซ ๋กœ๋”ฉ ๋น ๋ฆ„ ( HTML์ด ์™„์„ฑ๋œ ์ƒํƒœ๋กœ ์ „๋‹ฌโญ• )
โœ… ๊ฒ€์ƒ‰ ์—”์ง„์ด ๋‚ด์šฉ์„ ์‰ฝ๊ฒŒ ์ฝ์„ ์ˆ˜ ์žˆ์Œ ( ๐Ÿ”SEO ์œ ๋ฆฌ๐Ÿ‘ )
โœ… ์„œ๋ฒ„์—์„œ ๋ Œ๋”๋ง์„ ํ•ด์•ผ ํ•˜๋ฏ€๋กœ ์„œ๋ฒ„ ๋ถ€ํ•˜๊ฐ€ ์žˆ์Œ๐Ÿคฏ


๐Ÿ‘ฉโ€๐Ÿ’ป Next.js ์‚ฌ์šฉํ•ด๋ณด์ž โšก

๐Ÿ“๋ฐ”ํƒ•ํ™”๋ฉด์— nextjs-app ํด๋” ๋งŒ๋“ค๊ธฐ

VScode ํ„ฐ๋ฏธ๋„์—์„œ npx create-next-app ./ ๋ช…๋ น์–ด๋กœ Next.js ์„ค์น˜ํ•˜๊ธฐ

์„ค์น˜ํ–ˆ์„ ๋•Œ src/ ํด๋” ์‚ฌ์šฉํ•œ๋‹ค๊ณ  ๋™์˜ํ•ด์„œ ์ƒ๊ธด๊ฒƒ
๊ทธ๋ฆฌ๊ณ  App Router ์‚ฌ์šฉ ์•ˆ ํ•œ๋‹ค๊ณ  ํ–ˆ์–ด์„œ pages ํด๋”๊ฐ€ ์ƒ์„ฑ๋œ๊ฑฐ์ž„

๐Ÿš€next.js ์‹คํ–‰ : npm run dev

โฌ‡

๐Ÿindex.js ํŒŒ์ผ์ด ์‹œ์ž‘์ ์ธ ๊ฑธ ์•Œ ์ˆ˜ ์žˆ์Œ

ํฐํŠธ ์ •์ ์ธ ํŒŒ์ผ๋“ค์ด ์—ฌ๊ธฐ์— ๋“ค์–ด์žˆ์Œ

๐Ÿ”—์ „์—ญ ์Šคํƒ€์ผ์€ src>styles>globals.css ํŒŒ์ผ์— ์žˆ์Œ

์ „์—ญ ์Šคํƒ€์ผ ์ฝ”๋“œ ์ง€์šฐ๋ฉด ์Šคํƒ€์ผ ๋ณ€๊ฒฝ์ด ๋จ

HTML ๋ฌธ์„œ์˜ ๊ธฐ๋ณธ ๊ตฌ์กฐ๋ฅผ ์ปค์Šคํ„ฐ๋งˆ์ด์ง•ํ•  ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ํŒŒ์ผโ—
๋ฆฌ์•กํŠธ์˜ index.html ๊ฐ™์€ ์—ญํ• ์„ ํ•˜๋Š”๋ฐ
Next.js์—์„  ์„œ๋ฒ„์—์„œ ํ•œ ๋ฒˆ๋งŒ ๋ Œ๋”๋ง๋˜๊ณ  ํด๋ผ์ด์–ธํŠธ์—์„œ ๋ณ€๊ฒฝโŒ

  • html, head, body ํƒœ๊ทธ ์ง์ ‘ ์ˆ˜์ • ๊ฐ€๋Šฅโœ”
  • ๊ธ€๋กœ๋ฒŒ ์Šคํƒ€์ผ ์‹œํŠธ( CSS )๋‚˜ ํฐํŠธ, ๋ฉ”ํƒ€ ํƒœ๊ทธ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Œโœ”
  • ๋‹คํฌ ๋ชจ๋“œ ๊ฐ™์€ ํ…Œ๋งˆ ์„ค์ • ํ•  ๋•Œ ์œ ์šฉโœ”

๐Ÿ˜ฏ ../.. ์ด๊ฑฐ ๋Œ€์‹  @ ์ด๋ ‡๊ฒŒ ํ•  ์ˆ˜ ์žˆ์Œ

โš™๏ธnext.js ์„ค์ •( config )ํ•˜๋Š” ํŒŒ์ผ ( ์—„์ฒญ ๋งŽ์€ ์„ค์ • ํ•  ์ˆ˜ ์žˆ์Œ )

reactStrictMode: true ์„ค์ •ํ•˜๋ฉด ๊ฐœ๋ฐœ ์ค‘์— ๋ฌธ์ œ๋ฅผ ๊ฐ์ง€ํ•˜๊ณ  ๊ฒฝ๊ณ ๋ฅผ ๋ณด์—ฌ์ฃผ๋Š” ๋ชจ๋“œ๊ฐ€ ์ผœ์ง๐Ÿ’ก

postcss.config.mjs ํŒŒ์ผ์€ tailwind.css ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ ํŒŒ์ผ

tailwind๋Š” css ํ”„๋ ˆ์ž„์›Œํฌ( ๋ฌด์กฐ๊ฑด ๋ฐฐ์›Œ์•ผํ•˜๋Š” CSS Framework )

F1๏ธโƒฃ2๏ธโƒฃ ๋ˆŒ๋Ÿฌ์„œ ์†Œ์Šค๋ณด๊ธฐํ•˜๋ฉด

๊ทธ๋ƒฅ ๋ฆฌ์•กํŠธ๋Š” ์ด๋ ‡๊ฒŒ ๋˜์–ด์žˆ์Œ ( ์ฝ์–ด์•ผ ๋˜๋Š” ๋ถ€๋ถ„์ด ํ…… ๋น„์–ด์žˆ์Œ ) ๋ฐ˜๋ฉด์—

Next.js๋Š” ์ด๋ ‡๊ฒŒ ๋˜์–ด์žˆ์Œ

npm run build๋ฅผ ํ•˜๊ณ 

์—ฌ๊ธฐ๋ฅผ ๋ณด๋‹ˆ๊นŒ Generating static pages 3๊ฐœ ๋ผ๊ณ  ๋˜์–ด์žˆ์Œ

3๊ฐœ์˜ ํŒŒ์ผ์ด ๋งŒ๋“ค์–ด์ ธ์žˆ๋Š”๊ฑธ ๋ณผ ์ˆ˜ ์žˆ์Œ

Next.js๋Š” ์ •์  ํŽ˜์ด์ง€( SSG )์šฉ index.html ํ•˜๊ณ 
์˜ค๋ฅ˜ ํŽ˜์ด์ง€( 404.html, 500.html )๋ฅผ ๋ฏธ๋ฆฌ ์ƒ์„ฑํ•ด์„œ ๋ฐฐํฌํ•  ๋•Œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•จ๐Ÿ”ฅ
๐Ÿ‘‰ 404 ( Not Found ) : ์—†๋Š” ํŽ˜์ด์ง€์— ์ ‘๊ทผํ–ˆ์„ ๋•Œ ๋‚˜ํƒ€๋‚˜๋Š” ์˜ค๋ฅ˜
๐Ÿ‘‰ 500 ( Internal Server Error ) : ์„œ๋ฒ„์—์„œ ๋ฌธ์ œ ์ƒ๊ฒผ์„ ๋•Œ ๋‚˜ํƒ€๋‚˜๋Š” ์˜ค๋ฅ˜


โœ‹์ž ๊นโœ‹

๐Ÿ—๏ธPre-rendering

NextJSโžก๋ชจ๋“  ํŽ˜์ด์ง€๋ฅผ pre-render ํ•จโšก

pre-render ํ•œ๋‹ค๋Š” ์˜๋ฏธ : ๋ชจ๋“  ํŽ˜์ด์ง€๋ฅผ ์œ„ํ•œ HTML์„
Client ์‚ฌ์ด๋“œ์—์„œ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋กœ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์ „ "์‚ฌ์ „์—" ์ƒ์„ฑํ•œ๋‹ค๋Š” ๊ฒƒ
์ด๋ ‡๊ฒŒ ํ•˜๊ธฐ์— ๐Ÿ”SEO ๊ฒ€์ƒ‰์—”์ง„ ์ตœ์ ํ™”๊ฐ€ ์ข‹์•„์ง๐Ÿ‘

๐Ÿ”น Client ์‚ฌ์ด๋“œ : ํฌ๋กฌ, ์‚ฌํŒŒ๋ฆฌ ๊ฐ™์€ ๋ธŒ๋ผ์šฐ์ €์—์„œ ์›น์‚ฌ์ดํŠธ ์—ด์—ˆ์„ ๋•Œ
๊ทธ ๋ธŒ๋ผ์šฐ์ €์—์„œ ์‹คํ–‰๋˜๋Š” ์ฝ”๋“œ( HTML, CSS, JS ๋“ฑ )

๐Ÿ“ฐํฌ๋กค๋Ÿฌ( ์ •๋ณด ์ˆ˜์ง‘ ํ”„๋กœ๊ทธ๋žจ )๊ฐ€ index.html ๋ณด๊ณ ์„œ
ํฌ๋กค๋งํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— SEO ๊ฒ€์ƒ‰์—”์ง„์ด ์ข‹์•„์งˆ ์ˆ˜ ๋ฐ–์— ์—†๋Š”๊ฑฐ๐Ÿ”

์ฆ‰, ํฌ๋กค๋Ÿฌ๊ฐ€ ๋ฏธ๋ฆฌ ๋ Œ๋”๋ง๋œ HTML์„ ์ฝ์œผ๋‹ˆ๊นŒ, ํŽ˜์ด์ง€๊ฐ€ ๋” ์ž˜ ๊ฒ€์ƒ‰๋  ์ˆ˜๋ฐ–์— ์—†๋Š” ๊ฒƒโœŒ

๐Ÿ”ซ๋ฆฌ์•กํŠธ์—์„œ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋ฅผ ๋””๋ฒ„๊ทธ( disable ) ์‹œ์ผœ๋ณด๊ธฐ( JS๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ฒ ๋‹ค๋Š” ๊ฒƒ )

๐Ÿค” ๊ทธ๋Ÿฌ๊ณ  ์ƒˆ๋กœ๊ณ ์นจํ•˜๋‹ˆ๊นŒ ์ด๋ ‡๊ฒŒ ๋œจ๋Š”๋ฐ ์™œ ์ด๋ ‡๊ฒŒ ๋‚˜์˜ค๋Š”๊ฑธ๊นŒ โ“

CSR ์ˆœ์„œ ์ค‘์—์„œ JS๋ฅผ ๋ง‰์€๊ฑฐ๋‹ˆ๊นŒ ๋ณด์ด๋Š” ํ™”๋ฉด์ด ์ด๋ถ€๋ถ„์ธ ๊ฒƒ,,,๐Ÿ˜ฏ๐Ÿ’ก
๊ณ„์† ์ง„ํ–‰์ด ๋ผ์•ผ ํ™”๋ฉด์ด ๋ณด์—ฌ์ง€๊ธฐ ๋•Œ๋ฌธ์— ์ด๋Ÿฐ ํ˜„์ƒ์ด ๋ฐœ์ƒํ•˜๋Š”๊ฑฐ์ž„

next.js๋ฅผ ๋˜‘๊ฐ™์ด disable ์‹œ์ผœ๊ณ  ์ƒˆ๋กœ๊ณ ์นจ ํ•ด๋„ ํ™”๋ฉด์ด ๋˜‘๊ฐ™์Œโ—
๐Ÿค” ์ด๊ฑด ์™œ ํ™”๋ฉด์ด ๋˜‘๊ฐ™์ด ๋‚˜์˜ฌ๊นŒ โ“

JS ๋ถ€๋ถ„์„ ๋ง‰์•˜์ง€๋งŒ ๋ณด๋Š”๋ฐ๋Š” ์ง€์žฅ์—†์Œ๐Ÿ™…โ€โ™€๏ธ
์™œ๋ƒ, ์ด๋ฏธ html์„ ๋งŒ๋“ค์–ด๋†”์„œ ์ด๊ฑธ ํ™”๋ฉด์—์„œ ๋ณด์—ฌ์ฃผ๊ธฐ ๋•Œ๋ฌธโœจ

ํ•˜์ง€๋งŒ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๊ฑฐ๋‚˜ ํ–ˆ์„ ๋• ๋™์ž‘์ด ์•ˆ ๋  ๊ฒƒ ( JS ์˜์—ญ )

Next.js ์—์„  ์ฒจ์— ๋กœ๋“œํ•  ๋•Œ ์ด๋ฏธ ์‚ฌ์ „์— ์ค€๋น„๋œ html์„ ๋ณด์—ฌ์ฃผ๊ณ 
๊ทธ๋‹ด์— JS๋ฅผ ๋‹ค์šด๋กœ๋“œ ํ•จ๐Ÿ“ฅ

๊ทธ๋Ÿฌ๊ณ  ๋ฆฌ์•กํŠธ๋ฅผ ์‹คํ–‰ํ•˜๊ณ  ์ด๋•Œ ํ•˜๋Š” ๊ฑธ ๐Ÿ’ง'Hydration'( ์ˆ˜๋ถ„์„ ๊ณต๊ธ‰ ) ์ด๋ผ๊ณ  ํ•จ
๐Ÿ‘‰ HTML๊ณผ JS๊ฐ€ ํ•ฉ์ณ์ ธ์„œ React ์•ฑ์ด ์™„์„ฑ๋˜๋Š” ๊ณผ์ •๐Ÿ’ก

๊ทธ๋Ÿฌ๋ฉด ์ด์ œ ์ƒํ˜ธ์ž‘์šฉํ•œ ์•ฑ์ด ๋˜๋Š” ๊ฒƒ ๐Ÿ”ฅ

๋ฆฌ์•กํŠธ์—์„  ์ฒจ์—” ์•„๋ฌด๊ฒƒ๋„ ์•ˆ ์ผ์–ด๋‚˜๊ณ  JS ๋‹ค์šด๋กœ๋“œํ•˜๊ณ  ๋ฆฌ์•กํŠธ๋ฅผ ์‹คํ–‰ํ•จ
๊ทธ ๋‹ค์Œ ํ™”๋ฉด์ด ๋‚˜ํƒ€๋‚˜๊ณ  ์ƒํ˜ธ์ž‘์šฉ ๊ฐ€๋Šฅํ• ๊ฑฐ์ž„๐Ÿ™†โ€โ™€๏ธ


๐Ÿ˜ŽData Fetching

๐Ÿ”Next.js ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๋ฐฉ๋ฒ•์€โ“

์—ฌ๋Ÿฌ๊ฐ€์ง€๊ฐ€ ์žˆ์–ด์„œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์‚ฌ์šฉ ์šฉ๋„์— ๋”ฐ๋ผ ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์œผ๋กœ ์‚ฌ์šฉํ•ด์ฃผ๋ฉด ๋จ
๋ณดํ†ต React ์—์„  ๋ฐ์ดํ„ฐ ๊ฐ€์ ธ์˜ฌ ๋•Œ useEffect ์•ˆ์—์„œ ๊ฐ€์ ธ์˜ด
ํ•˜์ง€๋งŒ Next.js ์—์„  ๋‹ค๋ฅธ ๋ฐฉ๋ฒ• ์‚ฌ์šฉํ•ด์„œ ๊ฐ€์ ธ์˜ด

๐Ÿ“Œ React ์—์„œ useEffect ์‚ฌ์šฉํ•œ ๋ฐ์ดํ„ฐ ์š”์ฒญ ํ๋ฆ„

user๊ฐ€ ์„œ๋ฒ„ํ•œํ…Œ ๋ฐ์ดํ„ฐ๋ฅผ ์š”์ฒญ( request )๋ณด๋‚ผ ๋•Œ
์ปดํฌ๋„ŒํŠธ์— useEffect ์•ˆ์—์„œ ์š”์ฒญ์„ ๋ณด๋ƒˆ์—ˆ์Œ
โœ… ์ˆœ์„œ : state ๋ถ€๋ถ„๋“ค์ด ์ƒ์„ฑโžกUI ๋ถ€๋ถ„ ๋ Œ๋”๋งโžก๊ทธ ๋‹ค์Œ useEffect ์‹คํ–‰

1๏ธโƒฃ user๊ฐ€ localhost:3000 ๊ฒฝ๋กœ๋กœ ์ ‘์†
๐Ÿ‘‰ ํ•ด๋‹น ํŽ˜์ด์ง€์˜ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์‹คํ–‰๋จ

2๏ธโƒฃ ์‹คํ–‰ํ•œ ํ•ด๋‹น ์ปดํฌ๋„ŒํŠธ์˜ state๊ฐ€ ์ƒ์„ฑ
๐Ÿ‘‰ useState๋กœ ๊ด€๋ฆฌํ•˜๋Š” ์ƒํƒœ ๋ณ€์ˆ˜๋“ค์ด ์ดˆ๊ธฐ๊ฐ’์„ ๊ฐ€์ง๐Ÿ”„

3๏ธโƒฃ UI๊ฐ€ ๋ Œ๋”๋ง๋จ ( return ๋ถ€๋ถ„ ์‹คํ–‰ )
๐Ÿ‘‰ ํ™”๋ฉด์— ์ดˆ๊ธฐ UI๊ฐ€ ํ‘œ์‹œ๋จ( ์•„์ง ๋ฐ์ดํ„ฐ ์—†์ŒโŒ )

4๏ธโƒฃ useEffect ์‹คํ–‰
๐Ÿ‘‰ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ Œ๋”๋ง๋œ ํ›„ ๋น„๋™๊ธฐ ์š”์ฒญ( fetching ) ์‹œ์ž‘

5๏ธโƒฃ ๋น„๋™๊ธฐ ๋ฐ์ดํ„ฐ ์š”์ฒญ( fetching ) ๋ฐœ์ƒ
๐Ÿ‘‰ API ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ด ( ex - fetch or axios ์‚ฌ์šฉโญ• )

6๏ธโƒฃ ๊ฐ€์ ธ์˜จ ๋ฐ์ดํ„ฐ state์— ์ €์žฅ
๐Ÿ‘‰ setState ์‚ฌ์šฉํ•ด ์ƒํƒœ๋ฅผ ์—…๋ฐ์ดํŠธ๐Ÿ†™

7๏ธโƒฃ state ๋ณ€๊ฒฝ๋์œผ๋‹ˆ ์ปดํฌ๋„ŒํŠธ ๋ฆฌ๋ Œ๋”๋ง
๐Ÿ‘‰ ์ƒˆ๋กœ์šด ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ˜์˜ํ•œ UI๊ฐ€ ๋‹ค์‹œ ๋ Œ๋”๋ง๋จ

๐Ÿ”ฅNext.js์˜ ๋ฐ์ดํ„ฐ ๊ฐ€์ ธ์˜ค๋Š” 3๊ฐ€์ง€ ๋ฐฉ๋ฒ•

๐Ÿ”ธ getStaticProps : ์ •์ ์ธ HTML์„ ๋ฏธ๋ฆฌ ๋งŒ๋“ค์–ด์„œ ๋น ๋ฅด๊ฒŒ ๋ณด์—ฌ์คŒ

  • ๋นŒ๋“œ ํƒ€์ž„์— ์‹คํ–‰ โ†’ HTML ๋ฏธ๋ฆฌ ๋งŒ๋“ค์–ด์„œ ์†๋„ ๋น ๋ฆ„๐Ÿš€
  • ํŽ˜์ด์ง€์— ๋ณ€๋™์ด ๊ฑฐ์˜ ์—†๋Š” ๋ฐ์ดํ„ฐ์— ์ ํ•ฉ ( ex - ๋ธ”๋กœ๊ทธ ๊ธ€, ์ œํ’ˆ ๋ชฉ๋ก )

๐Ÿค“ ์˜ˆ์ œ : ๋ธ”๋กœ๊ทธ ๊ฒŒ์‹œ๊ธ€ ๋ฏธ๋ฆฌ ๋งŒ๋“ค์–ด๋‘๊ธฐ

export async function getStaticProps() {
  const res = await fetch("https://api.example.com/posts");
  const posts = await res.json();

  return { props: { posts } };
}

๐Ÿ’ก ๊ฒฐ๊ณผ : ๋นŒ๋“œํ•  ๋•Œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์™€์„œ ์™„์„ฑ๋œ HTML์„ ๋ณด์—ฌ์คŒ

๐Ÿ”ธ getStaticPaths : ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์ •์  ํŽ˜์ด์ง€๋ฅผ ๋ฏธ๋ฆฌ ๋งŒ๋“ค์–ด ๋‘ 

  • getStaticProps์™€ ํ•จ๊ป˜ ์‚ฌ์šฉโœ”
  • ๋™์ ์ธ ๊ฒฝ๋กœ( ex - /posts/1, /posts/2 )๋ฅผ ๋ฏธ๋ฆฌ ์ƒ์„ฑํ•  ๋•Œ ์‚ฌ์šฉโœ”

๐Ÿค“ ์˜ˆ์ œ : ์—ฌ๋Ÿฌ ๊ฐœ์˜ ๋ธ”๋กœ๊ทธ ๊ธ€ ํŽ˜์ด์ง€ ๋ฏธ๋ฆฌ ๋งŒ๋“ค๊ธฐ

export async function getStaticPaths() {
  const res = await fetch("https://api.example.com/posts");
  const posts = await res.json();

  const paths = posts.map((post) => ({
    params: { id: post.id.toString() },
  }));

  return { paths, fallback: false };
}

๐Ÿ’ก ๊ฒฐ๊ณผ : /posts/1, /posts/2 ๊ฐ™์€ ํŽ˜์ด์ง€๋“ค์„ ๋ฏธ๋ฆฌ ๋งŒ๋“ค์–ด๋‘ 

๐Ÿ”ธ getServerSideProps : ๋งค๋ฒˆ ์ƒˆ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ด

  • ์‚ฌ์šฉ์ž๊ฐ€ ์ ‘์†ํ•  ๋•Œ๋งˆ๋‹ค ์„œ๋ฒ„์—์„œ ์‹คํ–‰๋จ
  • ํ•ญ์ƒ ์ตœ์‹  ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์™€์•ผ ํ•  ๋•Œ ์ ํ•ฉ ( ex - ์‹ค์‹œ๊ฐ„ ๋‰ด์Šค, ์‚ฌ์šฉ์ž๋ณ„ ๋ฐ์ดํ„ฐ )

๐Ÿค“ ์˜ˆ์ œ : ์ ‘์†ํ•  ๋•Œ๋งˆ๋‹ค ์ตœ์‹  ๋‰ด์Šค ๋ถˆ๋Ÿฌ์˜ค๊ธฐ

export async function getServerSideProps() {
  const res = await fetch("https://api.example.com/news");
  const news = await res.json();

  return { props: { news } };
}

๐Ÿ’ก ๊ฒฐ๊ณผ : ์‚ฌ์šฉ์ž๊ฐ€ ํŽ˜์ด์ง€๋ฅผ ๋ฐฉ๋ฌธํ•  ๋•Œ๋งˆ๋‹ค ์ตœ์‹  ๋‰ด์Šค ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ด


๐Ÿฑโ€๐Ÿ’ป์‹ค์ œ ์‚ฌ์šฉํ•ด๋ณด์žโšก

โ–ซ src>pages>index.js

์ด๋ถ€๋ถ„ ์ „์ฒด ๋‹ค ์ง€์šฐ๊ณ 

div ํƒœ๊ทธ๋งŒ ๋‚จ๊ฒจ๋‘๊ฒ ์Œ

โ–ซ src>styles>globals.css

10๋ฒˆ ์ค„๋ถ€ํ„ฐ ์‹น ๋‹ค ์ง€์šฐ๊ณ 

โฌ‡

npm run dev๋กœ ์‹คํ–‰ํ•ด๋ณด๋ฉด ์ด๋Ÿฐ์‹์œผ๋กœ ๋˜๋Š” ๊ฑธ ๋ณผ ์ˆ˜ ์žˆ์Œ๐Ÿ‘€

โ–ซ src>pages>index.js

Head ํƒœ๊ทธ ์•ˆ์— title Your Name ์“ฐ๋ฉด ์ œ๋ชฉ์ด ์ ํ˜€์ง

๐Ÿ”–section ์‹œ๋ฉ˜ํ‹ฑ ํƒœ๊ทธ๋ฅผ ์ด์šฉํ•ด์„œ p ํƒœ๊ทธ ์•ˆ์—
[Your Self Introduction] ์ด๋ž‘ (This is a website) ๐Ÿ‘Œ

๐Ÿ”–๋ฌธ์„œ์˜ ํŠน์ • ์ฃผ์ œ๋ฅผ '๊ทธ๋ฃนํ™”' ํ•˜๋Š” ์šฉ๋„๋กœ ์‚ฌ์šฉ๋˜๋Š” ๋ธ”๋ก ์š”์†Œ

๋˜ section ํ•˜๋‚˜ ๋” ํ•ด์„œ ๋ถ€์ œ๋ชฉ์œผ๋กœ Blog ํ•ด์ฃผ๊ณ 
๊ทธ ๋ฐ‘์— ul ์ˆœ์„œ ์—†๋Š” ํƒœ๊ทธ ์ด๋ ‡๊ฒŒ ํ•ด๋†“๊ธฐ

โฌ‡

๊ทธ๋Ÿฐ ๋‹ด์— ์ด์ œ ํ•ด์•ผํ•˜๋Š”๊ฑด Blog ๋“ค์„ ๋‚˜์—ดํ•˜๋ฉด ๋จโœ”

๋ธ”๋กœ๊ทธ๋“ค์„ ์ œ๋ชฉ๋“ค๋งŒ ๋‚˜์—ดํ•œ๊ฑด๋ฐ When~ ์ด๋ถ€๋ถ„์„ ์œ„ํ•œ ํŒŒ์ผ์ด๋ž‘
Two~ ์ด๋ถ€๋ถ„์„ ์œ„ํ•œ ํŒŒ์ผ ์ด 2๊ฐœ๋ฅผ ๋งŒ๋“ค๊ฑฐ์ž„๐Ÿ™†โ€โ™€๏ธ

pre-render.md ํŒŒ์ผ์ด๋ž‘ static.md ํŒŒ์ผ ๋งŒ๋“ค๊ธฐ

'๋งˆํฌ๋‹ค์šด ํŒŒ์ผ'์„ ์ด๋Ÿฐ์‹์œผ๋กœ ๋„ฃ์—ˆ์Œ

โ™ ํ…์ŠคํŠธ๋ฅผ ๊ฐ„๋‹จํ•œ ๊ทœ์น™์„ ์‚ฌ์šฉํ•ด์„œ ๊พธ๋ฏธ๋Š” ํŒŒ์ผ
๋งˆํฌ๋‹ค์šด ์‚ฌ์šฉํ•˜๋ฉด ๋ฌธ์„œ๋ฅผ ๋น ๋ฅด๊ฒŒ ์ž‘์„ฑํ•˜๊ณ ,
HTML์ฒ˜๋Ÿผ ๋ณต์žกํ•œ ํƒœ๊ทธ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ ๋„
๊ธ€์ž ํฌ๊ธฐ, ์ œ๋ชฉ, ๋ฆฌ์ŠคํŠธ, ๋งํฌ, ์ด๋ฏธ์ง€ ๋“ฑ์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์ŒโœŒ

DB๊ฐ€ ์ง€๊ธˆ ์—†์œผ๋‹ˆ๊นŒ ๊ทธ๋ž˜์„œ ๊ทธ๋ƒฅ ํŒŒ์ผ์—๋‹ค๊ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ๋„ฃ์–ด๋‘” ๊ฒƒโ—
๋ธ”๋กœ๊ทธ ํ•˜๋‚˜์˜ ๊ฒŒ์‹œ๋ฌผ์— ๋Œ€ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ๋„ฃ์–ด๋‘”๊ฑฐ์ž„๐Ÿš€

์›๋žœ ์–˜๋„ค๋“ค์ด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋“ค์–ด์žˆ์„๊ฑฐ์ž„โญ•

posts ๋ผ๋Š” ํด๋”๋ฅผ ๋งŒ๋“ค๊ณ  ์ด ์•ˆ์— pre-render.md & static.md ํŒŒ์ผ์„ ๋„ฃ์–ด์ฃผ๊ธฐ

Blog ๋ฐ‘์—๋‹ค๊ฐ€ ์ด๋ถ€๋ถ„๋งŒ ๊ฐ€์ ธ์™€์„œ ํ™”๋ฉด์— ๋ณด์ด๊ฒŒ ํ•  ๊ฒƒ๐Ÿค“

์ด ๋ฐ์ดํ„ฐ๋“ค์„ ๊ฐ€์ ธ์™€์•ผํ•˜๋Š”๋ฐ Next.js๋‹ˆ๊นŒ ์–ธ์ œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์™€์•ผํ• ๊นŒโ“
๐Ÿ‘‰ build time

โœ… ๋ฆฌ์•กํŠธ ์ผ์„ ๋• useEffect ์จ์„œ ๋ฐ์ดํ„ฐ ์š”์ฒญํ•ด์„œ ๊ฐ€์ ธ์™”์—ˆ์Œ

๋ฐ์ดํ„ฐ ๊ฐ€์ ธ์˜ค๊ธฐ ์œ„ํ•ด์„œ ๋‘ ๊ฐœ์˜ ํŒŒ์ผ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์™€์•ผํ•˜๋Š”๋ฐ
๊ทธ๋Ÿฌ๊ธฐ ์œ„ํ•ด ๋‘ ๊ฐœ์˜ ํŒŒ์ผ์— ์ ‘๊ทผํ•ด์•ผํ•จโšก

์ด fs๋Š” ํŒŒ์ผ ์‹œ์Šคํ…œ์ด๋ผ๊ณ  ํ•˜๋Š” API
๐Ÿ‘‰ Node.js ๋•๋ถ„์— ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์• ๐Ÿ”ฅ

โŒclient side ์—์„  ์‚ฌ์šฉ ๋ถˆ๊ฐ€โŒ
๐Ÿคทโ€โ™€๏ธ์™œโ“โžกclient side ์—์„  ๋ธŒ๋ผ์šฐ์ €์—์„œ ์ œ๊ณตํ•ด์ฃผ๋Š”๊ฑธ ์“ธ ์ˆ˜ ์žˆ๋Š”๋ฐ
fs๋Š” ๋ธŒ๋ผ์šฐ์ €์—์„œ ์ œ๊ณตํ•ด์ฃผ๋Š” ๊ฒƒ์ด ์•„๋‹Œ, Node.js ์—์„œ ์ œ๊ณตํ•ด์ฃผ๊ธฐ ๋•Œ๋ฌธโ—

Node.js ์—์„œ ์ œ๊ณตํ•ด์ฃผ๋Š”๊ฑธ ์–ด๋–ป๊ฒŒ ์“ธ ์ˆ˜ ์žˆ๋ƒ๋ฉด
๐Ÿ“ฅ์šฐ๋ฆฌ ์ปดํ„ฐ์— ์ด๋ฏธ Node.js๊ฐ€ ์„ค์น˜ ๋˜์–ด์žˆ์Œ๐Ÿ˜Ž

๐Ÿ“fs๊ฐ€ ํ•˜๋Š” ์ผ : ํŒŒ์ผ์„ ์ˆ˜์ • ํ˜น์€ ์‚ญ์ œํ•˜๊ฑฐ๋‚˜, ์—…๋ฐ์ดํŠธ ํ•˜๊ฑฐ๋‚˜ ํ•  ์ˆ˜ ์žˆ์Œโœ”

์ง€๊ธˆ ์šฐ๋ฆฐ ์ด ํŒŒ์ผ๋“ค์„ ์ฝ์œผ๋ ค๊ณ  ํ•˜๋Š” ๊ฒƒ์ด๊ธฐ์—
๐Ÿ“–fs.readdirSync( ๋””๋ ‰ํ† ๋ฆฌ ์‹ฑํฌ์˜ ์•ฝ์ž ) ์šฐ์„  ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ๋„ฃ์–ด์ฃผ๋Š”๋ฐ

๐Ÿ‘‰ ์ฝ์œผ๋ ค๊ณ  ํ•˜๋Š” ํŒŒ์ผ์ด ํ˜„์žฌ posts ์•ˆ์— ์žˆ์œผ๋‹ˆ๊นŒ

๊ทธ๋ž˜์„œ ์ด๋ ‡๊ฒŒ process.cwd( ), 'posts' ๋ผ๊ณ  ํ•ด์ค€๊ฑฐ์ž„๐Ÿ‘Œ

nextjs-app ํด๋” ๊นŒ์ง€์˜ ๊ฒฝ๋กœ๊ฐ€ process.cwd( ) ์ด๊ณ ,
'posts' ๊นŒ์ง€์˜ ๊ฒฝ๋กœ๊ฐ€ postsDirectory ์ธ ๊ฒƒ๐Ÿ”ฅ

์šฐ๋ฆฐ ํ˜„์žฌ src ํด๋” ์•ˆ์— posts ํด๋”๋ฅผ ๋งŒ๋“ ๊ฑฐ๋‹ˆ๊นŒ src๋ฅผ ํ•˜๋‚˜ ๋” ๋„ฃ์–ด์ค˜์•ผํ•จ
์•„๋‹ˆ๋ฉด posts ๋ถ€๋ถ„์„ src ๋ฐ–์œผ๋กœ ๋นผ์ฃผ๋ฉด ํ•ด๊ฒฐ๋จ๐Ÿ‘

์šฐ์„  ํŒŒ์ผ ์ด๋ฆ„์„ ์ฃผ์„์ฒ˜๋Ÿผ ๋˜‘๊ฐ™์ด pre-rendering.md, ssg-ssr.md๋กœ ๋ฐ”๊ฟ”์ฃผ๊ธฐ

postsDirectory ๊ฒฝ๋กœ์— ์žˆ๋Š” ํŒŒ์ผ์„ ์ฝ๋Š”๋‹ค๋Š”๊ฑฐ์ž„๐Ÿ“–
๊ฒฝ๋กœ์— ์žˆ๋Š” ํŒŒ์ผ์„ ์ฝ์œผ๋ฉด fileNames ๋ถ€ํ„ฐ ์ฝ๊ฒŒ๋จ

readdirSync๋ฅผ ์ด์šฉํ•ด์„œ fileNamesโžกpre-rendering.md, ssg-ssr.md ๋‘˜ ๋‹ค ์ฝ์—ˆ์Œ

๊ทธ ๋‹ด์— fileName.replace ๋ผ๊ณ  ํ•˜๋Š”๋ฐ ์ €๊ฒŒ ''์ด๊ฑธ๋กœ ๋Œ€์ฒดํ•œ๋‹ค๋Š” ๊ฒƒ
๐Ÿ‘‰ ์ฆ‰, id์—” pre-rendering ์ด๋ž‘ ssg-ssr ๊นŒ์ง€๋งŒ ๋“ค์–ด๊ฐ€๊ฒŒ๋จ ( .mdโŒ )

postsDirectory( posts ํด๋” )์—
fileName( pre-rendering ์ด๋ž‘ ssg-ssr ํŒŒ์ผ๋“ค )์„ join( ํ•ฉ์นจ )๐Ÿฑโ€๐Ÿš€

๊ทธ๋ฆฌ๊ณ  ๋ฐ‘์—๊ฐ€ ๊ฐ๊ฐ์˜ ํŒŒ์ผ ์ „์ฒด๋ฅผ ์ฝ๋Š”๊ฑฐ์ž„โœจ

์ด๋ถ€๋ถ„์€ ํŒŒ์ผ ๊ฐ€์ ธ์˜ฌ ๋•Œ string ๋ฐ์ดํ„ฐ๋กœ ๊ฐ€์ ธ์˜ค๋Š”๋ฐ

์—ฌ๊ธธ ๋ณด๋ฉด content๋Š” ๋ญ๊ณ  data์˜ title์€ ๋ญ๊ณ  date๋Š” ๋ญ๊ณ 
์ด๋Ÿฐ์‹์œผ๋กœ ๋ถ„์„ํ•ด์ฃผ๋Š” ๋ถ€๋ถ„์ด ์ € ์ฝ”๋“œ์ž„๐Ÿ’ก

matter : ๋งˆํฌ๋‹ค์šด ํŒŒ์ผ์—์„œ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ(์ œ๋ชฉ, ๋‚ ์งœ ๋“ฑ)๋ฅผ ์ถ”์ถœํ•˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํ•„์š”๐Ÿ˜Ž

๊ฐ€์ ธ์˜จ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฆฌํ„ดํ•ด์ค„๊ฑฐ์ž„๐Ÿ”
allPostsData๊ฐ€ id๋Š” ๋ญ๊ณ , ์—ฌ๊ธฐ์— ์žˆ๋Š” content๋Š” ๋ญ๊ณ 
date๋Š” ๋ญ๊ณ  title์€ ๋ญ”์ง€ ๋‹ค ๋ฆฌํ„ด์„ ํ•ด์ค„ ๊ฒƒ๐Ÿ˜ฏ

๐ŸŽฏdate๋ฅผ ์ด์šฉํ•ด์„œ ์ •๋ ฌํ•˜๋Š” ๋ถ€๋ถ„

๐Ÿ‘ฉโ€๐Ÿ’ป์ด์ œ ์ง์ ‘ ์ž‘์„ฑํ•ด๋ณด์ž

src ํด๋” ์•ˆ์— utils ํด๋” ๋งŒ๋“ค๊ณ  getSortedPostsData.js ํŒŒ์ผ ๋งŒ๋“ค๊ธฐ

โ–ซ src>utils>getSortedPostsData.js

์ด๋ ‡๊ฒŒ ํ•ด์ฃผ๊ณ 

๋จผ์ € ์ด ํŒŒ์ผ๋“ค์˜ ์ด๋ฆ„์„ ๊ฐ€์ ธ์˜ฌ๊ฑฐ์ž„
๊ทธ๋Ÿด๋ ค๋ฉด posts์˜ ๊ฒฝ๋กœ๋ถ€ํ„ฐ ์ ‘๊ทผํ•ด์•ผํ•จโœ”

๊ฒฝ๋กœ ์ ‘๊ทผํ•˜๋ ค๋ฉด path ์‚ฌ์šฉโšก
process.cwd( )โžกnextjs-app ํด๋” ๊นŒ์ง€์˜ ๊ฒฝ๋กœ โž• 'posts'โžกposts ํด๋” ๊นŒ์ง€์˜ ๊ฒฝ๋กœ
๐Ÿ‘‰ ์ด ๋‘๊ฐœ์˜ ๊ฒฝ๋กœ๊ฐ€ ํ•ฉ์ณ( join )์ง„๊ฒŒ postsDirectory๐Ÿ”ฅ

๊ทธ๋‹ด์— postsDirectory ์ด ํด๋”์— ์žˆ๋Š” ํŒŒ์ผ๋“ค์˜ ์ด๋ฆ„ ๊ฐ€์ ธ์˜ค๊ธฐ ์œ„ํ•ด
fs( ํŒŒ์ผ ์‹œ์Šคํ…œ ).readdirSync ํ•œ ๋‹ด์—
postsDirectory ์—ฌ๊ธฐ ๊ฒฝ๋กœ์— ์žˆ๋Š” ํŒŒ์ผ๋“ค์„ ๋‹ค ์ฝ๊ฒ ๋‹ค๋Š” ๊ฒƒโ—

๊ทธ๋Ÿฌ๊ณ  pre-rendering.md๋ž‘ ssg-ssr.md์— ์žˆ๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๊ณ  ์‹ถ์œผ๋ฉด
ํŒŒ์ผ๋“ค์— ์žˆ๋Š” content๋ฅผ ๋จผ์ € ์ฝ์–ด์•ผํ•จโญ•

โœ… ๊ทผ๋ฐ ์ง€๊ธˆ fileName์€ ๋ฐฐ์—ด๋กœ ๋˜์–ด์žˆ์Œโžก[ 'pre-rendering.md', 'ssg-ssr.md']

๐Ÿ—บ fileName( ๋ฐฐ์—ด ). ํ•˜๋‚˜์”ฉ ์ฝ๋Š”๊ฑฐ๋‹ˆ๊นŒ map ๋ฉ”์†Œ๋“œ๋กœ ํ•˜๊ธฐ
๐Ÿ‘‰ ํ•˜๋‚˜์˜ fileName ( 'pre-rendering.md' | 'ssg-ssr.md' ์ž„ )

๐Ÿ”„ ์ฒจ ์ˆœํšŒํ•  ๋• 'pre-rendering.md', ๋‹ด์€ 'ssg-ssr.md'

์šฐ์„  ์—ฌ๊ธฐ์„œ ์ด ํŒŒ์ผ์„ ์ฝ์œผ๋ ค๋ฉด fs.readFileSync๋กœ ํ•˜๋ฉด ๋˜๋Š”๋ฐ
( ์ด ์•ˆ์— ๋‘ ๊ฐœ์˜ ํŒŒ์ผ๊นŒ์ง€์˜ ๊ฒฝ๋กœ๋ฅผ ๋„ฃ์–ด์ค˜์•ผ ์ด ํŒŒ์ผ๋“ค์„ ์ฝ์„ ์ˆ˜ ์žˆ์Œ๐Ÿ™†โ€โ™€๏ธ )

๐Ÿ“posts ํด๋”์˜ ๊ฒฝ๋กœ๊นŒ์ง€๊ฐ€ postsDirectory๋‹ˆ๊นŒ
๐Ÿ‘‰ postsDirectory โž• fileName( 'pre-rendering.md' | 'ssg-ssr.md' ) ํ•ด์ฃผ๋ฉด ๋จ

์˜†์— ์˜ต์…˜์œผ๋กœ ์ธ์ฝ”๋”ฉ ์–ด๋–ป๊ฒŒ ํ• ๊ฑด์ง€โžก'utf8'
์ด๋ถ€๋ถ„์—์„œ ํ•˜๋Š”๊ฒŒ ํŒŒ์ผ์„ ์ฝ์–ด์„œ ์ด ๋ฐ์ดํ„ฐ๋ฅผ ์—ฌ๊ธฐ์„œ ๊ฐ€์ ธ์˜ค๋Š” ๊ฒƒโžกfileContents

์ด์ œ ์—ฌ๊ธฐ์„œ title์€ ๋ญ๊ณ  date๋Š” ๋ญ๊ณ  content๋Š” ๋ญ๊ณ 
์ด๋Ÿฐ์‹์œผ๋กœ ์›ํ•˜๋Š” ๋ฐ์ดํ„ฐ ํ˜•์‹์œผ๋กœ ๋ณ€ํ™˜์‹œ์ผœ์ค˜์•ผํ•จ๐Ÿ”ฎ

๋ณ€ํ™˜ ์‹œ์ผœ์ฃผ๊ธฐ ์œ„ํ•ด ๋ชจ๋“ˆ ํ•˜๋‚˜๋ฅผ ์„ค์น˜ํ•ด์•ผํ•จ
๐Ÿ“ฅ npm install gray-matter

์„ค์น˜ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ matter๋กœ fileContents๋ฅผ ๋ณ€๊ฒฝ์‹œ์ผœ์ค„ ๊ฒƒ

allPostsData๋ฅผ return ํ•˜๋ฉด ์–ด๋–ค ํ˜•์‹์ด ๋ ๊นŒโ“
์ง€๊ธˆ ์—ฌ๊ธฐ ๋ฐ์ดํ„ฐ 2๊ฐœโžก[ ๋ฐฐ์—ด ์•ˆ์— { ๊ฐ์ฒด 1 }, { ๊ฐ์ฒด 2 } ]

๊ทธ๋Ÿผ ๊ฐ๊ฐ์˜ ๊ฐ์ฒด ์•ˆ์— ์œ ๋‹ˆํฌํ•œ id๊ฐ€ ์žˆ์–ด์•ผํ•จ
#๏ธโƒฃ { id: 'pre-rendering' }, { id: 'ssg-ssr' } ์ด๋ ‡๊ฒŒ ํ•ด์ฃผ๊ณ  ์‹ถ์€๊ฑฐ์ž„

const id = fileName( 'pre-rendering.md' | 'ssg-ssr.md' ์ธ๋ฐ .md ์‚ญ์ œํ• ๊ฑฐ์ž„โŒ )
๐Ÿ‘‰ ๋Œ€์ฒดํ•ด์ฃผ๋Š” replace ์ด์šฉํ•ด์„œ .md ์—†์•จ ๊ฒƒ๐Ÿ‘‹

postsDirectory๋Š” posts ํด๋” ๊ฒฝ๋กœ๊นŒ์ง€ ์™€์„œ
fileName์€ ํŒŒ์ผ( pre-rendering, ssg-ssr )๊นŒ์ง€์˜ ๊ฒฝ๋กœ๋ฅผ fullPath์— ๋„ฃ์–ด์ค€ ๋‹ด์—

readFileSync๋กœ fullPath ํŒŒ์ผ์„ ์ฝ์œผ๋ ค๊ณ  ํ•˜๋Š” ๊ฒƒ๐Ÿ—ฃ๐Ÿ“–

fileContents๋Š” string์œผ๋กœ ๋‹ค ๋˜์–ด์žˆ์—ˆ๋Š”๋ฐ

title์€ ๋ญ๊ณ  date๋Š” ๋ญ๊ณ  content๋Š” ๋ญ์ธ์ง€ ๋ถ„์„ํ•ด์„œ ํ˜•์‹์„ ๋ณ€๊ฒฝํ•ด์ฃผ๋Š” ๊ฒƒ๐Ÿ˜Ž

๊ทธ๋ž˜์„œ ์ด๊ฑธ ๋ฆฌํ„ดํ•  ๋•Œ ๊ฐ์ฒด์˜ ํ˜•์‹์œผ๋กœ ๋ฆฌํ„ด์„ ํ•˜๊ณ  ์‹ถ์€๋ฐ
id๋Š” id, matterResult๊ฐ€

์—ฌ๊ธฐ์˜€์œผ๋‹ˆ๊นŒ matterResult.data ์ธ๋ฐ matterResult.data ์ด๋ ‡๊ฒŒ๋งŒ ๋„ฃ์œผ๋ฉด๋ ๊นŒโ“
matterResult์— ์žˆ๋Š” data ์ด๋ถ€๋ถ„๋งŒ ๋„ฃ์–ด์ค„๊ฑฐ๋‹ˆ๊นŒโžก...matterResult.data โ—

๊ทธ๋Ÿฌ๋ฉด allPostsData ์—ฌ๊ธฐ์— ์–ด๋–ป๊ฒŒ ๋˜์–ด์žˆ์„๊นŒโ“

๐Ÿ‘‰ ๋ฐฐ์—ด ์•ˆ์— ๊ฐ์ฒด ๋‘ ๊ฐœ๊ฐ€ ์žˆ์„ํ…๋ฐ id ์žˆ๊ณ , titleํ•˜๊ณ  date๊ฐ€ ์žˆ์„๊ฑฐ์ž„โœ”

์ด๋ ‡๊ฒŒ ๋ฐ”๋กœ ๋ฆฌํ„ดํ•ด์ค˜๋„ ๋ฌด๊ด€๐Ÿ‘Œ

๐Ÿ“ข๊ทธ๋Ÿฌ๋ฉด getSortedPostsData ํ•จ์ˆ˜ ํ˜ธ์ถœํ•˜๋ฉด ์ € ๋ฐฐ์—ด์ด ๋ฆฌํ„ด๋ ๊ฑฐ์ž„๐Ÿ”

๊ทผ๋ฐ ์—ฌ๊ธฐ์„œ ์ข€๋” ๋‚˜์•„๊ฐ€์„œ

์›๋ž˜ ํ›จ์”ฌ ์ด๋Ÿฐ ์• ๋“ค์ด ์ˆ˜๋‘๋ฃฉ ํ• ๊ฑฐ๋ผ date๋ฅผ ์ด์šฉํ•ด์„œ ์ •๋ ฌํ•ด์ฃผ๋Š”๊ฒŒ ์ข‹์„๊ฑฐ์ž„๐Ÿ”ฅ

allPostsData์— sort ๋ฉ”์†Œ๋“œ ์ด์šฉํ•ด์„œ ์ •๋ ฌํ•ด์ฃผ๊ธฐ๐ŸŽŽ
๐Ÿ‘‰ a.date๊ฐ€ ๋” ๊ณผ๊ฑฐ๋ผ๋ฉด b๋ฅผ ์•ž์ชฝ์œผ๋กœ ์ด๋™ ( ์ตœ์‹ ์ˆœ ์ •๋ ฌ )
๐Ÿ‘‰ ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด a๋ฅผ ์•ž์ชฝ์œผ๋กœ ์ด๋™

๊ทธ๋Ÿฌ๋ฉด ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค์—ˆ๊ณ 

index.js๋Š” ์ด๋Ÿฐ์‹์œผ๋กœ ๋˜์–ด์žˆ์Œ

โฌ‡์‹คํ–‰์„ ํ•˜๋ฉด ์ด๋ ‡๊ฒŒ ๋˜์–ด์žˆ์Œโšก

์ด ์•ฑ์ฒ˜๋Ÿผ ์ฒจ์— ์ด๋ ‡๊ฒŒ ๋‚˜์—ดํ•˜๊ณ  ์‹ถ์Œ
๋‚˜์—ดํ•˜๋ ค๋ฉด ์ด ๋ฐ์ดํ„ฐ ๊ฐ€์ ธ์™€์•ผํ•˜๋Š”๋ฐ ๊ฐ€์ ธ์˜ค๋ ค๋ฉด index.js ์—์„œ ์–ด๋–ป๊ฒŒํ•˜๋ฉด ๋ ๊นŒโ“

๋ฆฌ์•กํŠธ ํ–ˆ์„ ๋• ๋ฐ์ดํ„ฐ ๊ฐ€์ ธ์˜ฌ ๋•Œ useEffect ์‚ฌ์šฉํ•ด์„œ ํ–ˆ์—ˆ๋Š”๋ฐ
๐Ÿ‘‰ getStaticProps ์ด์šฉโ—

๐Ÿš€getStaticProps ์ด์šฉํ•ด์„œ ๋ฐ์ดํ„ฐ ๊ฐ€์ ธ์˜ค๊ธฐ

โ–ซ src>pages>index.js

โŒจ์ปดํฌ๋„ŒํŠธ ๋ฐ‘์—๋‹ค getStaticProps ์ž‘์„ฑํ•˜๊ธฐ

๐ŸŽฏ์ด ํ•จ์ˆ˜๋Š” ์„œ๋ฒ„์—์„œ ์‹คํ–‰๋˜๋ฉฐ, ๋นŒ๋“œ ์‹œ์ ์— ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์™€ ์ •์  ํŽ˜์ด์ง€๋ฅผ ์ƒ์„ฑํ•จ

allPostsData ( ๋ฐฐ์—ด ๋ฐ์ดํ„ฐ )

props.allPostsData๋‹ˆ๊นŒโžก{ allPostsData } ์ด๋ ‡๊ฒŒ ๊ฐ€์ ธ์˜ค๋ฉด ๋จโญ•

์ฝ˜์†” ๊ฒฐ๊ณผ๋Š” ์š”๋ ‡๊ฒŒ ์›ํ•˜๋Š” ๋ฐ์ดํ„ฐ๊ฐ€ ์ž˜ ๋‚˜์˜ค๋Š” ๊ฑธ ๋ณผ ์ˆ˜ ์žˆ์Œ๐Ÿ™†โ€โ™€๏ธ

๊ทธ๋Ÿผ ์ด์ œ allPostsData๋กœ UI์— ์ž˜ ๋‚˜์˜ค๊ฒŒ ํ•ด์ค„๊ฑฐ์ž„๐Ÿ’ป

โฌ‡์ด๋ ‡๊ฒŒ ํ•ด์ฃผ๋‹ˆ๊นŒ ์ด๋Ÿฐ์‹์œผ๋กœ ํ™”๋ฉด์— ์ž˜ ๋‚˜์˜ค๋Š” ๊ฑธ ๋ณผ ์ˆ˜ ์žˆ์Œ๐Ÿ‘€

๊ทธ๋ฆฌ๊ณ  ์ด๋ถ€๋ถ„์„ ํด๋ฆญํ•˜๋ฉด ์ƒ์„ธํŽ˜์ด์ง€๋กœ ์ด๋™ํ•˜๊ฒŒ ๋จ๐ŸŒซ๐Ÿฑโ€๐Ÿ

๋ฆฌ์•กํŠธ ์‚ฌ์šฉํ–ˆ์„ ๋•Œ ํŽ˜์ด์ง€ ์ด๋™ํ•  ๋•Œ ์–ด๋–ค๊ฑฐ ์ด์šฉํ–ˆ์—ˆ์ง€โ“
๐Ÿ‘‰ React-Router-Dom ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ด์šฉํ•ด์„œ ๋งŒ๋“ค์—ˆ์Œโœ”

Next.js ์—์„  ๋‹ค๋ฅธ ๊ฑธ ์‚ฌ์šฉํ•จ
๐Ÿ‘‰ File System Routing ์‚ฌ์šฉํ•  ๊ฒƒ ( ํ”„๋ ˆ์ž„์›Œํฌ๋‹ˆ๊นŒ ์ด๋ฏธ ๋งŽ์€ ๊ฑธ ๊ฐ–๊ณ  ์žˆ์Œ )

๐Ÿ˜ฏFile System Routing ํ™œ์šฉํ•œ ์ž๋™ ํŽ˜์ด์ง€ ์ด๋™ ์„ค์ •

๐Ÿฑโ€๐Ÿš€localhost:3000/posts/:id ๋‹ค์ด๋‚˜๋ฏนํ•˜๊ฒŒ ํ•ด์ค˜์•ผํ•จ

posts ํด๋” ๋งŒ๋“ค๊ณ  :id ๋‹ค์ด๋‚˜๋ฏน ํ•˜๊ฒŒ ์™€์•ผํ•˜๋ฏ€๋กœ [id].js ํŒŒ์ผ ๋งŒ๋“ค๋ฉด ๋จ
๐Ÿ‘‰ localhost:3000/posts/pre-rendering | ssg-ssr ์–ด๋– ํ•œ ์• ๊ฐ€ ์˜ค๋“  ์ฒ˜๋ฆฌ๋Š” ์—ฌ๊ธฐ์„œ๐Ÿ˜Ž

์ด๋Ÿฐ๊ฑธ file system routing ์ด๋ผ๊ณ  ํ•˜๋Š” ๊ฒƒ๐Ÿ”ฅ

โ–ซ src>pages>posts>[id].js

rafce๋กœ ํ•จ์ˆ˜ํ˜• ์ปดํฌ๋„ŒํŠธ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•ด์ฃผ๊ณ  PostsDetailPage ๋ผ๊ณ  ์ด๋ฆ„ ๋ฐ”๊ฟ”์ฃผ๊ธฐ

โ–ซ src>pages>index.js

๐Ÿ”—href={ ์—ฌ๊ธฐ์— ์ด๋™ํ•˜๊ณ ์ž ํ•˜๋Š” ๊ฒฝ๋กœ๋ฅผ ๋„ฃ์–ด์ฃผ๋ฉด ๋จ }

โฌ‡

์ž˜ ๋‚˜์˜ค๋Š” ๊ฑธ ๋ณผ ์ˆ˜ ์žˆ์Œ๐Ÿ‘€
๊ทธ๋Ÿผ ์ด์ œ ํ™”๋ฉด์— ์ž˜ ๋‚˜์˜ค๊ฒŒ ํ•ด์ค˜์•ผํ•จ

โ–ซ src>pages>posts>[id].js

build time( npm run build )ํ–ˆ์„ ๋•Œ ์–ด๋– ํ•œ id์— ํฌ์ŠคํŠธ๋“ค์ด ์žˆ๋Š”์ง€ ์•Œ ์ˆ˜ ์—†์Œ๐Ÿค”โ“
๐Ÿ‘‡

๐ŸŽฏgetStaticPaths : ๋นŒ๋“œ ์‹œ์ ์— ๋™์ ์œผ๋กœ ์ƒ์„ฑํ•  ํŽ˜์ด์ง€์˜ id ๋ชฉ๋ก์„ ๋ฐ˜ํ™˜ํ•˜๊ณ ,
๐ŸŽฏgetStaticProps : ํ•ด๋‹น id์— ๋งž๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์™€
์ปดํฌ๋„ŒํŠธ์˜ props๋กœ ์ „๋‹ฌํ•˜์—ฌ ํŽ˜์ด์ง€๋ฅผ ๋ฏธ๋ฆฌ ์ƒ์„ฑํ•˜๋Š” ๋ฐฉ์‹โœจ

์ƒ์„ธํŽ˜์ด์ง€ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด ํฌ์ŠคํŠธ๊ฐ€ ์—ฌ๋Ÿฌ๊ฐœ๋‹ˆ๊นŒ ๋™์ ๋ผ์šฐํŒ…์„ ํ•ด์•ผํ•จ
์–ด๋– ํ•œ ํฌ์ŠคํŠธ๋“ค์ด ์žˆ๋Š”์ง€ ๊ทธ ๊ฒฝ๋กœ๋ฅผ ๋‹ค ๊ฐ€์ ธ์˜ค๊ธฐ ์œ„ํ•ด getStaticPaths ์ด์šฉโญ•

๐Ÿ†”์—ฌ๊ธฐ์„œ ํ•ด์ค˜์•ผํ•˜๋Š”๊ฑด ๋ชจ๋“  ํฌ์ŠคํŠธ์˜ id๋“ค์„ ๊ฐ€์ ธ์™€์•ผํ•จโœ”

โœ…fallback์— true & false ๋„ฃ์–ด์ค„ ์ˆ˜ ์žˆ์Œ
falseโžก์—ฌ๊ธฐ์— ํฌ์ŠคํŠธ๊ฐ€ 1, 2, 3, 4๊ฐ€ ์žˆ๋‹ค๊ณ  ํ–ˆ์„ ๋•Œ
getStaticProps ์—์„œ ๊ฐ๊ฐ์˜ ํฌ์ŠคํŠธ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ฌ๊ฑด๋ฐ
๊ฐ‘์ž๊ธฐ ์œ ์ €๊ฐ€ 5( pre-render ๋œ html ์—†๋Š” )๋กœ ์ ‘๊ทผํ–ˆ์„ ๊ฒฝ์šฐ 404 ํŽ˜์ด์ง€๊ฐ€ ๋œจ๊ฒŒํ•จ๐Ÿšจ

trueโžกfallback ํŽ˜์ด์ง€๋ฅผ ๋งŒ๋“ค์–ด์„œ ๊ทธ๋ถ€๋ถ„์„ ๋ณด์—ฌ์ค„ ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋ฉด ๋จ

โ–ซ src>utils>posts.js
๐Ÿ‘‰ getSortedPostsData ์—์„œ posts.js๋กœ ํŒŒ์ผ ๋ฆฌ๋„ค์ž„ํ•จโœ”

getAllPostsIds( ) ๋งŒ๋“ค์–ด์„œ ์ด ํ•จ์ˆ˜์— ์–ด๋–ค ๋กœ์ง์„ ์ž‘์„ฑํ• ๊นŒโ“
์ง€๊ธˆ posts๊ฐ€ ๋‘ ๊ฐœ ์žˆ๋Š”๋ฐ id( pre-rendering & ssg-ssr )๋ฅผ
๊ฐ€์ ธ์˜ค๋Š” ๋กœ์ง์„ ์—ฌ๊ธฐ์„œ ์ž‘์„ฑํ•˜๋ฉด ๋จโ—

fileNames์— ๋ฐฐ์—ด๋กœ ๋‘ ๊ฐœ์˜ ํŒŒ์ผ ์ด๋ฆ„์ด ๋“ค์–ด๊ฐ€์žˆ์Œโœ”

๊ทธ๋‹ค์Œ ๋ฆฌํ„ดํ•  ๋•Œ fileNames.map ๋ฉ”์†Œ๋“œ ์ด์šฉํ•ด์„œ ํ•˜๋‚˜์˜ fileName ํ•˜๊ณ 

์–ด๋–ค ํ˜•์‹์œผ๋กœ ๋ฆฌํ„ด ํ•ด์ค„๊ฑฐ๋ƒ๋ฉด [id].js paths: ์•ˆ์— ๋“ค์–ด๊ฐˆ ๊ฑฐ

์ด ํ˜•์‹์œผ๋กœ ํ•ด์ฃผ๋ ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผํ• ๊นŒโ“

โœ… id: 'pre-rendering', id: 'ssg-ssr' ์ด๋ ‡๊ฒŒ ๋“ค์–ด๊ฐ€์•ผํ•จ

๐Ÿ” { } ์ค‘๊ด„ํ˜ธ ํ•ด์คฌ์œผ๋‹ˆ๊นŒ return์„ ํ•ด์ค˜์•ผํ•จ
id๋ฅผ fileName ์—์„œ .md ์‚ญ์ œํ•˜๋‹ˆ๊นŒโžกpre-rendering & ssg-ssr

โ–ซ src>pages>posts>[id].js

getAllPostsIds( ) ํ•จ์ˆ˜ ๊ฐ€์ ธ์™€์„œ paths ์ƒ์ˆ˜ ์ด๋ฆ„ ๋ฆฌํ„ด์•ˆ์— ์จ์ฃผ๊ธฐ
paths: paths ์ด๋ฆ„ ๊ฐ™์œผ๋‹ˆ๊นŒ paths๋งŒ ์จ์ฃผ๊ธฐ๐Ÿ‘Œ

๐Ÿคทโ€โ™€๏ธ ๊ทธ๋Ÿฌ๋ฉด ์—ฌ๊ธฐ paths ๋ฆฌํ„ดํ•œ๊ฑฐ ์–ด๋””๋กœ ๊ฐˆ๊นŒ โ“
๐Ÿ‘‰ getStaticProps๋กœ โ—

paths ์•ˆ์— params๊ฐ€ ์žˆ์œผ๋‹ˆ๊นŒ

params ๊ฐ€์ ธ์˜ดโ—

params ์•ˆ์— id๊ฐ€ ์žˆ์œผ๋‹ˆ๊นŒโžกparams.id
๐Ÿ‘‰ posts/ssg-ssr ๊ฒฝ๋กœ๋กœ ์™”์œผ๋ฉด params.id๋Š” ssg-ssr ์ด๊ฒŒ ๋˜๋Š”๊ฑฐ๊ณ ,
๐Ÿ‘‰ posts/rendering ์œผ๋กœ ์™”์œผ๋ฉด pre-rendering์ด ๋˜๋Š” ๊ฒƒ

โœ… ์ด๊ฑธ ์ด์šฉํ•ด์„œ ํŒŒ์ผ์˜ ์ƒ์„ธ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ฌ๊ฑด๋ฐ ์˜ฌ๋ฐ”๋ฅธ ํ˜•์‹์œผ๋กœ ๊ฐ€์ ธ์™€์•ผํ•จ

์ € ๋ฐ์ดํ„ฐ ๊ฐ€์ ธ์˜ค๋Š” ๊ฑธ ์—ฌ๊ธฐ์„œ ์ž‘์„ฑํ•ด์ฃผ๋ฉด ๋จ๐Ÿ™†โ€โ™€๏ธ
๐Ÿ” ์˜ฌ๋ฐ”๋ฅธ ๋ฐ์ดํ„ฐ ๊ฐ€์ ธ์˜จ ๋‹ด์— ์–ด๋–ป๊ฒŒ ๋ฆฌํ„ดํ• ๊นŒ โ“

โšก์—ฌ๊ธฐ์„œ ๋ฆฌํ„ดํ•˜๋Š”๊ฑด ์ด props๋กœ ๊ฐ€๋Š”๊ฑฐ๋‹ˆ๊นŒ

props ํ•˜๊ณ  ๋ฆฌํ„ดํ•œ ๊ฐ’์„ ssg-ssr ํ•˜๋‚˜์˜ ํฌ์ŠคํŠธ์— ๋Œ€ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ์—ฌ๊ธฐ๋‹ค ๋„ฃ์–ด์ฃผ๋ฉด ( ์ €์ชฝ์œผ๋กœ ๊ฐˆ๊ฑฐ์ž„โœ” )

๋ฐ์ดํ„ฐ ๊ฐ€์ ธ์˜ค๋Š” ๋กœ์ง์„ ์—ฌ๊ธฐ๋‹ค ์ž‘์„ฑํ•ด๋ณด์žโ—

โ–ซ src>utils>posts.js

์ด๊ฒƒ๋„ posts.js ์—์„œ ๋งŒ๋“  ๋‹ด์— ๊ฐ€์ ธ์˜ฌ๊ฑฐ์ž„

์—ฌ๊ธฐ์„  ๋น„๋™๊ธฐ๋ฅผ ํ•ด์ค˜์•ผํ•˜๋Š” ๋ถ€๋ถ„์ด ์žˆ์–ด์„œ async๋กœ ๊ฐ์‹ธ์ค„ ๊ฒƒ๐Ÿ
์ด ํ•จ์ˆ˜์˜ ๋ชฉํ‘œ๋Š” ํŒŒ์ผ์˜ ๋ฐ์ดํ„ฐ ์ „์ฒด๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๊ฒƒ๐Ÿค“

getSortedPostsData๋ž‘ ๋น„์Šทํ• ๊ฑด๋ฐ

์—ฌ๊ธฐ์„œ ํ–ˆ๋˜ ๊ฑด ์ด๋ถ€๋ถ„๋งŒ ๊ฐ€์ ธ์™”์—ˆ์Œโญ•

๐Ÿ‘‰ ์™œ๋ƒ, ์ฒจ์— ํ™”๋ฉด ๋ณด์—ฌ์ค„๋•Œ title ํ•˜๊ณ  date๋งŒ ๋ณด์—ฌ์ค˜์•ผํ•˜๊ธฐ ๋•Œ๋ฌธ

โœ… title ํด๋ฆญํ•˜๊ณ  ๋“ค์–ด๊ฐ€๋Š” ํŽ˜์ด์ง€์—์„  ํŒŒ์ผ์˜ ์ „์ฒด ๋ฐ์ดํ„ฐ๊ฐ€ ํ•„์š”ํ•จ

[id].js ์—ฌ๊ธฐ์„œ getPostData ํ•จ์ˆ˜ ํ˜ธ์ถœํ• ๊ฑด๋ฐ๐Ÿ“ข( ์ด๋•Œ params.id๋ฅผ ๋„ฃ์–ด์ค„๊ฑฐ์ž„โœ” )
๐Ÿ†”โžกpre-rendering ์ธ์ง€ ์•„๋‹˜ ssg-ssr ์ธ์ง€๋ฅผ ๋„ฃ์–ด์ค„ ๊ฒƒ

id ๋ฐ›์•„์˜ค์žโ—
๊ทธ๋‹ด์— ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ํŒŒ์ผ์˜ ์ด๋ฆ„์ด ๋˜๋Š”๊ฑฐ์ž„
( ํŒŒ์ผ์˜ ์ด๋ฆ„์„ ์•Œ์•„์•ผ ํ•ด๋‹น ํŒŒ์ผ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ์„ ์ˆ˜๊ฐ€ ์žˆ์Œ๐Ÿ˜Ž )

๐Ÿ—ฃ์ฝ์„ ๋•โ“โžกfs( ํŒŒ์ผ ์‹œ์Šคํ…œ ).readFileSync( )๋กœ ์ฝ์–ด์ค„ ๊ฒƒ๐Ÿ“–
( ๐Ÿ”—์ „์ฒด path๋ฅผ ๋„ฃ์–ด์ค˜์•ผํ•˜๋ฏ€๋กœโžกpostsDirectory( posts ํด๋”๊นŒ์ง€์˜ ๊ฒฝ๋กœ )โž•id.md๐Ÿ”ฅ )

fullPath ๋„ฃ์–ด์ฃผ๊ณ  ์˜ต์…˜์—๋‹ค๊ฐ€ encoding ์˜ต์…˜ 'utf-8' ๋„ฃ์–ด์คŒ
๋„ฃ์–ด์ฃผ๋ฉด ํŒŒ์ผ์˜ ์ปจํ…์ธ ๋ฅผ ๋ฆฌํ„ด์„ ํ•˜๋Š”๋ฐ ์ด๋ฆ„์„ fileContents๋กœ ํ•ด์ค„๊ฑฐ์ž„๐Ÿ‘Œ

๋จผ์ € ํŒŒ์ผ์„ ์ด๋ ‡๊ฒŒ ๋ณ€๊ฒฝํ•˜๊ณ 

๋‚˜์ค‘์— ์ด๋ ‡๊ฒŒ ๋ณ€๊ฒฝํ•ด์ค„๊ฑฐ์ž„๐Ÿ”ฎ

โ˜์ฒ˜๋Ÿผ ๋ณ€๊ฒฝํ•ด์ฃผ๊ธฐ ์œ„ํ•ด matter ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ด์šฉํ•ด์„œ fileContents ๋„ฃ์–ด์ฃผ๊ธฐ
๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ๋ถ„์„( parse )ํ•ด์„œ ์ €๋Ÿฐ์‹์œผ๋กœ ๋งŒ๋“œ๋Š”๊ฑฐ์ž„

โœŒ์ฒ˜๋Ÿผ html string ์œผ๋กœ ๋งŒ๋“ค์–ด์ฃผ๋Š” ๋ถ€๋ถ„์„ ์œ„ํ•œ ์ฝ”๋“œ ๋งŒ๋“ค์žโ—

๐Ÿ“šMarkdown ํŒŒ์‹ฑํ•˜๊ณ  ๋ณ€ํ™˜ํ•˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

๐Ÿ“ฅ์ด๋ถ€๋ถ„์„ ์œ„ํ•ด npm install remark ๋ช…๋ น์–ด๋กœ ์„ค์น˜ํ•ด์ฃผ์ž

๐Ÿ“šMarkdown์„ HTML๋กœ ๋ฐ”๊ฟ”์ฃผ๋Š” ํ”Œ๋Ÿฌ๊ทธ์ธ ( ๐Ÿ“ฅํ•˜๋‚˜ ๋” ์„ค์น˜ํ•˜๊ธฐ )

๐Ÿ”นremark : remark ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ์ดˆ๊ธฐํ™” ํ•จ์ˆ˜๋กœ, ๋งˆํฌ๋‹ค์šด์„ ์ฒ˜๋ฆฌํ•  ์ค€๋น„๋ฅผ ํ•จ
๐Ÿ”น.use( html ) : remark๊ฐ€ HTML๋กœ ๋ณ€ํ™˜ํ•˜๋„๋ก ์„ค์ •ํ•˜๋Š” ๋ถ€๋ถ„
๐Ÿ”น.process( matterResult.content ) : matterResult.content์— ์ €์žฅ๋œ
๋งˆํฌ๋‹ค์šด ํ…์ŠคํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•˜์—ฌ HTML๋กœ ๋ณ€ํ™˜
๐Ÿ”นprocessedContent.toString : ๋ณ€ํ™˜๋œ HTML์„ ๋ฌธ์ž์—ด๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๋ถ€๋ถ„

contentHtml ์ € ๋ถ€๋ถ„์ด ์ด๋ถ€๋ถ„์— ํ•ด๋‹นโœ”

๐Ÿ“ขgetPostData ์ด ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ–ˆ์„ ๋•Œ ๊ฐ์ฒด ํ˜•์‹์œผ๋กœ ๋ฆฌํ„ด์„ ํ•ด์ค„๊ฑฐ์ž„๐Ÿ”

๐Ÿ†”๋Š” ์ด id ๋ผ๊ณ  ํ•ด์ฃผ๊ณ , ์ด html string ๋ถ€๋ถ„๋„ contentHtml ์ด๋ ‡๊ฒŒ ํ•ด์ฃผ๊ณ 

์—ฌ๊ธฐ์— ๋“ค์–ด์žˆ๋Š”๊ฒŒ

์ด๋ถ€๋ถ„๋„ ์žˆ๊ณ  ์—ฌ๊ธฐ๋„ ์žˆ์ง€๋งŒ content ๋ถ€๋ถ„์€ ๊ฐ€๊ณตํ•˜์ง€ ์•Š๊ณ ์„œ ๋ณด๋‚ด์ค€ ๋ถ€๋ถ„์ž„โญ•
'๋งˆํฌ๋‹ค์šด'์„ ๋ฐ”๋กœ html๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์ŒโŒ
br ํƒœ๊ทธ๋ฉฐ pํƒœ๊ทธ๋ฉฐ ์žˆ์„ํ…๋ฐ ์ด๊ฑธ html๋กœ string ์œผ๋กœ ๊ฐ€๊ณตํ•ด์ฃผ๋Š” ๋ถ€๋ถ„์ด

๋ฐ”๋กœ ์ด๋ถ€๋ถ„โ—

ํŒŒ์ผ์˜ title / date / content ์ด ์ „์ฒด์ ์ธ ๋ถ€๋ถ„ ๋‹ค ๋‚ด๋ ค์ฃผ๊ธฐ ์œ„ํ•ด์„ 
์œ„์ชฝ์—์„œ ํ–ˆ๋˜ ๊ฒƒ์ฒ˜๋Ÿผ ...matterResult.data ํ•ด์ฃผ๋ฉด ๋จ๐Ÿค“

โ–ซ src>pages>posts>[id].js

await const postData ํ•˜๊ณ  postData๋ฅผ ๋‚ด๋ ค์ฃผ๊ธฐ
postData ์–ด๋””์„œ ๊ฐ€์ ธ์˜ค์ง€โ“

๐Ÿ‘‰ { postData } ์—ฌ๊ธฐ์„œ ๊ฐ€์ ธ์˜ดโ—
์ฝ˜์†”๋กœ ์ฐ์–ด๋ณด๋ฉด

โฌ‡์ด๋Ÿฐ์‹์œผ๋กœ ๋ฐ์ดํ„ฐ ์ž˜ ๊ฐ€์ ธ์˜จ๊ฑธ ๋ณผ ์ˆ˜ ์žˆ์Œ๐Ÿ‘€

โœ… ์ด์ œ ํ™”๋ฉด์— ๋ฐ์ดํ„ฐ๋“ค์ด ์ž˜ ๋‚˜์˜ค๊ฒŒ ํ•ด์ฃผ๋ฉด ๋จ

๐Ÿš€์ƒ์„ธํŽ˜์ด์ง€์—์„œ ๋ฐ์ดํ„ฐ ์ž˜ ๋‚˜์˜ค๊ฒŒ ํ•˜๊ธฐ

title ์ œ๋ชฉ ๋ฐ”๊ฟ”์ฃผ๊ธฐ

article ์ด๋ผ๋Š” ์‹œ๋ฉ˜ํ‹ฑ ํƒœ๊ทธ ์‚ฌ์šฉํ•ด์„œ title, date ํ•ด์ฃผ๊ธฐ

๊ทธ ๋‹ด์— ์—ฌ๊ธฐ ๋ถ€๋ถ„ ๋ณด์—ฌ์ค˜์•ผํ•จ

๐ŸšจdangerouslySetInnerHTML : ๋ฆฌ์•กํŠธ์—์„œ HTML์„ ์ง์ ‘ ์‚ฝ์ž…ํ•  ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ์†์„ฑโ—

โฌ‡๊ทธ๋Ÿผ ์ด๋ ‡๊ฒŒ ์ž˜ ๋‚˜์˜ค๋Š” ๊ฑธ ๋ณผ ์ˆ˜ ์žˆ์Œ๐Ÿ‘€

์—ฌ๊ธฐ๋กœ ๊ฐ€์„œ title์„ ํด๋ฆญํ•ด๋„

ํ•ด๋‹น ํŒŒ์ผ ์ƒ์„ธํŽ˜์ด์ง€๊ฐ€ ์ž˜ ๋‚˜์˜ค๋Š” ๊ฑธ ๋ณผ ์ˆ˜ ์žˆ์Œ๐Ÿฅณ

๐Ÿคฉํ•ต์‹ฌ

โ˜ Next.js์— pages ๋ผ์šฐํ„ฐ๋ฅผ ์ด์šฉํ•  ๋•Œ ํŒŒ์ผ ์‹œ์Šคํ…œ ๋ผ์šฐํŒ… ์ด์šฉํ•ด์„œ ํŽ˜์ด์ง• ์ฒ˜๋ฆฌํ•œ๋‹ค๋Š” ๊ฒƒ
๐Ÿ‘‰ ์–ด๋–ป๊ฒŒ ํด๋” ๊ตฌ์กฐ๋ฅผ ๊ฐ€์ ธ๊ฐ€๋Š”์ง€ ( ํด๋”๋ž‘ ํŒŒ์ผ ์ด๋ฆ„ )

โœŒ ๋ฐ์ดํ„ฐ ํŒจ์นญ ์–ด๋–ค์‹์œผ๋กœ ํ•˜๋Š”์ง€ ( getStaticProps, getStaticPaths, ... )

profile
์•ˆ๋…•ํ•˜์„ธ์š”! ํผ๋ธ”๋ฆฌ์‹ฑ & ํ”„๋ก ํŠธ์—”๋“œ ๊ฐœ๋ฐœ ๊ณต๋ถ€ ๋ธ”๋กœ๊ทธ ์ž…๋‹ˆ๋‹ค!

0๊ฐœ์˜ ๋Œ“๊ธ€