Frontend ๐Ÿ“š/React

[React] ํ•˜์ด๋“œ๋ ˆ์ด์…˜(Hydration), Next etc.

leejaejae 2024. 7. 12. 16:38

1. ํ•˜์ด๋“œ๋ ˆ์ด์…˜
2. Next.JS


1. ํ•˜์ด๋“œ๋ ˆ์ด์…˜(Hydration) โญ๏ธ

  • ํ•˜์ด๋“œ๋ ˆ์ด์…˜
    • ๋ฆฌ์•กํŠธ์—์„œ ์„œ๋ฒ„์‚ฌ์ด๋“œ ๋ Œ๋”๋ง ํ˜น์€ SSG(์Šคํƒœํ‹ฑ ์‚ฌ์ดํŠธ ์ œ๋„ค๋ ˆ์ด์…˜)์„ ์‹คํ–‰ํ•œ HTML ๊ฒฐ๊ณผ๋ฌผ์„ ๋ฐ›์•„์˜จ ๋’ค, ๋ธŒ๋ผ์šฐ์ €์—์„œ ์ด๊ฒƒ์„ ๋‹ค์‹œ ๋ฆฌ์•กํŠธ ํŠธ๋ฆฌ์— ๋งž๊ฒŒ ํŒŒ์‹ฑํ•˜๋Š” ํ–‰์œ„

  • ๋ฆฌ์•กํŠธ๋Š” DOM์— ๋ฆฌ์•กํŠธ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ Œ๋”๋งํ•ด์ฃผ๋Š” render ๋ฉ”์†Œ๋“œ๋ฅผ ์ œ๊ณตํ•จ ↓
/* ์ปจํ…Œ์ด๋„ˆ DOM์— ๋ฆฌ์•กํŠธ ์—˜๋ฆฌ๋จผํŠธ๋ฅผ ๋ Œ๋”๋งํ•˜๋Š” ํ•จ์ˆ˜ */
ReactDOM.render(element, container[, callback])
  • ์ด renderํ•จ์ˆ˜๋Š” ์ปดํ…Œ์ด๋„ˆ์˜ ์ž์‹์œผ๋กœ ๋ฆฌ์•กํŠธ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋„ฃ์–ด์ฃผ๋Š”๋ฐ, ๊ธฐ์กด์— ์ด๋ฏธ ๋ Œ๋”๋ง ๋œ ๋ฆฌ์•กํŠธ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์žˆ๋‹ค๋ฉด ์ƒˆ๋กœ ๋ Œ๋”๋ง ํ•˜๋Š”๊ฒŒ ์•„๋‹ˆ๋ผ ์—…๋ฐ์ดํŠธ๋งŒ ํ•ด์คŒ.
    ๊ทธ๋ฆฌ๊ณ  ๋ Œ๋”๋ง์ด ์™„๋ฃŒ๋„๋ฉด ์„ธ๋ฒˆ์งธ ์ธ์ž๋กœ ์ „๋‹ฌ๋œ ์ฝœ๋ฐฑ์ด ์‹คํ–‰๋˜๊ฒŒ ํ•  ์ˆ˜ ์žˆ์Œ.
  • ์ฆ‰, ReactDomdml render๋ฉ”์†Œ๋“œ๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ Œ๋”๋งํ•œ ํ›„์— ์ฝœ๋ฐฑ์„ ์‹คํ–‰ํ•จ

  • ๋ฐ˜๋ฉด, ReactDOM์—๋Š” hydrate๋ผ๋Š” ๋ฉ”์†Œ๋“œ๋„ ์กด์žฌํ•จ ↓
ReactDOM.hydrate(element, container[, callback])
  • ๋ฉ”์†Œ๋“œ ๋ชจ์–‘์ด render์™€ ๋˜‘๊ฐ™์€๋ฐ, hydrate๋Š” ๋ Œ๋”๋ง ํ•˜์ง€ ์•Š๊ณ  ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋งŒ ๋ถ™์—ฌ์คŒ.

  • SSR(Server Side Rendering)์„ ํ•ด์„œ ์ด๋ฏธ ๋งˆํฌ์—…์ด ์ฑ„์›Œ์ ธ์žˆ๋Š” ๊ฒฝ์šฐ์—๋Š” ๊ตณ์ด render๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•  ํ•„์š”์—†์ง€๋งŒ,
    hydrate๋กœ ์ฝœ๋ฐฑ์„ ๋ถ™์—ฌ์•ผ ํ•จ

    CSR(Client Side Rendering)์„ ํ•˜๋Š” ๊ฒฝ์šฐ์—๋Š” ํƒ€๊ฒŸ ์ปจํ…Œ์ด๋„ˆ์— ๋ฆฌ์•กํŠธ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ Œ๋”๋ง ๋œ ์ ์ด ์—†์„ ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— render๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉ, ํ•˜์ง€๋งŒ SSR ํ”„๋ ˆ์ž„์›Œํฌ์™€ ํ•จ๊ป˜ ๋ฆฌ์•กํŠธ๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ๋Š” hydrate ์‚ฌ์šฉ์„ ๊ณ ๋ คํ•ด์•ผ ํ•จ.

2) Hydration ๊ณผ์ • โญ๏ธ

Hydration ๊ณผ์ •

  • ์„œ๋ฒ„๊ฐ€ ์™„์„ฑ๋œ HTML์„ ๋‚ด๋ ค์คŒ. ์ด๋•Œ Dehydrate๋ž€ ๋™์ ์ธ ๊ฒƒ์„ ์ •์ ์œผ๋กœ ๋งŒ๋“œ๋Š” ํ–‰์œ„๋ฅผ ๋งํ•จ.
  • ๊ทธ๋ฆฌ๊ณ  ๋‚˜์„œ JS๊ฐ€ ์‹คํ–‰๋˜๋ฉด์„œ ๋ฆฌ์•กํŠธ๊ฐ€ ์ •์ ์ธ HTML๊ณผ store๋ฅผ ๋™์ ์ธ ๋ฆฌ์•กํŠธ ์ปดํฌ๋„ŒํŠธ ํŠธ๋ฆฌ์™€ store๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๊ณผ์ •์ด ์ผ์–ด๋‚˜๋Š๋ฐ, ์ด๊ฑธ (Re)hydrate(์ •์ →๋™์ )๋ผ๊ณ  ํ•จ.
  • ๋ฌธ์ œ๋Š”!
    • ์ด๋ ‡๊ฒŒ rehydrate๊ฐ€ ์ผ์–ด๋‚˜๋ฉด ํ™”๋ฉด์ด ํ•œ ๋ฒˆ ๋” ๊ทธ๋ ค์ง€๋Š” ํ˜„์ƒ์ด ๋ฐœ์ƒํ•˜๊ฒŒ ๋˜๋Š”๋ฐ, ๋ฆฌ์•กํŠธ๋Š” ์„œ๋ฒ„์—์„œ ์™„์„ฑ๋œ HTML์ด ๋‚ด๋ ค์™€์„œ ์ด๋ฏธ ํ™”๋ฉด์— ์ œ๋Œ€๋กœ ๋ Œ๋”๋ง์ด ๋ฌ๋Š”์ง€ ์•ˆ๋ฌ๋Š”์ง€ ๋ชจ๋ฅด๊ณ  ์ž๊ธฐ ํ•  ์ผ์„ ํ•˜๊ธฐ ๋•Œ๋ฌธ์ž„
  • ๊ทธ๋ž˜์„œ SSR์„ ํ•˜๋Š” ๊ฒฝ์šฐ์—๋Š” ReactDOM์˜ render๋ฉ”์†Œ๋“œ๊ฐ€ ์•„๋‹ˆ๋ผ hydrate๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š” ๊ฑฐ์ž„~
  • ์„œ๋ฒ„์—์„œ ๋‚ด๋ ค์ค€ HTML๋กœ ๋ Œ๋”๋ง ๋œ ํ™”๋ฉด์€ ๊ทธ๋ƒฅ ๋‹จ์ˆœํžˆ ๊ทธ๋ฆผ์ผ ๋ฟ์ž„;;(๋ฆฌ์•กํŠธ๊ฐ€ ๊ด€๋ฆฌํ•˜์ง€ ์•Š๋Š” ํ™”๋ฉด์ด๋ž€ ๋œป)
    SSR์„ ํ•˜๋”๋ผ๋„ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ฆฌ์•กํŠธ๊ฐ€ ๊ด€๋ฆฌํ•˜๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” hydration์€ ๊ผญ ํ•„์š”ํ•œ ์ž‘์—… !

3) Hydration ์ด์Šˆ โญ๏ธ

  • hydrate ๋‹จ๊ณ„์—์„œ, 
    1. ๋ Œ๋”๋งํ•œ ๊ฒฐ๊ณผ๋ฌผ์ด ์–ด๋–ค ์ปดํฌ๋„ŒํŠธ์ธ์ง€ ํ™•์ธํ•˜๊ณ ,
    2. ๊ฐ ์ปดํฌ๋„ŒํŠธ์— ๊ฑธ๋ฆฐ ์ด๋ฒคํŠธ๋“ค์„ ์‹ค์ œ DOM์— ๊ฑธ์–ด์ฃผ๋Š” ๋™์ž‘์„ ํ•˜๊ฒŒ ๋œ๋‹ค.
  • ํ•˜์ด๋“œ๋ ˆ์ด์…˜์ด ์ž˜๋ชป๋˜์—ˆ์„ ๋•Œ, ๋Œ€๋ถ€๋ถ„ ๋งˆ์ฃผํ•˜๋Š” ๋ฌธ์ œ๋“ค์€ ๊ฑฐ์˜ 1๋ฒˆ ๊ณผ์ •์ด ์ž˜๋ชป๋˜์–ด์„œ ์ผ์–ด๋‚จ.

Q) ์™œ ๋ฐœ์ƒํ•˜๋Š”๊ฐ€!?

  • Next.JS์—์„œ ๋‚ด๋ถ€์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ReactDOM.hydrate ํ•จ์ˆ˜๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ผ์„ ํ•จ
    1. ์„œ๋ฒ„์—์„œ ๋ฐ›์•„์˜จ DOM tree์™€ ์ž์ฒด์ ์œผ๋กœ ๋ Œ๋”๋งํ•œ tree๋ฅผ ๋น„๊ต
    2. ๋‘ tree ์‚ฌ์ด์˜ ์ฐจ์ด(diff, difference)๋ฅผ ์–ป์–ด๋‚ธ ๋’ค, ์ž์ฒด์ ์œผ๋กœ(ํด๋ผ์ด์–ธํŠธ์‚ฌ์ด๋“œ) ๋ Œ๋”๋ง ํ•œ tree์— ๋น„๊ตํ•˜๋ฉด์„œ ์–ด๋–ค DOM์ด ์–ด๋–ป๊ฒŒ ๋งค์นญ๋˜๋Š”์ง€ ์ดํ•ดํ•จ
    3. ์ดํ•ดํ•œ ๋‚ด์šฉ์— ๋”ฐ๋ผ CSR ๋™์ž‘ ์‹คํ–‰
  • ๋ฆฌ์•กํŠธ๋Š” DOM Element ๋‹จ์œ„์—์„œ๋งŒ ๋น„๊ตํ•˜๋ฏ€๋กœ, className์ด๋‚˜ id ๊ฐ™์€ ํ”„๋กœํผํ‹ฐ๊ฐ€ ์—‰๋šฑํ•œ ์—˜๋ฆฌ๋จผํŠธ์— ์ž˜๋ชป ๋ถ™๋Š” ํ˜„์ƒ์ด ๋ฐœ์ƒํ•˜๊ฒŒ ๋˜๋ฉฐ, ์ด๋กœ ์ธํ•ด ์ž˜๋ชป๋œ ์Šคํƒ€์ผ์ด ๋จนํžˆ๋Š” ๊ฒƒ์ด ๊ฐ€์žฅ ์ผ๋ฐ˜์ ์œผ๋กœ ๊ฒช์„ ์ˆ˜ ์žˆ๋Š” ๋ฌธ์ œ์ž„.
  • ์˜ˆ๋ฅผ ๋“ค๋ฉด, ๋ชจ๋ฐ”์ผ์—์„œ๋งŒ sticky Header ๋ฅผ ๋ Œ๋”๋ง ํ•˜๋„๋ก ํ•˜์˜€๋Š”๋ฐ, ๋ฐ์Šคํฌํƒ‘ ํด๋ผ์ด์–ธํŠธ์˜ Contents์— sticky Header์˜ ์Šคํƒ€์ผ์ด ๋จนํ˜€์žˆ๋‹ค๊ฑฐ๋‚˜, ํ•˜๋Š” ์‹

Q) ์–ด๋–ป๊ฒŒ ํ•ด๊ฒฐํ•˜๋Š”๊ฐ€!?

  • ์ •์ƒ์ ์ธ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•
    • ํด๋ผ์ด์–ธํŠธ ์‚ฌ์ด๋“œ์—์„œ๋งŒ, ํ˜น์€ ์„œ๋ฒ„ ์‚ฌ์ด๋“œ์—์„œ๋งŒ ๋ Œ๋”๋ง๋˜๋Š” ๋กœ์ง์„ ์ œ๊ฑฐ(์‰ฝ๊ฒŒ ๋งํ•ด return null์„ ํ•˜์ง€ ์•Š์Œ)

      1. return null ๋Œ€์‹  return <div />
      2. return null ๋Œ€์‹  visibility: hidden; ๋˜๋Š” display: none;

  • ๊ผผ์ˆ˜ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•
    - ์ด ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋น„๋™๊ธฐ๋กœ ๋ฐ›์•„์˜ฌ ํŠน์ • ๋ฐ์ดํ„ฐ๋ฅผ ๊ผญ ํ•„์š”๋กœ ํ•œ๋‹ค๊ฑฐ๋‚˜, return null์ด ์•„๋‹ˆ๋ฉด ๋ ˆ์ด์•„์›ƒ์ด ๊นจ์ง„๋‹ค๊ฑฐ๋‚˜, ์ปดํฌ๋„ŒํŠธ ๋กœ์ง์ด ๋ณต์žกํ•ด ์œ„ ๋ฐฉ๋ฒ•์œผ๋กœ ๊ณ ์น˜๊ธฐ์—” ์‹œ๊ฐ„์ด ์—†๋‹ค๊ฑฐ๋‚˜ ํ•  ๋•Œ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Œ
    • ๋ฆฌ์•กํŠธ๊ฐ€ ๋‘ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์–ด๋–ป๊ฒŒ๋“  ๊ตฌ๋ถ„ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๊ธฐ!

      1. ์„œ๋กœ ๋‹ค๋ฅธ ์—˜๋ฆฌ๋จผํŠธ๋ฅผ ์‚ฌ์šฉ. ํŠนํžˆ ์ด๋ ‡๊ฒŒ ๋ Œ๋”๋ง์ด ๋˜๋‹ค ๋ง๋‹ค ํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ์˜ ๋ฃจํŠธ๋ฅผ div, span, section, p, ๊ฐ™์€ ๋Œ€์ฒด ๊ฐ€๋Šฅํ•œ ์—˜๋ฆฌ๋จผํŠธ๋กœ ๋ณ€๊ฒฝ
      2. ํ˜น์€, ์‚ฌ์ด ์‚ฌ์ด์— <div />๊ฐ€ ์•„๋‹Œ ์š”์†Œ๋ฅผ ์‚ฝ์ž…

 

2. Next 

๋”๋ณด๊ธฐ

CSR : ์ฒซ ๋ Œ๋”์‹œ ๊ทธ๋ƒฅ ํŽ˜์ด์ง€ ๋กœ๋“œ, ๋‹ค์‹œ ๋ Œ๋”๋งํ•จ์œผ๋กœ์จ ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜ด. ๊ทธ๋ž˜์„œ ๋ฐ์ดํ„ฐ๊ฐ€ ๊ฒ€์ƒ‰์—”์ง„์— ์•ˆ ๊ฑธ๋ฆผ. ๊ทธ๋Ÿฌ๋‚˜ ํ•œ ๋ฒˆ์— ๋ฐ์ดํ„ฐ๋ฅผ ์™•์ฐฝ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ ๋•Œ๋ฌธ์— ํŽ˜์ด์ง€ ์ด๋™ํ•  ๋•Œ ๋น ๋ฆ„
SSR : ์ฒซ ๋ Œ๋”์‹œ ๋ฐ์ดํ„ฐ๋„ ์„œ๋ฒ„์ธก์—์„œ ํ•จ๊ป˜ ๋กœ๋“œ. ๋ Œ๋” ํ•œ ๋ฒˆ์ด๋ผ ์ดˆ๊ธฐ ๋กœ๋”ฉ์†๋„ ๋น ๋ฅด๊ณ , ๊ฒ€์ƒ‰์—”์ง„์— ๋ฐ์ดํ„ฐ๋“ค์ด ๊ฑธ๋ฆผ. ๊ทธ๋Ÿฌ๋‚˜ ํŽ˜์ด์ง€ ๋ถˆ๋Ÿฌ์˜ฌ ๋•Œ๋งˆ๋‹ค ์ค‘๋ณต ๋ฐ์ดํ„ฐ ๋ถˆ๋Ÿฌ์™€์•ผ ํ•ด์„œ ํŽ˜์ด์ง€ ์ด๋™์‹œ ๋Š๋ฆผ.

  • CSR์˜ ๊ฒฝ์šฐ, ์ดˆ๊ธฐ์— ํŽ˜์ด์ง€๊ฐ€ ์ผ๋‹จ ๋ Œ๋”๊ฐ€ ๋œ ์ดํ›„, ํด๋ผ์ด์–ธํŠธ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๋ฉฐ ๋‹ค์‹œ ํ•œ ๋ฒˆ ๋ Œ๋”๋ง
  • ํ•œํŽธ, SSR์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒฝ์šฐ, ์ฒ˜์Œ ๋ Œ๋”๊ฐ€ ๋  ๋•Œ ์„œ๋ฒ„ ์ธก์—์„œ ๋ฐ์ดํ„ฐ๋„ ํ•จ๊ป˜ ๊ฐ€์ ธ์™€์„œ ๊ทธ๋ ค์คŒ.

  • ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— SSR์˜ ๊ฒฝ์šฐ, ํ•œ ๋ฒˆ์— ๋ Œ๋”๋ง์ด ๋˜๊ธฐ ๋•Œ๋ฌธ์— ์ดˆ๊ธฐ ๋กœ๋”ฉ์†๋„๊ฐ€ ๋น ๋ฅด์ง€๋งŒ, 
    ํŽ˜์ด์ง€๋ฅผ ๋„˜๊ธธ ๋•Œ๋งˆ๋‹ค ์ค‘๋ณต๋˜๋Š” ๋ฐ์ดํ„ฐ์ผ์ง€๋„ ์„œ๋ฒ„์ธก์—์„œ ๋‹ค์‹œ ๋ถˆ๋Ÿฌ์™€์ค˜์•ผํ•˜๊ธฐ ๋•Œ๋ฌธ์— ํŽ˜์ด์ง€ ๊ณผ๋ถ€ํ•˜๊ฐ€ ๊ฑธ๋ฆด ์œ„ํ—˜์„ฑ์ด CSR์— ๋น„ํ•ด ํผ.

  • ๊ทธ๋Ÿผ์—๋„ SSR์„ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ ๋Š” ํŽ˜์ด์ง€๊ฐ€ ๋กœ๋”ฉ๋  ๋•Œ ๋ฐ์ดํ„ฐ๋„ ๋™์‹œ์— ๋กœ๋“œ๋˜๊ธฐ ๋•Œ๋ฌธ์— ๊ฒ€์ƒ‰์—”์ง„์— ํ•ด๋‹น ๋ฐ์ดํ„ฐ๋“ค์ด ๊ฑธ๋ฆฌ๊ธฐ ๋•Œ๋ฌธ์ž„
  • ๋”ฐ๋ผ์„œ ์ฒซ ๋กœ๋“œ์‹œ ๋นˆ ์ƒํƒœ์ธ CSR๊ณผ ๋‹ฌ๋ฆฌ ๊ฒ€์ƒ‰์—”์ง„ ์ตœ์ ํ™”์— ํšจ๊ณผ์ ์ด๋‹ค~

1) Next์˜ ๋ Œ๋”๋ง ์ˆ˜ํ–‰ ๋ฐฉ์‹  โญ๏ธ

  • Next.js๋Š” SSR์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜์ง€๋งŒ, ํŽ˜์ด์ง€๊ฐ€ ๋กœ๋“œ๋œ ์ดํ›„์—” React์—์„œ CSR์„ ์ด์šฉํ•˜๋Š” ๋ฐฉ์‹์„ ์ฐจ์šฉํ•จ
  1. ํŽ˜์ด์ง€๋Š” ์„œ๋ฒ„๊ฐ€ ๊ทธ๋ฆฌ๊ณ 
  2. pages/์•ˆ์— ํด๋”๋ฅผ ๋งŒ๋“ค๋ฉด, ํ•ด๋‹น ๋ผ์šฐํŒ…์˜ ํŽ˜์ด์ง€๋“ค์€ ์„œ๋ฒ„์ธก์—์„œ ๋จผ์ € ๋กœ๋“œํ•ด์คŒ(SSR ๊ธฐ๋ฐ˜์œผ๋กœ ์„œ๋ฒ„์— ์‚ฌ์ „์— ์ €์žฅ๋œ ๋ Œ๋”ํŠธ๋ฆฌ์˜ HTML ๋กœ๋“œ → ์‚ฌ์ „ ๋ Œ๋”๋ง(pre-render))
  3. ํŽ˜์ด์ง€๊ฐ€ ๊ทธ๋ ค์ง„ ์ดํ›„์— ํŽ˜์ด์ง€ ๋‚ด๋ถ€์—์„œ ๋™์ ์ธ ๋ฐ์ดํ„ฐ๋ฅผ ํŒจ์น˜ํ•˜๋Š” ๊ณผ์ •(axios,swr, fetch, XMLHttpRequest)์€ CSR์˜ ๋ฐฉ์‹์„ ๋”ฐ๋ฆ„.
    ! ์ด๋•Œ์˜ ๋ฐ์ดํ„ฐ๋“ค์€ ์ผ๋‹จ ํŽ˜์ด์ง€๊ฐ€ ๋กœ๋“œ๋œ ์ดํ›„์— ํด๋ผ์ด์–ธํŠธ ์ธก์—์„œ ๋‹ค์‹œ ๋ Œ๋”๋˜๋ฉฐ ๋ถˆ๋Ÿฌ์™€์ง€๊ธฐ ๋•Œ๋ฌธ์— SEO์— ๊ฑธ๋ฆฌ์ง€ ์•Š์Œ.

  • ๋งŒ์•ฝ ํŽ˜์ด์ง€๊ฐ€ ๋กœ๋“œ๋  ๋•Œ ํ•จ๊ป˜ ๋ฐ์ดํ„ฐ๊ฐ€ ํŒจ์นญ๋˜์–ด์•ผ ํ•˜๋Š” ์ƒํ™ฉ์ด๋ผ๋ฉด(pre-rendering)
  • next.js์˜ ๋ฐ์ดํ„ฐ ํŒจ์นญ ๋ฐฉ์‹ (getInitialProps, getStaticProps, getStaticPath, getServerSideProps)์„ ์ด์šฉํ•ด ์ฒซ ๋ Œ๋”์— ๋ฐ์ดํ„ฐ๊ฐ€ ํŒจ์นญ๋  ์ˆ˜ ์žˆ๋„๋ก ์ฒ˜๋ฆฌ๋ฅผ ํ•ด์ฃผ์–ด์•ผ ํ•จ (์ฐธ๊ณ )


  • Q) Next๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ  โญ๏ธ
  • โ‘  ์‚ฌ์ „ ๋ Œ๋”๋ง ๋ฐ ์„œ๋ฒ„ ์‚ฌ์ด๋“œ ๋ Œ๋”๋ง
    - ์„œ๋ฒ„ ์‚ฌ์ด๋“œ ๋ Œ๋”๋ง ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ด ํด๋ผ์ด์–ธํŠธ ์‚ฌ์ด๋“œ ๋ Œ๋”๋ง ํ™˜๊ฒฝ๋ณด๋‹ค ๋น ๋ฅธ ๋ Œ๋”๋ง์„ ๋ถˆ๋Ÿฌ์˜ฌ ์ˆ˜ ์žˆ์Œ

    โ‘ก Hot Code Reloading ์ง€์›
    - Next ๊ฐœ๋ฐœ ํ™˜๊ฒฝ์—์„œ๋Š” ์ฝ”๋“œ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์ด ์ €์žฅ๋˜๋ฉด ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์„ ์ž๋™์œผ๋กœ ๋‹ค์‹œ ๋กœ๋“œ

    โ‘ข ์ž๋™ ์ฝ”๋“œ ๋ถ„ํ• 
    - ์ฝ”๋“œ์˜ ๋ชจ๋“  ๊ฐ€์ ธ์˜ค๊ธฐ๊ฐ€ ๋ฒˆ๋“ค๋กœ ๋ฌถ์—ฌ ๊ฐ ํŽ˜์ด์ง€์™€ ํ•จ๊ป˜ ์ œ๊ณต๋จ. ๊ฒฐ๊ณผ์ ์œผ๋กœ, ๋ถˆํ•„์š”ํ•œ ์ฝ”๋“œ๊ฐ€ ํŽ˜์ด์ง€์— ๋กœ๋“œ๋˜์ง€ ์•Š๊ฒŒ ๋จ

    โ‘ฃ ์„ค๋ช… ํ•„์š”X
    - Next๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ์›นํŒฉ๊ณผ ๋ฐ”๋ฒจ์„ ์‚ฌ์šฉํ•จ. ์ด๋ฏธ ์„œ๋ฒ„ ์‚ฌ์ด๋“œ ๋ Œ๋”๋ง ๋ฐ ๊ฐœ๋ฐœ์— ํ•„์š”ํ•œ ์„ค์ •์ด ๋˜์–ด ์žˆ์œผ๋ฏ€๋กœ ๋น ๋ฅด๊ฒŒ ๊ฐœ๋ฐœ ์‹œ์ž‘ ๊ฐ€๋Šฅ
    - ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ์€ ํ”Œ๋Ÿฌ๊ทธ์ธ์ด ์žˆ๋‹ค๋ฉด ์†์‰ฝ๊ฒŒ ์ถ”๊ฐ€ํ•ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ์ง€์›ํ•จ

    โ‘ค ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ ๋‚ด์žฅ

    โ‘ฅ ํŒŒ์ผ๊ธฐ๋ฐ˜ ๋„ค๋น„๊ฒŒ์ด์…˜ ๊ฐ€๋Šฅ
    - ๋ฆฌ์•กํŠธ์—์„œ๋Š” `react-router`๋ผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•ด ๋ผ์šฐํŒ… ์„ค์ •์„ ํ•ด์ค˜์•ผํ•จ. ๊ทธ๋กœ ์ธํ•ด ํŽ˜์ด์ง€์˜ ๊ฒฝ๋กœ์— ๋Œ€ํ•ด ์ง์ ‘ ์„ค์ •์„ ํ•ด์ค˜์•ผ ํ•จ
    - ํ•˜์ง€๋งŒ Next๋Š” ํŒŒ์ผ ์‹œ์Šคํ…œ ๊ธฐ๋ฐ˜ ๋ผ์šฐํŒ…์„ ์‚ฌ์šฉํ•ด, ํด๋”์˜ ๊ฒฝ๋กœ์— ๋”ฐ๋ผ ํŽ˜์ด์ง€์ด ๊ฒฝ๋กœ๊ฐ€ ์„ค์ •๋˜์–ด ๊ตฌ์ถ•์ด ๋น ๋ฅด๊ณ  ๊ด€๋ฆฌ๊ฐ€ ํŽธ๋ฆฌํ•˜๋‹ค๋Š” ์žฅ์ 

  • Q) Next๋ฅผ ๊ตฌ์„ฑํ•˜๋Š” ๊ธฐ๋ณธ ์„ค์ • ํŒŒ์ผ์€? โญ๏ธ
  • A) _app.jsx, _document.jsx, _error.jsx, 404.jsx
    • _app.jsx
      - App ์ปดํฌ๋„ŒํŠธ๋Š” ๋ชจ๋“  ํŽ˜์ด์ง€์˜ ๊ณตํ†ต ํŽ˜์ด์ง€ ์—ญํ• 

      - App ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ด์šฉํ•˜์—ฌ ๋ชจ๋“  ํŽ˜์ด์ง€๋“ค์„ ์ดˆ๊ธฐํ™”ํ•˜์—ฌ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์—ญํ• ์„ ํ•  ์ˆ˜ ์žˆ์Œ
      - ํŽ˜์ด์ง€๋“ค์˜ ๊ณตํ†ต๋œ ๋ ˆ์ด์•„์›ƒ, ํŽ˜์ด์ง€๋ฅผ ํƒ์ƒ‰ํ•  ๋•Œ ์ƒํƒœ ์œ ์ง€, ์ถ”๊ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ํŽ˜์ด์ง€์— ์ฃผ์ž…, ๊ธ€๋กœ๋ฒŒ CSS ์ถ”๊ฐ€

       
    • _document.jsx
      - ์ผ๋ฐ˜์ ์œผ๋กœ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ <HTML>๋ฐ <body> ํƒœ๊ทธ๋ฅผ ๋ณด๊ฐ•ํ•˜๋Š”๋ฐ ์‚ฌ์šฉ
      - ๋„ํ๋จผํŠธ๋ฅผ ์ด์šฉํ•˜์—ฌ <title><description><meta>๋“ฑ ํ”„๋กœ์ ํŠธ์˜ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•˜๋Š” HTML ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๊ณ ,
      - ํฐํŠธ๋‚˜ ์™ธ๋ถ€ api, cdn ๋“ฑ์„ ๋ถˆ๋Ÿฌ์˜ค๋„๋ก ํ•  ์ˆ˜ ์žˆ์Œ
      - ๋˜ํ•œ CSS-in-JS์˜ ์„œ๋ฒ„ ์‚ฌ์ด๋“œ ๋ Œ๋”๋ง์„ ์œ„ํ•œ ์„ค์ •์„ ํ•  ๋•Œ ์‚ฌ์šฉ
      - Head ํƒœ๊ทธ์— meta ํƒœ๊ทธ๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ํ•ด๋‹น ํ”„๋กœ์ ํŠธ์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๊ณ , ๊ตฌ๊ธ€ ํฐํŠธ ๋“ฑ์—์„œ ์ œ๊ณตํ•˜๋Š” ํฐํŠธ๋ฅผ link ๋กœ ๋ถˆ๋Ÿฌ์™€ ์ „์—ญ์œผ๋กœ ์ ์šฉ์‹œํ‚ฌ ์ˆ˜ ์žˆ์Œ

    • _error.jsx
      - next์—์„œ ๋นŒ๋“œ ๋œ ํ”„๋กœ๋•์…˜ ํ™˜๊ฒฝ์—์„œ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ์—๋Ÿฌ ํŽ˜์ด์ง€๋กœ ๋„˜์–ด๊ฐ
      - ๋”ฐ๋กœ ๋ผ์šฐํŒ… ๊ฒฝ๋กœ๋ฅผ ์„ค์ •ํ•˜์ง€ ์•Š๋”๋ผ๋„, ๋นŒ๋“œ ๋œ ํ”„๋กœ๋•ํŠธ ํ™˜๊ฒฝ์—์„œ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค๋ฉด ์—๋Ÿฌ ํŽ˜์ด์ง€๋กœ ์ž๋™์ ์œผ๋กœ ๋„˜์–ด๊ฐ
      - ์ถ”๊ฐ€์ ์œผ๋กœ ์—๋Ÿฌ ์ƒํ™ฉ์— ๋”ฐ๋ผ์„œ 500, 404 ๋“ฑ๋„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Œ
/* pages/_app.jsx */

import Header from '../components/Header';

const MyApp = ({ Component, pageProps }) => {
  return (
    <>
      <Header />
      <Component {...pageProps} />
      <style jsx global>
        {`
          body {
            margin: 0;
          }
        `}
      </style>
    </>
  );
};

export default MyApp;


/* pages/_document.jsx */

import Document, { Html, Head, Main, NextScript } from 'next/document';

class MyDocument extends Document {
  render() {
    return (
      <Html lang="ko">
        <Head>
          <meta name="title" content="๊นƒํ—ˆ๋ธŒ ๋ ˆํฌ์ง€ํ† ๋ฆฌ" />
          <meta name="description" content="๊นƒํ—ˆ๋ธŒ ๋ ˆํผ์ง€ํ† ๋ฆฌ ๋ฆฌ์ŠคํŠธ์ž…๋‹ˆ๋‹ค" />
          <link
            href="https://fonts.googleapis.com/css?family=Noto+Sans:400,700&display=swap"
            rel="stylesheet"
          />
          <link
            href="https://fonts.googleapis.com/css?family=Noto+Sans+KR:400,700&display=swap&subset=korean"
            rel="stylesheet"
          />
        </Head>
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    );
  }
}

export default MyDocument;


/* pages/_error.jsx */

const Error = () => {
  return (
    <div>
      <p>์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค</p>
    </div>
  );
};

export default Error;