Next.js: React Router 4์™€ ํ•จ๊ป˜ ์‚ฌ์šฉ

์— ๋งŒ๋“  2017๋…„ 04์›” 05์ผ  ยท  122์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: vercel/next.js

์ƒˆ๋กœ์šด ๋ฐ˜์‘ ๋ผ์šฐํ„ฐ v4์™€ ํ•จ๊ป˜ next.js๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

๊ฐ€์žฅ ์œ ์šฉํ•œ ๋Œ“๊ธ€

@timneutkens๊ฐ€ ๋ฐ˜์‘ ๋ผ์šฐํ„ฐ ํ†ตํ•ฉ์„ ์ถ”๊ฐ€ํ•˜๋ฉด nextjs ์ฑ„ํƒ์„ ๋Š˜๋ฆฌ๊ณ  ๊ฐœ๋ฐœ์„ ๊ฐœ์„ ํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ €์™€ ๊ฐ™์€ ๊ฐœ๋ฐœ์ž๋“ค์€ ์ด๋Ÿฐ ์ผ์ด ์ผ์–ด๋‚˜๊ธฐ๋ฅผ ์›ํ•ฉ๋‹ˆ๋‹ค. ์šฐ์„  ์ˆœ์œ„๋ฅผ ๋†’์ด๋Š” ๊ฒƒ์„ ๊ณ ๋ คํ•ด์ฃผ์„ธ์š”.

๋ชจ๋“  122 ๋Œ“๊ธ€

@Knaackee ๊ฐ€๋Šฅ์„ฑ์„ ์‹œํ—˜ํ•ด ๋ณด์•˜์Šต๋‹ˆ๊นŒ? ๋ˆ„๊ตฐ๊ฐ€๊ฐ€ RR์˜ ๋ชจ๋“  ๋ฒ„์ „๊ณผ ํ•จ๊ป˜ ์ž‘๋™ํ•˜๋„๋กํ–ˆ๋Š”์ง€ ๊ถ๊ธˆํ•ฉ๋‹ˆ๋‹ค.

๋‹ค์Œ์œผ๋กœ ์ž์‹ ์˜ ๋ผ์šฐํ„ฐ๊ฐ€ ์žˆ๋Š”๋ฐ ์™œ RR์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๊นŒ?

๊ธฐ์กด ์•ฑ์„ Next๋กœ ์ด์‹ ํ•  ๋•Œ @sergiodxa ๊ณ„๋Ÿ‰ ์˜ต์…˜. ์ •์ , ์ค‘์ฒฉ ๋œ ๊ฒฝ๋กœ ๊ตฌ์„ฑ์ด ์ž‘๋™ํ•˜๊ณ  ๋ฌด์—‡์„ ๊ณ„์† ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ๊ถ๊ธˆํ•ฉ๋‹ˆ๋‹ค.

@oyeanuj ๐Ÿค” ์ ์ง„์ ์œผ๋กœ Next๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Next.js๋ฅผ 1 ๊ฐœ์˜ ๊ฒฝ๋กœ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋„๋ก ์„ค์ •ํ•˜๊ณ  ํ”„๋ก์‹œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ˜„์žฌ ์•ฑ๊ณผ Next.js๋ฅผ ๋ชจ๋‘ ๋ณด์œ ํ•œ ๋‹ค์Œ ๋‘ ๋ฒˆ์งธ ๊ฒฝ๋กœ๋ฅผ RR์—์„œ Next.js๋กœ ์ด๋™ํ•˜๋ฉด๋ฉ๋‹ˆ๋‹ค. ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ํ•˜๋Š” ๋™์•ˆ ํ˜„์žฌ ์•ฑ์„ ์œ ์ง€ํ•  ์ˆ˜์žˆ๋Š” ๋ฐฉ๋ฒ•์€ ๊ฒฐ๊ตญ Next.js์— ๋ชจ๋“  ๊ฒƒ์ด ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.

์˜ˆ์ œ๋ฅผ ์‚ดํŽด๋ณด๋ฉด next์—๋Š” RRv2-3๊ณผ ๊ฐ™์€ ๋‹จ์ผ ๋ผ์šฐํŒ… ํ…Œ์ด๋ธ”์ด ์žˆ๊ณ  RRv4์™€ ๊ฐ™์€ "์ค‘์ฒฉ ๋œ ๊ฒฝ๋กœ"๋ฅผ ์ง€์›ํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์œผ๋กœ ๋ณด์ž…๋‹ˆ๋‹ค. ์ด๊ฒƒ๋“ค์€ ๋ฉ‹์ง€๋‹ค.

RR์„ ์‚ฌ์šฉํ•˜๋ ค๊ณ ํ•˜๊ฑฐ๋‚˜ ๋ชจ๋ฅด๋Š” ํฐ์ฃผ์˜ ์‚ฌํ•ญ์ด ์žˆ์Šต๋‹ˆ๊นŒ?

@igl ๊ทธ๊ฒƒ์— ๋Œ€ํ•œ ํ•ด๊ฒฐ์ฑ…์„

์ค‘์ฒฉ ๋œ ๊ฒฝ๋กœ์˜ ์ƒˆ๋กœ์šด react-router 4 ํŒจ๋Ÿฌ๋‹ค์ž„์€ ๊ฒŒ์ž„ ์ฒด์ธ์ €์ด๋ฉฐ ํ˜„์žฌ ํ”„๋กœ์ ํŠธ์—์„œ ํ•„์ˆ˜ ํ•ญ๋ชฉ์ž…๋‹ˆ๋‹ค. rr4๋ฅผ next.js์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๋Š” ๋ฐ ์„ฑ๊ณตํ•œ ์‚ฌ๋žŒ์ด ์žˆ๋Š”์ง€ ๊ถ๊ธˆํ•ฉ๋‹ˆ๋‹ค.

MemoryRouter ๋Š” ์˜๋„ ํ•œ๋Œ€๋กœ ์ž‘๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค ...
๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ๋™์  ๊ตฌ์„ฑ ์š”์†Œ๋Š” HashRouter ๊ฐ€ ์ œ๋Œ€๋กœ ์ž‘๋™ํ•˜๋Š” ํด๋ผ์ด์–ธํŠธ ์ธก๋งŒ ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

const AdminPage = dynamic(
  import('..../AdminPage'),
  { ssr: false }
);

๋‚˜๋Š” ๋˜ํ•œ @malixsys ์ ‘๊ทผ ๋ฐฉ์‹์„ react-router ํด๋ผ์ด์–ธํŠธ ์ธก ๋ผ์šฐํŒ…์„ ์ฒ˜๋ฆฌํ•˜๊ณ  next ๋ผ์šฐํ„ฐ๋กœ ๋ชจ๋“  ์„œ๋ฒ„ ๋ Œ๋”๋ง ์ฝ˜ํ…์ธ ๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

@malixsys @pegiadise ๋‹ค์Œ ๋ผ์šฐํ„ฐ์™€ ๋ฆฌ ์•กํŠธ ๋ผ์šฐํ„ฐ๋ฅผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•œ ์ž์„ธํ•œ ์ •๋ณด๋ฅผ ์ œ๊ณต ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

componentDidMount ํ”Œ๋ž˜๊ทธ๋ฅผ ์„ค์ •ํ•˜๊ณ  ํ”Œ๋ž˜๊ทธ๊ฐ€ ์ง„์‹ค ์ผ ๋•Œ <Router /> ์กฐ๊ฑด๋ถ€๋กœ ๋ Œ๋”๋ง ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ( componentDidMount ๋Š” ์„œ๋ฒ„์—์„œ ์‹คํ–‰๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค ๐Ÿ˜‰)

์‚ฌ์‹ค, ๊ณง Next.js์— React Router๋ฅผ ํ†ตํ•ฉ ํ•  ์˜ˆ์ •์ž…๋‹ˆ๋‹ค. :)
โ€” https://twitter.com/rauchg/status/948318111828099072

์—ฌ์ „ํžˆ ์ผ์–ด๋‚˜๊ณ  ์žˆ์Šต๋‹ˆ๊นŒ? V6 ์นด๋‚˜๋ฆฌ์•„์˜ ๋ฆด๋ฆฌ์Šค ์ •๋ณด๋ฅผ ๋ณผ ์ˆ˜ ์žˆ์ง€๋งŒ ์ด์— ๋Œ€ํ•œ ์–ธ๊ธ‰์€ ์—†์Šต๋‹ˆ๋‹ค.

๊ฒฐ๊ตญ. ํ™•์‹คํžˆ ์šฐ๋ฆฌ ๋งˆ์Œ์— ์žˆ์Šต๋‹ˆ๋‹ค. ์ง€๊ธˆ ๋‹น์žฅ ๋‹ค๋ฅธ ์šฐ์„  ์ˆœ์œ„๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค (๋ ˆ์ด์•„์›ƒ ๊ตฌ์„ฑ ์š”์†Œ, ์•ˆ์ •์ ์ธ ๊ฐœ๋ฐœ ๋ฐ ๊ธฐํƒ€ ์˜ค๋ž˜ ์ง€์†๋˜๋Š” ๋ช‡ ๊ฐ€์ง€ ๋ฏธํ•ด๊ฒฐ ๋ฌธ์ œ).

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

@timneutkens๊ฐ€ ๋ฐ˜์‘ ๋ผ์šฐํ„ฐ ํ†ตํ•ฉ์„ ์ถ”๊ฐ€ํ•˜๋ฉด nextjs ์ฑ„ํƒ์„ ๋Š˜๋ฆฌ๊ณ  ๊ฐœ๋ฐœ์„ ๊ฐœ์„ ํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ €์™€ ๊ฐ™์€ ๊ฐœ๋ฐœ์ž๋“ค์€ ์ด๋Ÿฐ ์ผ์ด ์ผ์–ด๋‚˜๊ธฐ๋ฅผ ์›ํ•ฉ๋‹ˆ๋‹ค. ์šฐ์„  ์ˆœ์œ„๋ฅผ ๋†’์ด๋Š” ๊ฒƒ์„ ๊ณ ๋ คํ•ด์ฃผ์„ธ์š”.

๋ถ€๋„๋Ÿฌ์šด ์ผ์ž…๋‹ˆ๋‹ค. ํŒ€์˜ ์šฐ์„  ์ˆœ์œ„๊ฐ€ ๋‚ฎ์„ ์ˆ˜ ์žˆ์ง€๋งŒ ๊ธฐ๋ณธ์ ์œผ๋กœ ์ €์™€ ๊ฐ™์€ ์‚ฌ๋žŒ๋“ค์ด ์‚ฌ์šฉ์„ ์‹œ์ž‘ํ•˜๋Š” ๊ฒƒ์„ ๋ง‰๋Š” ์œ ์ผํ•œ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.

๊ฐ™์€.

์ถ”์  ํ•  ์ˆ˜ ์žˆ๋„๋ก ์ ์–ด๋„์ด ๋ฌธ์ œ๋ฅผ ๋‹ค์‹œ ์—ด ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

๋‚˜๋Š” ์ด๊ฒƒ์„ ๋‹ค์‹œ ์—ด ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ด๊ฒƒ์€ ์˜คํ”ˆ ์†Œ์Šค ํ”„๋กœ์ ํŠธ ์ด๊ณ  ์šฐ๋ฆฌ๋Š” ๋ชจ๋“  ๊ฒƒ์— Next.js๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— ํ˜„์žฌ zeit.co์— ๋Œ€ํ•ด ๊ทธ๋‹ค์ง€ ๊ฐ•๋ ฅํ•œ ์‚ฌ๋ก€๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์ด๊ฒƒ์ด ์ œ๊ฐ€ ์žฅ๊ธฐ ๋ชฉํ‘œ์˜ ์ผ๋ถ€์ด๋ฉฐ ์ฆ‰์‹œ ๊ตฌํ˜„ํ•  ์ˆ˜ ์—†๋‹ค๊ณ  ๋งํ•œ ์ด์œ ์ž…๋‹ˆ๋‹ค.ํ•˜์ง€๋งŒ ์šฐ๋ฆฌ๋Š” ๊ทธ๊ฒƒ์„ ์œ„ํ•ด ๋…ธ๋ ฅํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

Next 6์—์„œ ์†Œ๊ฐœ ํ•œ ๊ธฐ๋Šฅ์€ ์‹ค์ œ๋กœ React Router ์ง€์›์„ ์œ„ํ•ด ์ž‘๋™ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

Next 6์— ๋Œ€ํ•œ ๋‹ค๋ฅธ ์šฐ์„  ์ˆœ์œ„๋Š” Next.js์˜ ์•ˆ์ •์„ฑ๊ณผ ํ™•์žฅ ์„ฑ์„ ์—„์ฒญ๋‚˜๊ฒŒ ํ–ฅ์ƒ ์‹œํ‚ค๋Š”๋ฐ, ์˜ˆ๋ฅผ ๋“ค์–ด 100 ๋ฐฐ ๋” ๋น ๋ฅธ ํŽ˜์ด์ง€ ํ™•์ธ, ์•ฑ ๊ตฌ์„ฑ ์š”์†Œ, ๊ฐœ๋ฐœ์ค‘์ธ ๋‹ค์Œ ๋‚ด๋ณด๋‚ด๊ธฐ ์ž‘์—… ๋งŒ๋“ค๊ธฐ, babel 7 ๋“ฑ.

๋‚˜๋Š” ์ด๊ฒƒ์ด ๋‚˜์˜ ์ด์ „ ์˜๊ฒฌ์— ๋Œ€ํ•ด ์ž์„ธํžˆ ์„ค๋ช…ํ•˜๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ TLDR์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • ์šฐ๋ฆฌ๋Š” ๊ทธ๊ฒƒ์„ ํ•  ๊ฒƒ์ด์ง€๋งŒ ์ฆ‰์‹œ๋Š” ์•„๋‹™๋‹ˆ๋‹ค
  • Next 6์—๋Š” Next.js์˜ ์—ฌ๋Ÿฌ ๋ถ€๋ถ„์ด ๋งŽ์ด ๊ฐœ์„ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

@timneutkens ์˜ ์˜๊ฒฌ์„ ๋” ํ™•์žฅํ•˜๊ธฐ ์œ„ํ•ด : ์šฐ๋ฆฌ๋Š” ํ™•์‹คํžˆ RR์„ ์›ํ•˜์ง€๋งŒ ํ˜„์žฌ ๋ผ์šฐํ„ฐ์— ์šฐ์„  ์ˆœ์œ„๋ฅผ ๋ถ€์—ฌํ•˜๋Š” ๊ธด๊ธ‰ํ•œ ์ œํ•œ์ด ์—†์Šต๋‹ˆ๋‹ค. ์ƒ์ƒํ•  ์ˆ˜์žˆ๋Š” ๋ชจ๋“  ๋ผ์šฐํŒ… ์‚ฌ์šฉ ์‚ฌ๋ก€๊ฐ€ ํ˜„์žฌ Next.js API๋กœ ์„ฑ๊ณต์ ์œผ๋กœ ๊ตฌํ˜„๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

React Router ์ง€์› ์„ ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค .

  • ์ž์ฒด ๋ผ์šฐํ„ฐ๋ฅผ ์œ ์ง€ ๊ด€๋ฆฌ ํ•  ํ•„์š”์—†์ด ์ž์ฒด Next.js ์ฝ”๋“œ๋ฒ ์ด์Šค๋ฅผ ๋‹จ์ˆœํ™”ํ•˜๊ณ  ํฌ๊ธฐ๋ฅผ ์ค„์ด๊ณ  ๋ชจ๋“ˆํ™”ํ•ฉ๋‹ˆ๋‹ค.
  • ์ด๋ฏธ RR์„ ์‚ฌ์šฉํ•˜๊ณ ์žˆ๋Š” ๋Œ€๊ทœ๋ชจ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ๊ฒฝ๋กœ ๋‹จ์ˆœํ™”

๋”ฐ๋ผ์„œ์ด ๋ฌธ์ œ๋ฅผ ๊ณ„์† ๊ณต๊ฐœํ•ด์•ผํ•œ๋‹ค๋Š” ๋ฐ ๋™์˜ํ•ฉ๋‹ˆ๋‹ค!

๋Œ€์œ„๋ฒ•์œผ๋กœ react-router๊ฐ€ ์—†๋‹ค๋Š” ๊ฒƒ์€ next๊ฐ€ relay-modern๊ณผ ์ž˜ ์ž‘๋™ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•˜๋ฉฐ ์šฐ๋ฆฌ๊ฐ€ ์ด์ „ react-router ์•ฑ์—์„œ next๋กœ ์ „ํ™˜ ํ•œ ์ด์œ  ์ค‘ ํ•˜๋‚˜์˜€์Šต๋‹ˆ๋‹ค.

@merry ์ž‘๋…„์— ๋ฆด๋ ˆ์ด ๋ชจ๋˜์œผ๋กœ RRv4 ์•ฑ์—์„œ ์ž‘์—…ํ–ˆ๋Š”์ง€ ์—ฌ๋ถ€. ์ข€ ๋” ๊ตฌ์ฒด์ ์œผ๋กœ ์„ค๋ช… ํ•˜์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ?
๋‘˜ ์ค‘ ํ•˜๋‚˜ ๋•Œ๋ฌธ์— ์‹ฌ๊ฐํ•œ ๋ฌธ์ œ๊ฐ€ ์žˆ์—ˆ๋˜ ๊ธฐ์–ต์ด ์—†์Šต๋‹ˆ๋‹ค.

@igl ์ด๊ฒƒ์€ ๋ฆด๋ ˆ์ด ๋ฌธ์„œ์— ๋”ฐ๋ฅธ ๊ฒƒ์ž…๋‹ˆ๋‹ค : https://facebook.github.io/relay/docs/en/routing.html#react -router-https-reacttrainingcom-react-router

๋ฌธ์ œ๋Š” RRv4์˜ ๊ตฌ์„ฑ ์š”์†Œ ์ ‘๊ทผ ๋ฐฉ์‹์ด ์‚ฌ์ „ ์ปดํŒŒ์ผ ๋‹จ๊ณ„์—์„œ ๊ฒฐ์ • ์„ฑ์„ ํ—ˆ์šฉํ•˜์ง€ ์•Š์•„ ํด๋ผ์ด์–ธํŠธ์—์„œ ์š”์ฒญ ํญํฌ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

@rauchg ํฅ๋ฏธ๋กญ๊ฒŒ๋„ Next์˜ ๋ผ์šฐํ„ฐ์— ๋Œ€ํ•œ ๋‚˜์˜ ์ดํ•ด๋Š” ์ค‘์ฒฉ ๋ผ์šฐํŒ… ๊ฐœ๋…์„ ์ง€์›ํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ํŽ˜์ด์ง€ ๋‚ด์—์„œ ํƒ์ƒ‰ํ•˜๋Š” ๋™์•ˆ ์™ธ๋ถ€ ๋งˆํฌ ์—…์„ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํ˜„์žฌ ๋ผ์šฐํ„ฐ๋กœ์ด๋ฅผ ๊ฐ€๋Šฅํ•˜๊ฒŒํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ๋Š”์ง€ ์•Œ๊ณ  ์žˆ์Šต๋‹ˆ๊นŒ?

@dbbk ๋Š” nextgram ์˜ˆ์ œ ์•ฑ (https://github.com/now-examples/nextgram)์„ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

๋‹ค์Œ 5 ๋ฒˆ์—์„œ๋Š” ๋ชจ๋“  ํŽ˜์ด์ง€๊ฐ€ ํ™•์žฅ๋˜๋Š” ์ตœ์ƒ์œ„ ๋ ˆ์ด์•„์›ƒ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ "์™ธ๋ถ€ ๋งˆํฌ ์—…"์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ ๋ ˆ์ด์•„์›ƒ์—๋Š” ์ƒ๋‹จ ํƒ์ƒ‰์ด ์žˆ๊ณ , ๋ชฉ๋ก / ์„ธ๋ถ€ ์ •๋ณด / ๊ธฐํƒ€์— ๋Œ€ํ•œ ๊ธฐ๋ณธ์„ ํ™•์žฅํ•˜๋Š” ๋ช‡ ๊ฐ€์ง€ ํ•˜์œ„ ๋ ˆ์ด์•„์›ƒ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ํŽ˜์ด์ง€ ๊ตฌ์„ฑ ์š”์†Œ๋Š” ์ด๋Ÿฌํ•œ ํ•˜์œ„ ๋ ˆ์ด์•„์›ƒ์„ ๊ณ ์œ  ํ•œ ํŠน์ • ์ฝ˜ํ…์ธ ๋กœ ํ™•์žฅํ•ฉ๋‹ˆ๋‹ค. ๋‹ค์Œ 6์—์„œ๋Š” _app.js ์‚ฌ์šฉํ•˜์—ฌ ๊ธฐ๋ณธ "์™ธ๋ถ€ ๋งˆํฌ ์—…"์„ ์ˆ˜ํ–‰ ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‹ค์Œ ๋ฒ„์ „์€ React Router๊ฐ€ ์•„๋‹Œ ๋ผ์šฐํŒ… ์†”๋ฃจ์…˜์„ ์„ ํƒํ•˜๋„๋ก ๊ตฌ์„ฑ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

์•ˆ๋…•, ๋‚œ ๋‹จ์ง€ (์‚ฌ์šฉ ํŽ˜์ด์ง€์— ์†Œํ’ˆ์„ ํ†ต๊ณผํ•˜๊ธฐ ์œ„ํ•ด ๋ผ์šฐํ„ฐ ๋ฐ˜์‘ ํ•  ํ•„์š” <Route render ={} /> ๋Œ€์‹  <Route component ={} /> ๋‚˜๋Š”์ด ๋‹ค์Œ์— ํ•  ์ˆ˜์žˆ๋Š”)?

์˜ˆ์ œ๋ฅผ ์‚ดํŽด๋ณด๋ฉด next์—๋Š” RRv2-3๊ณผ ๊ฐ™์€ ๋‹จ์ผ ๋ผ์šฐํŒ… ํ…Œ์ด๋ธ”์ด ์žˆ๊ณ  RRv4์™€ ๊ฐ™์€ "์ค‘์ฒฉ ๋œ ๊ฒฝ๋กœ"๋ฅผ ์ง€์›ํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์œผ๋กœ ๋ณด์ž…๋‹ˆ๋‹ค. ์ด๊ฒƒ๋“ค์€ ๋ฉ‹์ง€๋‹ค.

์•ˆ๋…•ํ•˜์„ธ์š”,

์ด๊ฒƒ์€ ๋‹จ์ผ ๊ฒฝ๋กœ์— ๋Œ€ํ•ด ๋‹จ์ผ ํŽ˜์ด์ง€๋ฅผ ๋งŒ๋“ค์–ด์•ผ ํ•จ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๊นŒ?

2 ๊ฐœ์˜ ๊ฒฝ๋กœ sign up , log in ๊ฐ€ ์žˆ๋‹ค๊ณ  ๊ฐ€์ • ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ๋™์ผํ•œ ๋ ˆ์ด์•„์›ƒ์„ ๊ณต์œ ํ•˜๋Š” 1 ํŽ˜์ด์ง€๊ฐ€์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์œ ์ผํ•œ ์ฐจ์ด์ ์€ ์–‘์‹ ์˜์—ญ์ž…๋‹ˆ๋‹ค. pages ํด๋”์— ํŒŒ์ผ 1 ๊ฐœ๋ฅผ ์ƒ์„ฑํ•˜๋ฉด๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋‹ค์Œ ๊ฒฝ๋กœ์—์„œ๋Š” pages ํด๋”์— 2 ๊ฐœ์˜ ํŒŒ์ผ์„ ๋งŒ๋“ค์–ด์•ผํ•ฉ๋‹ˆ๋‹ค. ๋งž๋‚˜์š”?

๊ทธ๋ ‡๋‹ค๋ฉด ๋ ˆ์ด์•„์›ƒ์€ ์–‘์‹ ์˜์—ญ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ๋ชจ๋“  ํƒ์ƒ‰๊ณผ ํ•จ๊ป˜ ๋‹ค์‹œ ๋งˆ์šดํŠธ๋ฉ๋‹ˆ๋‹ค.

@ 7c78 ํ•  ์ˆ˜์žˆ๋Š” ํ•œ ๊ฐ€์ง€๋Š” ๋ชจ๋“  ํŽ˜์ด์ง€์— ๋Œ€ํ•œ ์˜๊ตฌ ํŽ˜์ด์ง€ ๋ ˆ์ด์•„์›ƒ์— _app.js ๋ฅผ ํ™œ์šฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋˜ ๋‹ค๋ฅธ ์ž‘์—…์€ ์›ํ•˜๋Š” ๊ฒƒ์„ ์–ป๊ธฐ ์œ„ํ•ด ๋‹ค์–‘ํ•œ ํŽ˜์ด์ง€์—์„œ ์žฌ์‚ฌ์šฉ ํ•  ์ˆ˜์žˆ๋Š” ๊ณต์œ  ๋ ˆ์ด์•„์›ƒ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

// pages/login.js

class LoginPage extends React.Component {
  render() {
    return (
      <AuthForm>    // same component can be reused in signup
        <form>
          ...implementation of login
        </form>
      </AuthForm>
    );
  }
}

๋˜ํ•œ ์ตœ๊ทผ์— ์ˆ˜ํ–‰ ํ•œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๊ณ  ํŽ˜์ด์ง€ ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ๋ชจ๋‘ ํ™•์žฅํ•˜๋Š” ๊ธฐ๋ณธ ๋ ˆ์ด์•„์›ƒ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์ •์˜ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

//layouts/baseAuth.js

class BaseAuth extends React.Component {
  abstract formContent();  // we use typescript, but you can have the same concepts
  abstract formSubmit():

  render() {
    return (
      <SomeStyledDiv>
        <form>
          {this.formContent()}
          {this.formSubmit()}
        </form>
      </SomeStyledDiv>
    );
  }
}

๊ทธ๋Ÿฐ ๋‹ค์Œ ๋กœ๊ทธ์ธ ๋ฐ ๊ฐ€์ž… ํŽ˜์ด์ง€์—์„œ BaseAuth๋ฅผ ํ™•์žฅํ•˜๊ณ  ๊ฐ๊ฐ์— formContent ๋ฐ formSubmit ๋ฅผ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค (์ •ํ™•ํ•œ ์š”๊ตฌ ์‚ฌํ•ญ์„ ๋ชจ๋ฅด๊ธฐ ๋•Œ๋ฌธ์— ์žฅ๋‚œ๊ฐ ์˜ˆ์ œ์ž…๋‹ˆ๋‹ค).

์•ˆ๋…•ํ•˜์„ธ์š”.
๋‚˜๋Š” ํ˜„์žฌ ๋‹น์‹ ์˜ ์ ‘๊ทผ ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์œผ๋ฉฐ ๋‹ค์Œ ์˜ˆ์ œ๋„ ๊ทธ๊ฒƒ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ๋‚ด ๊ด€์‹ฌ์‚ฌ๋Š” ๋ณ„๋„์˜ ์–‘์‹์— ๋Œ€ํ•ด ๋ณ„๋„์˜ ํŽ˜์ด์ง€๋ฅผ ๋งŒ๋“ค์–ด์•ผํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์€ ๋ ˆ์ด์•„์›ƒ์ด ์žฌ์‚ฌ์šฉ๋˜์ง€๋งŒ ํŽ˜์ด์ง€๋Š” ์•„๋‹™๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋ ˆ์ด์•„์›ƒ์€ ๋ชจ๋“  ํƒ์ƒ‰๊ณผ ํ•จ๊ป˜ ๋‹ค์‹œ ๋งˆ์šดํŠธ๋ฉ๋‹ˆ๋‹ค.

RRv4์—์„œ๋Š” ๋‹จ์ผ ํŽ˜์ด์ง€๊ฐ€ ์žˆ์œผ๋ฉฐ ์–‘์‹์€ ์ „์ฒด ํŽ˜์ด์ง€๊ฐ€ ์•„๋‹Œ ๊ฒฝ๋กœ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๋ Œ๋”๋ง / ์žฌ ๋งˆ์šดํŠธ๋ฉ๋‹ˆ๋‹ค. ๊ฒฝ๋กœ๋Š” ๊ตฌ์„ฑ ์š”์†Œ ์ผ๋ฟ์ž…๋‹ˆ๋‹ค.

๋น ๋ฅธ ์‘๋‹ต์— ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค!

@ 7c78 vDOM ์ด ๋™์ผํ•œ ์ƒํƒœ๋กœ ํ™•์ธ ๋  ๋•Œ โ€‹โ€‹DOM ๋…ธ๋“œ๊ฐ€ ๋‹ค์‹œ ์‚ฌ์šฉ๋œ๋‹ค๊ณ  ์ƒ๊ฐํ•˜์ง€๋งŒ ๋‹ค์‹œ ๋งˆ์šดํŠธํ•˜๋Š” ๊ฒƒ์€ ์‚ฌ์‹ค์ž…๋‹ˆ๋‹ค.

์šฐ๋ฆฌ๋Š” ๋˜ํ•œ ๋ฆด๋ ˆ์ด ๋ชจ๋˜๊ณผ ํ•จ๊ป˜ ๋ฆฌ ์•กํŠธ ๋ผ์šฐํ„ฐ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์— ์šฐ๋ฆฌ๊ฐ€ ๋งค์šฐ ์—ผ๋ ค ํ•ด ์™”๋˜ ๊ฒƒ์ด ์•„๋‹™๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์šฐ๋ฆฌ๋Š” ์ƒ๊ด€์—†์ด์ด ํŒจํ„ด์„ ์‚ฌ์šฉํ•ด์•ผํ–ˆ์Šต๋‹ˆ๋‹ค.

@merry ์„œ๋ฒ„๊ฐ€ ๋ชจ๋“  ๊ฒฝ๋กœ์— ๋Œ€ํ•ด ์ƒˆ ๋ฌธ์„œ / html์„ ๋ฐ˜ํ™˜ํ•˜๊ธฐ ๋•Œ๋ฌธ์— vDOM์— ๋Œ€ํ•ด ์ž˜ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค. ์ฃ„์†กํ•ฉ๋‹ˆ๋‹ค.์ด ๊ฐ€์ •์„ ๋ฌด์‹œํ•˜์‹ญ์‹œ์˜ค. ์ €๋Š” ๋‹จ์ง€ ์ดˆ๋ณด์ž ์ผ๋ฟ์ž…๋‹ˆ๋‹ค.

์–ด์จŒ๋“ ์ด ํŒจํ„ด์„ ์‚ฌ์šฉํ•ด์•ผํ•œ๋‹ค๋Š” ๋ฐ ๋™์˜ํ•ฉ๋‹ˆ๋‹ค. ๊ฐ์‚ฌ!

์ „์ฒด ์•ฑ์ด pages / index.js์— ์žˆ๋„๋กํ•˜์—ฌ next.js์™€ ํ•จ๊ป˜ RR์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ์ฆ‰์‹œ ์ฝ”๋“œ ๋ถ„ํ• ๊ณผ ๊ฐ™์€ ๋‹ค์Œ์˜ ์žฅ์  ์ค‘ ์ผ๋ถ€๋ฅผ ์žƒ๊ณ  ์ง์ ‘ ์„ค์ •ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

Reach Router๊ฐ€ ๊ณ ๋ ค๋œ๋‹ค๋ฉด ๊ทธ๊ฒƒ์„ ์ข‹์•„ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. react-router์™€ ๋งค์šฐ ์œ ์‚ฌํ•˜๋ฉฐ ๋ช‡ ๊ฐ€์ง€ ์ค‘์š”ํ•œ ์ด์ ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

  • ๋งํฌ ์ƒ์„ฑ ๋ฐ ํฌ์ปค์Šค ๊ด€๋ฆฌ (https://reach.tech/router/accessibility)์™€ ๊ด€๋ จ๋œ ๋ช‡ ๊ฐ€์ง€ ์ค‘์š”ํ•œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•ฉ๋‹ˆ๋‹ค.
  • ๋ฌด๊ฒŒ๊ฐ€ ์ ์Œ (์ž‘์„ฑ ๋‹น์‹œ)

๋„๋‹ฌ ๋ผ์šฐํ„ฐ๋„ ํ›Œ๋ฅญํ•ฉ๋‹ˆ๋‹ค ๐Ÿฅ‡

RR ์Šคํƒ€์ผ์˜ ๋™์  ๊ฒฝ๋กœ๋Š” ์ข‹์€ API์ด์ง€๋งŒ ์ •์  (์ •์ ์œผ๋กœ ๋ถ„์„ ๊ฐ€๋Šฅํ•œ) ๋ผ์šฐํŒ…๋„ ๋งŽ์€ ์ด์ ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ๋‘ ์ ‘๊ทผ๋ฒ• ๋ชจ๋‘ ์Šฌ๋žจ ๋ฉํฌ ์Šน์ž๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค.

@sorokinvj ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ํ†ตํ•ด์„œ๋งŒ ์ง€์›๋ฉ๋‹ˆ๋‹ค (ํ˜„์žฌ) .. https://github.com/fridays/next-routes

์ •์  ๋งํฌ๋Š” ๋„ˆ๋ฌด ๊ธฐ๋ณธ์ ์ด์–ด์„œ ๋งํฌ์˜ ๋งค๊ฐœ ๋ณ€์ˆ˜๋„ ์ง€์›ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๋‚˜๋Š” ํƒ€์‚ฌ ํŒจํ‚ค์ง€ ๋‹ค์Œ ๊ฒฝ๋กœ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค .https : //github.com/fridays/next-routes

๋‚ด iPhone์—์„œ ๋ณด๋ƒ„

2018 ๋…„ 10 ์›” 24 ์ผ 23:01์— Andy Ingram [email protected] ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ผ์Šต๋‹ˆ๋‹ค.

RR ์Šคํƒ€์ผ์˜ ๋™์  ๊ฒฝ๋กœ๋Š” ์ข‹์€ API์ด์ง€๋งŒ ์ •์  (์ •์ ์œผ๋กœ ๋ถ„์„ ๊ฐ€๋Šฅํ•œ) ๋ผ์šฐํŒ…๋„ ๋งŽ์€ ์ด์ ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ๋‘ ์ ‘๊ทผ๋ฒ• ๋ชจ๋‘ ์Šฌ๋žจ ๋ฉํฌ ์Šน์ž๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค.

โ€”
์ด ์Šค๋ ˆ๋“œ๋ฅผ ๊ตฌ๋…ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์—์ด ๋ฉ”์‹œ์ง€๊ฐ€ ์ „์†ก๋˜์—ˆ์Šต๋‹ˆ๋‹ค.
์ด ์ด๋ฉ”์ผ์— ์ง์ ‘ ๋‹ต์žฅํ•˜๊ฑฐ๋‚˜ GitHub์—์„œ ๋ณด๊ฑฐ๋‚˜ ์Šค๋ ˆ๋“œ๋ฅผ ์Œ์†Œ๊ฑฐํ•˜์‹ญ์‹œ์˜ค.

์šฐ๋ฆฌ๋Š” ๋‹น๋ถ„๊ฐ„ next-routes ๋„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์ง€๋งŒ ๋‹ค์Œ ํŒ€์€ ์ •๊ทœ์‹ ํŒŒ์ผ ์ด๋ฆ„ (Sapper์—์„œ ์˜๊ฐ์„ ์–ป์Œ)์„ ํ†ตํ•ด ํŒŒ์ผ ์‹œ์Šคํ…œ ๋ผ์šฐํŒ…์— ๊ฒฝ๋กœ ๋งค๊ฐœ ๋ณ€์ˆ˜๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ์ž‘์—…์„ํ•˜๊ณ  ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

@merrywhether ๋‚˜๋Š” next-routes ๋„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์ง€๋งŒ ์ด๊ฒƒ์ด Next.js ์ฝ”์–ด์˜ ์ผ๋ถ€๊ฐ€๋˜๋Š” ๊ฒƒ์„ ์„ ํ˜ธํ•ฉ๋‹ˆ๋‹ค.

๋‹น์‹ ์€ ์–ธ๊ธ‰ํ–ˆ์Šต๋‹ˆ๋‹ค

๋‹ค์Œ ํŒ€์ด ๊ฒฝ๋กœ ๋งค๊ฐœ ๋ณ€์ˆ˜ ์ถ”๊ฐ€ ์ž‘์—…์„ํ•˜๊ณ  ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค ...

์ด๊ฒƒ์— ๋Œ€ํ•œ ์ฐธ๊ณ  ๋ฌธํ—Œ์ด ์žˆ์Šต๋‹ˆ๊นŒ? ๊ฒฝ๋กœ ๋งค๊ฐœ ๋ณ€์ˆ˜์— ๋Œ€ํ•œ ๋ฏธํ•ด๊ฒฐ ๋ฌธ์ œ์ผ๊นŒ์š”? ํ•˜๋‚˜๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค ... ์•„๋งˆ๋„ ํ”Œ๋Ÿฌ๊ทธ์ธ์ด ํ•„์š”๋ฅผ ํ•ด๊ฒฐํ•˜๊ณ  ์•ž์œผ๋กœ ๊ถŒ์žฅ๋˜๋Š” ์†”๋ฃจ์…˜์ด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

@curran ์†Œ์Šค๋Š”

์ด ๋ฌธ์ œ๋Š” 2017 ๋…„ 4 ์›” 5 ์ผ์— ์ œ๊ธฐ๋˜์—ˆ์œผ๋ฉฐ ์ง€๊ธˆ์€ 2019 ๋…„ 2 ์›” 27 ์ผ์ž…๋‹ˆ๋‹ค. ๊ฑฐ์˜ 2 ๋…„ ๋™์•ˆ ํ•ด๊ฒฐ์ฑ…์ด ์—†์Šต๋‹ˆ๋‹ค.
์ ˆ๋ฐ˜ ์ •๋„์˜ ๋‚ด์žฅ ๋ผ์šฐํ„ฐ๋ฅผ ์ข‹์€ ๊ฒƒ์œผ๋กœ ๊ต์ฒด ํ•  ๋•Œ๊ฐ€ ๋˜์—ˆ์„๊นŒ์š”?

์•„์•ผ. ์ด๋Š” ๋ผ์šฐํŒ… ์†”๋ฃจ์…˜์— ๋งŽ์€ ์‹œ๊ฐ„์„ ํˆฌ์ž ํ•œ NextJS ๊ฐœ๋ฐœ์ž์—๊ฒŒ ์ƒ๋‹นํžˆ ๋ชจ์š•์ ์ž…๋‹ˆ๋‹ค.

์ฒ˜์Œ์—๋Š” ReactRouter๋ฅผ ๋†“์ณค์Šต๋‹ˆ๋‹ค. ์ด์ œ๋Š” ๋ˆ„๊ตฐ๊ฐ€๊ฐ€ ๋‚˜์—๊ฒŒ ์ƒ๊ธฐ์‹œํ‚ค๊ธฐ ์ „๊นŒ์ง€ NextJS๊ฐ€ ๋‹ค๋ฅธ ๋ผ์šฐํ„ฐ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค๋Š” ์‚ฌ์‹ค์กฐ์ฐจ ๊ธฐ์–ตํ•˜์ง€ ๋ชปํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด Verbose Link API๋Š” (๋ฐ์ดํ„ฐ / API ์•„ํ‚คํ…์ฒ˜์— ๋”ฐ๋ผ) ํ”„๋ก์‹œ๋กœ ๋ž˜ํ•‘ํ•˜๊ธฐ๊ฐ€ ์‰ฝ์Šต๋‹ˆ๋‹ค. ์ด ์ผ๊ธ‰ ๋น„๋ฐ€ ๊ณต์œ  : ๐Ÿ˜†

import _Link from "next/link"
export function Link({as, children, href}) {
  as = as || QS.parse(U.parse(href).query || "").url || null // QS, U are parsing libs
  return <_Link as={as} href={href}>
    {children}
  </_Link>
}
<Link as="/about" href="/page?url=/about"/> verbose
โ†’
<Link href="/page?url=/about"/> ok

๋‚˜๋Š” ์šฐ๋ฆฌ ๋ชจ๋‘๊ฐ€ ๋ถ€์ฐจ์  ์ธ ๊ฒƒ์— ๋Œ€ํ•ด ๋ถˆํ‰ํ•˜๋Š” ๋ฐ ๋” ์ ์€ ์‹œ๊ฐ„์„ ์†Œ๋น„ํ•ด์•ผํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•œ๋‹ค ๐Ÿ˜‰

@ ivan-kleshnin Nice ๋น„์Šทํ•œ ๋ž˜ํผ๋ฅผ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค.

์ด์ „ ์˜๊ฒฌ์— ๋”ฐ๋ผ https://www.contributor-covenant.org/version/1/4/code-of-conduct ๋ฅผ ๊ฐ€๋ฆฌํ‚ค๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.

๋Œ“๊ธ€์„ ์ˆจ๊ฒผ์Šต๋‹ˆ๋‹ค.

๋Œ€๋ถ€๋ถ„์˜ ์‚ฌ์šฉ ์‚ฌ๋ก€์—์„œ next/router ์— ๋ฌธ์ œ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.
๊ทธ๋Ÿฌ๋‚˜ universal routing ๋ถ€๋ถ„์—์„œ ์•ฝ๊ฐ„ ๊ฐœ์„ ๋˜์–ด์•ผํ•ฉ๋‹ˆ๋‹ค.
Now 2 ๋ฐฐํฌ์˜ ๊ฒฝ์šฐ now.json ๋งŒ ๊ฐ€์ ธ ์™€์„œ ๋‚ด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ๋ผ์šฐํŒ…ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.

RR4๋ฅผ nextJs ํ”„๋กœ์ ํŠธ์— ๊ตฌํ˜„ํ•˜๋ ค๋ฉด ๋‹ค์Œ ๋‘ ๊ฐ€์ง€๋ฅผ ์ˆ˜ํ–‰ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

  1. NextJS SSR ๋ฐฉ์ง€, next/dynamic ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๊ทธ๋ ‡๊ฒŒ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  2. ์‚ฌ์šฉ HashRouter ๋Œ€์‹  BrowserRouter -> ์‚ฌ์šฉ์ž ์žฌ ์žฅ์ „ ํŽ˜์ด์ง€, ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์ด์ „ ํŽ˜์ด์ง€๋ฅผ๋กœ๋“œ ํ•  ์ˆ˜์žˆ๋Š” ๊ฒฝ์šฐ (์•ˆ 404 ํŽ˜์ด์ง€)

RR4๋ฅผ nextJs ํ”„๋กœ์ ํŠธ์— ๊ตฌํ˜„ํ•˜๋ ค๋ฉด ๋‹ค์Œ ๋‘ ๊ฐ€์ง€๋ฅผ ์ˆ˜ํ–‰ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

  1. NextJS SSR ๋ฐฉ์ง€, next/dynamic ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๊ทธ๋ ‡๊ฒŒ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  2. ์‚ฌ์šฉ HashRouter ๋Œ€์‹  BrowserRouter -> ์‚ฌ์šฉ์ž ์žฌ ์žฅ์ „ ํŽ˜์ด์ง€, ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์ด์ „ ํŽ˜์ด์ง€๋ฅผ๋กœ๋“œ ํ•  ์ˆ˜์žˆ๋Š” ๊ฒฝ์šฐ (์•ˆ 404 ํŽ˜์ด์ง€)

์ด ๋‹ต์žฅ์„ ๋ณด๋‚ด ์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

@ reach / router์™€ react-router 5๊ฐ€ ๋ณ‘ํ•ฉ๋ฉ๋‹ˆ๋‹ค : https://reacttraining.com/blog/reach-react-router-future/

์ด๊ฒƒ์ด next.js์— ์–ด๋–ค ์˜ํ–ฅ์„ ๋ฏธ์นฉ๋‹ˆ ๊นŒ?

@ alp82 Next.js๋Š” ์—ฌ์ „ํžˆ React Router ๋˜๋Š” Reach Router๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— Next.js์—๋Š” ์ „ํ˜€ ์˜ํ–ฅ์„์ฃผ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์ธ๋ฑ์Šค ํŽ˜์ด์ง€์—์„œ ์—ฌ๋Ÿฌ ํŽ˜์ด์ง€ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ๋ Œ๋”๋งํ•˜๋ ค๋ฉด nextjs์˜ ์Šค์œ„์น˜ ๊ฒฝ๋กœ ๊ธฐ๋Šฅ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.
๊ทธ๋ž˜์„œ ์–ด๋–ป๊ฒŒ nextjs ....... ??์—์„œ ์ด๊ฒƒ์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

RR4๋ฅผ nextJs ํ”„๋กœ์ ํŠธ์— ๊ตฌํ˜„ํ•˜๋ ค๋ฉด ๋‹ค์Œ ๋‘ ๊ฐ€์ง€๋ฅผ ์ˆ˜ํ–‰ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

  1. NextJS SSR ๋ฐฉ์ง€, next/dynamic ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๊ทธ๋ ‡๊ฒŒ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  2. ์‚ฌ์šฉ HashRouter ๋Œ€์‹  BrowserRouter -> ์‚ฌ์šฉ์ž ์žฌ ์žฅ์ „ ํŽ˜์ด์ง€, ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์ด์ „ ํŽ˜์ด์ง€๋ฅผ๋กœ๋“œ ํ•  ์ˆ˜์žˆ๋Š” ๊ฒฝ์šฐ (์•ˆ 404 ํŽ˜์ด์ง€)

404 ์˜ค๋ฅ˜๋ฅผ ๋ฐœ์ƒ์‹œํ‚ค์ง€ ์•Š๊ณ  ์ด์ „ ํŽ˜์ด์ง€๋ฅผ ๋‹ค์‹œ ๋ Œ๋”๋งํ•˜๋ ค๋ฉด ์ต์Šคํ”„๋ ˆ์Šค ์„œ๋ฒ„ ํŒŒ์ผ์—์„œ์ด get ๊ฒฝ๋กœ๋ฅผ ์‚ฌ์šฉํ•˜์‹ญ์‹œ์˜ค.

server.get ( 'your params', (req, res) => {
const actualPage = '/ your_page'
const queryParams = {id : req.params.id}
app.render (req, res, actualPage, queryParams)
})

๋‚ด๊ฐ€ ์‚ฌ์šฉํ•˜๋Š” ์ ‘๊ทผ ๋ฐฉ์‹์„ ๋ฌธ์„œํ™” next.js ๊ฐ€์ง„ react-router ๋‹จ์ผ ์ง„์ž… ์  ํŒŒ์ผ ๋Œ€์‹  ๊ธฐ๋ณธ ํŒŒ์ผ ์‹œ์Šคํ…œ ๊ธฐ๋ฐ˜ ๊ธฐ๋Šฅ์„ ๊ธฐ๋ณธ SSR์„ ๋ณด์กด ์™„์ „ํžˆ ๋ผ์šฐํŒ… ๋“ฑ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

ํ”ผ๋“œ๋ฐฑ์„ ๋ฐ›๊ณ  ๊ฐœ์„ ํ•ด ๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค.

์„ค๋ช…์„œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ฑด๋ฐฐ!

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

@timneutkens ์–ด์ฉŒ๋ฉด ๋‚ด๊ฐ€ ํ‹€๋ ธ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ง€์—ฐ ๋กœ๋”ฉ์„ ์‚ฌ์šฉํ•˜๋ฉด ๋ผ์šฐํŒ… ๊ตฌ์„ฑ์€ ํ•˜๋‚˜์˜ ๊ตฌ์„ฑ ํŒŒ์ผ ์ผ๋ฟ์ž…๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” ํ™•์žฅ ์„ฑ์ด๋‚˜ ์„ฑ๋Šฅ์— ์˜ํ–ฅ์„ ๋ฏธ์น˜์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด๊ฒƒ์— ๋Œ€ํ•ด ๋” ๋ฐฐ์šฐ๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.
react-router์˜ ์žฅ์ ์€ ๊ฐœ๋ฐœ์ž๊ฐ€ ์ฝ”๋“œ๋ฅผ ์™„์ „ํžˆ ์ œ์–ด ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

@timneutkens , ์—ฌ๊ธฐ์„œ ๋…ผ์Ÿ์„ ์‹œ์ž‘ํ•˜์ง€๋Š” ์•Š๊ฒ ์ง€ ๋งŒ ๋‚ด ๋Œ“๊ธ€ ์ˆจ๊ธฐ๊ธฐ๋ฅผ ํ•ด์ œ ํ•ด๋‹ฌ๋ผ๊ณ  ๋ถ€ํƒ๋“œ๋ฆฝ๋‹ˆ๋‹ค. ๋‚˜๋Š” ๋‚ด ์ง์—…์„ ์‚ฌ์šฉํ•  ์ˆ˜์žˆ๊ฒŒ ๋งŒ๋“ค๊ณ  ๊ทธ๊ฒƒ์„ ์ปค๋ฎค๋‹ˆํ‹ฐ์— ๋Œ๋ ค์ฃผ๊ธฐ ์œ„ํ•ด ์‹œ๊ฐ„์„ ๋ณด๋ƒˆ์ง€ ๋งŒ ์‚ฌ๋žŒ๋“ค์„ ์นจ๋ฌต์‹œํ‚ค๋Š” ๊ฒƒ์ด ์˜คํ”ˆ ์†Œ์Šค ๊ฐœ๋ฐœ์— ์–ด๋–ป๊ฒŒ ๋„์›€์ด ๋  ์ˆ˜ ์žˆ๋Š”์ง€ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค.

@timneutkens ๋Š” ๋‹น์‹ ์ด ์–ธ๊ธ‰ ํ•œ ์ ์— ๊ด€ํ•ด์„œ๋Š” ํŠธ๋ ˆ์ด๋“œ ์˜คํ”„ ๋ฌธ์ œ์ž…๋‹ˆ๋‹ค. Mine์€ Next.js๊ฐ€ ๋‹ค๋ฅธ ์„ค์ •์—์„œ ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ๋Š”์ง€๋ฅผ ๋ณด์—ฌ์ฃผ๋Š” ์‹คํ—˜์ž…๋‹ˆ๋‹ค.

ํด๋ผ์ด์–ธํŠธ ์ธก์— ๋„ˆ๋ฌด ๋งŽ์€ ์ฝ”๋“œ

๋ชจ๋“  ์ตœ์‹  ๋ฒˆ๋“ค์€ ํด๋ผ์ด์–ธํŠธ ์ž์‚ฐ์„ ์ฒญํฌ๋กœ ๋ถ„ํ•  ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ react-router ๊ฒฝ๋กœ๋Š” ์‹ค์ œ๋กœ ๋งค์šฐ ํŽธ๋ฆฌํ•œ ๋ถ„ํ•  ์ง€์ ์ž…๋‹ˆ๋‹ค.

๋” ๋†’์€ ๊ฐœ๋ฐœ ๋นŒ๋“œ ์‹œ๊ฐ„

ํฐ ํ”„๋กœ์ ํŠธ์— ์ง€๋ถˆํ•˜๋Š” ๋Œ€๊ฐ€์ด์ง€๋งŒ ์ ์ ˆํ•œ ์›นํŒฉ ๋ฏธ์„ธ ์กฐ์ •์œผ๋กœ๋Š” ํ•ด๊ฒฐํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

์ •์  ๋‚ด๋ณด๋‚ด๊ธฐ ์—†์Œ

์ •์  ๋‚ด๋ณด๋‚ด๊ธฐ๊ฐ€ ์ค‘์š”ํ•œ ์ตœ์ ํ™” ๋ ˆ์ด์–ด๋ผ๋Š” ๋ฐ ๋™์˜ํ•ฉ๋‹ˆ๋‹ค. ํ‰๊ท ์ ์ธ Next.js ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์ œ๊ณตํ•˜๋Š” ๋Œ€๋ถ€๋ถ„์˜ ํŽ˜์ด์ง€๋Š” ์–ด์จŒ๋“  ๋™์  ๋ฐ์ดํ„ฐ๋ฅผ ๊ฒ€์ƒ‰ํ•ด์•ผํ•˜๋ฉฐ ์ •์  ๋‚ด๋ณด๋‚ด๊ธฐ์˜ ์ด์ ์„ ์–ป์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

์ด ๋ฌธ์ œ์— ๋Œ€ํ•œ ํ•ด๊ฒฐ์ฑ…์ด ๋ถ€์กฑํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์˜ˆ : ์ •์ ์œผ๋กœ ๋‚ด๋ณด๋‚ผ ๊ฒฝ๋กœ ๋ชฉ๋ก์„ ์ˆ˜๋™์œผ๋กœ ์„ ์–ธ ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‚ด๊ฐ€ ๋Œ“๊ธ€์„ ์ˆจ๊ธด ์ด์œ ๋Š” ์ด๊ฒƒ์ด ๋†’์€ ํŠธ๋ž˜ํ”ฝ ๋ฌธ์ œ์ด๋ฉฐ Next.js ์•ฑ ๋นŒ๋“œ์— ๋Œ€ํ•œ ๊ถŒ์žฅ ์‚ฌํ•ญ์„ ๋ฐ˜์˜ํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋ˆ„๊ตฐ๊ฐ€๊ฐ€ ์—ฌ๊ธฐ์„œ react-router๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๊ณ ํ•œ๋‹ค๋ฉด ๊ทธ๋“ค์€ ์—ฌ๋Ÿฌ๋ถ„์˜ ์˜ˆ์ œ๋ฅผ ๋งน๋ชฉ์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๊ณ  Next.js๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ผ์šฐํŒ…์„ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์„ค์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์กฐ์‚ฌํ•˜์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

ํฐ ํ”„๋กœ์ ํŠธ์— ์ง€๋ถˆํ•˜๋Š” ๋Œ€๊ฐ€์ด์ง€๋งŒ ์ ์ ˆํ•œ ์›นํŒฉ ๋ฏธ์„ธ ์กฐ์ •์œผ๋กœ๋Š” ํ•ด๊ฒฐํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

์ ‘๊ทผ ๋ฐฉ์‹์— ๋”ฐ๋ผ ๊ฐœ๋ฐœ ์‹œ๊ฐ„ ๋ถ€ํŒ… ์†๋„๋ฅผ ๋†’์ผ ์ˆ˜๋Š” ์—†์Šต๋‹ˆ๋‹ค. webpack์€ ์ผ๋ฐ˜์ ์ธ ๊ตฌ์„ฑ ์š”์†Œ์— ๋Œ€ํ•œ ํŽธ์ง‘ ์†๋„๋ฅผ ๋Œ€ํญ ๋Š๋ฆฌ๊ฒŒ ๋งŒ๋“œ๋Š” ๋ชจ๋“  ๋‹จ์ผ ๊ฒฝ๋กœ๋ฅผ ์ปดํŒŒ์ผํ•˜๊ณ  ๊ฐ์‹œํ•˜๊ธฐ ๋•Œ๋ฌธ์— webpack ๊ตฌ์„ฑ์— ๋Œ€ํ•œ ํŠน์ • ๋ฏธ์„ธ ์กฐ์ •์ด ์—†์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ Next.js์— ์ฃผ๋ฌธํ˜• ํ•ญ๋ชฉ์ด์žˆ๋Š” ์ด์œ  : https://nextjs.org/blog/next-8#improved -on-demand-entries

๋˜ํ•œ ๊ฒฝ๋กœ ๋“ฑ์˜ (์ž๋™) ๋ฏธ๋ฆฌ ๊ฐ€์ ธ ์˜ค๊ธฐ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์— ๋“ค์–ด๊ฐˆ ์ˆ˜์žˆ๋Š” ์„ธ๋ถ€ ์‚ฌํ•ญ์ด ๋งŽ์ด ์žˆ์ง€๋งŒ tldr์€ ๊ฒฐ๊ตญ ๊ฐœ๋ฐœ์ž ๊ฒฝํ—˜๊ณผ ์•ฑ์ด ๋” ๋‚˜๋น ์งˆ ๊ฒƒ์ด๋ผ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์‚ฌ์šฉํ•˜๋ ค๋Š” ์œ ์ผํ•œ ์‹œ๊ฐ„์ด ์ด๋ฏธ react-router๋ฅผ ์‚ฌ์šฉํ•˜๊ณ ์žˆ๋Š” ์•ฑ์„ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ํ•œ ๋‹ค์Œ ์ ์ฐจ ์—ฌ๋Ÿฌ ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•˜๋Š” ๊ฒƒ์ž„์„ ์ ์ ˆํ•˜๊ฒŒ ๋ฐ˜์˜ํ•˜๋Š” ๊ฒฝ์šฐ ๋Œ“๊ธ€ ์ˆจ๊น€์„ ํ•ด์ œํ•ด๋„ ๊ดœ์ฐฎ์Šต๋‹ˆ๋‹ค.

์•ˆ๋…•ํ•˜์„ธ์š” @timneutkens
์ •์ ์œผ๋กœ ๋ถ„์„ ํ•  ์ˆ˜์žˆ๋Š” ๋ช‡ ๊ฐ€์ง€ ์ „๋ฌธ๊ฐ€๋ฅผ ๊ณ„์‚ฐํ•ด ๋ณด์‹œ๊ณ  ๋™์  ๋ผ์šฐํŒ… ์†”๋ฃจ์…˜์œผ๋กœ๋Š” ๋ถˆ๊ฐ€๋Šฅํ•œ ์ผ์ด ์žˆ์œผ์‹ญ๋‹ˆ๊นŒ?

https://github.com/jaredpalmer/after.js ๊ฐ™์€ ๊ฒƒ์ด ์žˆ์Šต๋‹ˆ๊นŒ?

๋‚˜๋Š” ๋ชจ๋“  ์˜๊ฒฌ์„ ์ฝ์—ˆ์œผ๋ฉฐ RR4 +๊ฐ€ next.js์˜ ํ–ฅํ›„ ๋ฐ˜๋ณต์—์„œ ํฌํ•จ๋˜๋Š”์ง€ ๋˜๋Š” ์„ ํƒ ์‚ฌํ•ญ์ธ์ง€ ์•„์ง ๋ช…ํ™•ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋ผ์šฐํ„ฐ ๋กœ๋“œ๋งต ๋˜๋Š” ์œ ์‚ฌํ•œ ๊ฒƒ์ž…๋‹ˆ๊นŒ?

@laurencefass (์˜ค๋Š˜ ํ˜„์žฌ) react-router ๋ฅผ ์ง€์›ํ•  ๊ณ„ํš์ด์—†๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

๋‚˜์—๊ฒŒ Next.js์˜ ๋ผ์šฐํŒ… ์‹œ์Šคํ…œ์€ ์ถฉ๋ถ„ํžˆ ์„ฑ์ˆ™ ํ•ด์ง€๊ณ  ์žˆ์œผ๋ฏ€๋กœ ์–ด์จŒ๋“  (๋” ์ด์ƒ) ํ•„์š”ํ•˜์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. :)

"๋‚˜์—๊ฒŒ Next.js์˜ ๋ผ์šฐํŒ… ์‹œ์Šคํ…œ์€ ์ถฉ๋ถ„ํžˆ ์„ฑ์ˆ™ ํ•ด์ ธ์„œ ์•„๋งˆ (๋” ์ด์ƒ) ํ•„์š”ํ•˜์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. :)"

๊ธฐ์กด ์ฝ”๋“œ๋ฒ ์ด์Šค์—์„œ Next.js๋ฅผ ์ ์ง„์ ์œผ๋กœ ์ฑ„ํƒํ•˜๋ ค๋Š” ์‚ฌ๋žŒ๋“ค์„ ์ œ์™ธํ•˜๊ณ . ๋” ์œ ์šฉํ•œ ํ† ๋ก ์€ ์•„๋งˆ๋„ "Next.js ๋ผ์šฐํŒ… ๋Œ€ ๋ฐ˜์‘ ๋ผ์šฐํ„ฐ ๋ผ์šฐํŒ…"์ด ์•„๋‹ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋” ์œ ์šฉํ•œ ํ† ๋ก ์€ "react-router๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฑฐ๋Œ€ํ•œ ์•ฑ์„ Next.js๋กœ ์ ์ง„์ ์œผ๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ํ•˜๋Š” ๋ฐฉ๋ฒ•"์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

๋‹ค์Œ์˜ ๋ผ์šฐํ„ฐ๋Š” ๊ฒฝ๋กœ๋ณด๊ธฐ๋ฅผ ์ค‘์ฒฉ ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๊ทธ๋ ‡์ฃ ? ๊ฒฝ๋กœ์— ๋Œ€ํ•œ ๋ชจ๋“  ํƒ์ƒ‰์€ DOM์„ ๋‚ ๋ ค ๋ฒ„๋ฆฌ๊ณ  ์ƒˆ๋กœ ๊ณ ์นฉ๋‹ˆ๋‹ค. ์ค‘์ฒฉ ๋œ ๋ทฐ๋Š” ๋งค์šฐ ์ผ๋ฐ˜์ ์ธ ์š”๊ตฌ ์‚ฌํ•ญ์ž…๋‹ˆ๋‹ค.

@dbbk nextjs ํŒ€์ด ์ž‘์—… ์ค‘์ด๋ผ๊ณ  ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค.

๋‹ค์Œ js๋Š” ๋ผ์šฐํ„ฐ์— ๋งค์šฐ ์œ ์—ฐํ•ฉ๋‹ˆ๋‹ค. https://dev.to/toomuchdesign/next-js-react-router-2kl8

์›น ์‚ฌ์ดํŠธ๋ฅผ ์ผ๋ฐ˜ JS ๋ฐ jQuery ์ฝ”๋“œ์—์„œ React๋กœ ์ด๋™ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ์ „ ์ฝ”๋“œ์™€ ๋‹ฌ๋ฆฌ ํŽ˜์ด์ง€๋ฅผ ๋ณ€๊ฒฝํ•  ๋•Œ ์Œ์•…์ด ๋ฉˆ์ถ”์ง€ ์•Š๋„๋กํ•ด์•ผํ•ด์„œ React Router๋ฅผ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.

์ด์ œ SEO ๋ชฉ์ ์œผ๋กœ Google ๊ฒ€์ƒ‰์—์„œ ์ข‹์€ ํŠธ๋ž˜ํ”ฝ์ด ๋ฐœ์ƒํ–ˆ๊ธฐ ๋•Œ๋ฌธ์—์ด๋ฅผ ์œ ์ง€ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋” ๋‚˜์€ ์„ฑ๋Šฅ์„ ์œ„ํ•ด Next.js์™€ ํ•จ๊ป˜ SSR์„ ์„ ํ˜ธํ•ฉ๋‹ˆ๋‹ค.

Next.js๋Š” ์„œ๋ฒ„ ์ธก์—์„œ ํŽ˜์ด์ง€๋ฅผ ๋ Œ๋”๋ง ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ํด๋ผ์ด์–ธํŠธ ์ธก์—์„œ ํŽ˜์ด์ง€๊ฐ€๋กœ๋“œ๋˜๋ฉด Next.js๋Š” React Router ์ œ์–ด ํ•˜์—์„œ ํƒ์ƒ‰์„ ํ—ˆ์šฉํ•˜๋ฏ€๋กœ ์‚ฌ์šฉ์ž๊ฐ€ ์Œ์•…์„ ๋“ฃ๊ณ  ์žˆ์œผ๋ฉด Next.js ๋งํฌ๊ฐ€ ์Œ์•…์„ ์ค‘์ง€ํ•˜๋ ค๋ฉด ํ˜„์žฌ ํŽ˜์ด์ง€๋ฅผ ๋– ๋‚˜์•ผํ•ฉ๋‹ˆ๊นŒ?

O Next.js๋Š” ํด๋ผ์ด์–ธํŠธ ์ธก ๋ผ์šฐํŒ… ๋งŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

React Router๋ฅผ ํ†ตํ•ฉํ•˜๋ฉด์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์•ฑ์ด ํด๋ผ์ด์–ธํŠธ ์ธก์— ๋„๋‹ฌํ•˜๋ฉด ์—ฐ์† ์Œ์•… ์žฌ์ƒ์ด ํ•„์ˆ˜์ด๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

๋‹ค์Œ js๋Š” ๋ผ์šฐํ„ฐ์— ๋งค์šฐ ์œ ์—ฐํ•ฉ๋‹ˆ๋‹ค. https://dev.to/toomuchdesign/next-js-react-router-2kl8

@laurencefass , ์•„์ฃผ ์ข‹์€ ์ ‘๊ทผ ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค. ์ „์— ์ฝ์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ธฐ์‚ฌ๋Š” Next.js ํŒ€์ด ๊ถŒ์žฅํ•˜์ง€ ์•Š๋Š”๋‹ค๊ณ  ๋งํ•ฉ๋‹ˆ๋‹ค. ์ด์œ ๋ฅผ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๋‚˜์—๊ฒŒ ์ข‹์€ ๊ฒƒ ๊ฐ™์•„

@KeitelDOG ๋ฅผ ์œ„ํ•ด react-router๊ฐ€ ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. Next.js ๋ผ์šฐํŒ…์€ ๋™์ผํ•œ ์ด์ ์„ ์ œ๊ณต ํ• ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ์ž๋™ ์ฝ”๋“œ ๋ถ„ํ•  ๋•๋ถ„์— ์•ฑ์ด ๋” ๊ฐ€๋ฒผ์›Œ์ง‘๋‹ˆ๋‹ค (react-router๋กœ๋Š” ์‰ฝ๊ฒŒ ์–ป์„ ์ˆ˜ ์—†์Œ).

_edit : ๊ทธ๋ƒฅ ์ถ”๊ฐ€ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค : react-router์˜ ์œ ์ผํ•œ ์žฅ์ ์€ ๋™์ผํ•œ๋ณด๊ธฐ ๊ธฐ๋Šฅ์— ์‰ฝ๊ฒŒ ์ค‘์ฒฉ ๋œ ๊ฒฝ๋กœ ์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Next.js ๋ผ์šฐํ„ฐ๋Š” ์‚ฌ์šฉ ์‚ฌ๋ก€์˜ 95 %๋ฅผ ํ•ด๊ฒฐํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค _

@martpie ์‘๋‹ต Link ๊ตฌ์„ฑ ์š”์†Œ๋กœ ๋ณด์•˜์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ Next.js๋Š” ๋‚ด๊ฐ€ ์›ํ•˜๋Š” ๋ฏน์Šค ์„œ๋ฒ„-ํด๋ผ์ด์–ธํŠธ์ž…๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ๋™์ ์œผ๋กœ ์ค‘์ฒฉ ๋œ ๊ฒฝ๋กœ๋ฅผ ์„ธ๋ถ€์ ์œผ๋กœ ์ œ์–ดํ•˜๋Š” โ€‹โ€‹๊ตฌ์„ฑ ์š”์†Œ์˜ ๊ฒฝ์šฐ React Router๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ React ์›น ์‚ฌ์ดํŠธ๋ฅผ Next.js๋กœ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๊ณ  ๋Œ€์‹  JS-jQuery ์›น ์‚ฌ์ดํŠธ๋ฅผ ๋‚ด SEO ์ด์ ์„ ์žƒ์ง€ ์•Š๊ณ  React ๋‹ค์ค‘ ํŽ˜์ด์ง€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์œผ๋กœ ๋ณ€๊ฒฝํ•˜๊ธฐ ์œ„ํ•ด ๊ณ„ํšํ•˜๊ณ  ํ…Œ์ŠคํŠธํ•˜๊ธฐ ๋•Œ๋ฌธ์— ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์„ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค๊ณ  ํ™•์‹ ํ•ฉ๋‹ˆ๋‹ค. Google์—์„œ. ๊ทธ๋ž˜์„œ Next.js๋กœ ๊ฐ€์•ผํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

@timneutkens Next.js 10์—์„œ์ด๋ฅผ ์ง€์›ํ•  ๊ณ„ํš์ด ์žˆ์Šต๋‹ˆ๊นŒ?

@TrejGun ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค, ๊ทธ๊ฒƒ์€ ํ™•์‹คํžˆ ์ฃผ์ œ์—์„œ ๋ฒ—์–ด๋‚œ ๊ฒƒ์ด ์•„๋‹™๋‹ˆ๋‹ค.

๊ณ„ํš์ด ์žˆ์Šต๋‹ˆ๊นŒ?
next/router ๋Š” ํ›Œ๋ฅญํ•˜๊ณ  ๋งŽ์€ ๋„์›€์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋ณต์žกํ•œ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์— ๋Œ€์ฒ˜ํ•˜๋ ค๋ฉด ๋” ์ „๋ฌธ์ ์ธ ๋ผ์šฐํ„ฐ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. React-router๋Š” ๋ผ์šฐํ„ฐ์˜ ์„ ๋‘ ์ฃผ์ž์ž…๋‹ˆ๋‹ค.
after.js ๋ฅผ ์ฐธ์กฐ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์˜ˆ,์ด ํŽ˜์ด์ง€ ๊ธฐ๋ฐ˜ ์‹œ์Šคํ…œ์€ ์ค‘์ฒฉ ๋œ ๊ฒฝ๋กœ์˜ ์ด์ ์„ ์–ป์„ ์ˆ˜์žˆ๋Š” ๋ณต์žกํ•œ ๋ฐ์ดํ„ฐ ๊ธฐ๋ฐ˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์ฒ˜๋ฆฌ ํ• ๋งŒํผ ์ •๊ตํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

React-router๋Š” ํ˜„์žฌ๊นŒ์ง€ ์ตœ๊ณ ์˜ ๋ผ์šฐํ„ฐ๊ฐ€ ๋  v6 ๋ฒ„์ „ ์„ ๊ณง ์ถœ์‹œ ํ•  ์˜ˆ์ •์ž…๋‹ˆ๋‹ค. next.js ์ง€์›์„ ๊ธฐ๋Œ€ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

๋” ๋‚˜์€ ์ ‘๊ทผ ๋ฐฉ์‹์€ next.js ์™€ router ์„ ๋ถ„๋ฆฌํ•˜์—ฌ ์‚ฌ๋žŒ๋“ค์ด ์ข‹์•„ํ•˜๋Š” router ์ž์œ ๋กญ๊ฒŒ ์„ ํƒํ•  ์ˆ˜ ์žˆ๋„๋กํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ด์ „ ๋Œ“๊ธ€์— +1. next.js๋Š” ๋‚ด๊ฐ€ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ์œ ์ผํ•œ ์ด์œ ๋Š” ๋ผ์šฐํ„ฐ์˜ ์œ ์—ฐ์„ฑ์ด ๋ถ€์กฑํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ํ–ฅํ›„ ๋ฆด๋ฆฌ์Šค์—์„œ React Router 6์„ ์ง€์›ํ•˜๊ฑฐ๋‚˜ ๋ผ์šฐํ„ฐ๋ฅผ ์Šค์™‘ ๊ฐ€๋Šฅํ•˜๊ฒŒ ๋งŒ๋“œ์‹ญ์‹œ์˜ค.

React Router๋ฅผ ์ •๋ง ์ข‹์•„ํ•˜๋Š” ์‚ฌ๋žŒ๋“ค์€ ๊ฐ™์€ ์ œ์ž‘์ž๊ฐ€ ๋งŒ๋“  React Router๋ฅผ ์‚ฌ์šฉํ•˜๋Š” Next.js ๋Œ€์•ˆ ์ธ "Remix"๋ผ๋Š” ์ƒˆ ํ”„๋กœ์ ํŠธ๋ฅผ ๋”ฐ๋ฅด๋Š” ๋ฐ ๊ด€์‹ฌ์ด์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋ฌธ์ œ๋Š” ํ”„๋ ˆ์ž„ ์›Œํฌ๊ฐ€ SSR, Server Side Props ๋“ฑ์œผ๋กœ ์ธํ•ด ํ•ด๋‹น ๋ผ์šฐํ„ฐ์— ๊นŠ์ด ์—ฐ๊ฒฐ๋˜์–ด ์žˆ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

Next๋Š” ์„ฑ๋Šฅ์„ ์—ผ๋‘์—๋‘๊ณ  ๊ตฌ์ถ•๋˜์—ˆ์œผ๋ฉฐ ์„œ๋ฒ„ ์ธก react-router๋Š” ๋ Œ๋”๋งํ•˜๋ ค๋Š” ํ•ญ๋ชฉ๊ณผ ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ์•Œ๊ธฐ ์ „์— DOM ํŠธ๋ฆฌ๋ฅผ ๊ฑธ์–ด์•ผํ•œ๋‹ค๋Š” ์ ์—์„œ ์„ฑ๋Šฅ์— ํฐ ์˜ํ–ฅ์„ ๋ฏธ์นฉ๋‹ˆ๋‹ค. getInitialProps ์˜ ์ „์ฒด ๋ชฉ์ ์€ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ ์˜ค๊ธฐ ์ „์— ๋ฐ˜์‘์„ ์ผ์‹œ์ ์œผ๋กœ ๋ Œ๋”๋ง ํ•  ํ•„์š”๊ฐ€ ์—†๋„๋กํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด๋Š” ๋งŽ์€ ํ”„๋ ˆ์ž„ ์›Œํฌ๊ฐ€ ์„œ๋ฒ„ (๋ฐ ํด๋ผ์ด์–ธํŠธ์—์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋‚˜ํƒ€๋‚จ)์—์„œ ๊ฒฝํ—˜ํ•˜๋Š” ์ผ๋ฐ˜์ ์ธ ํ•จ์ •์ž…๋‹ˆ๋‹ค. ํญํฌ ์š”์ฒญ). ๋‹ค์Œ์œผ๋กœ ๊ฐ ์ตœ์ƒ์œ„ ํŽ˜์ด์ง€์—์„œ ๋‹ค์–‘ํ•œ ํ•˜์œ„ ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ํ•„์š”๋กœ ํ•  ์ˆ˜์žˆ๋Š” ๋‹ค์–‘ํ•œ ๋ฐ์ดํ„ฐ ํŒจํ„ด์„ _all_ ์„ ์–ธํ•˜๊ณ  ์ „์ฒด ์š”์ฒญ ๊ฒฝ๋กœ์—์„œ ๋ถ„๊ธฐ (๋˜๋Š” ๋Œ€๊ทœ๋ชจ ๋‹จ์ผ ์˜ค๋ฒ„ ํŽ˜์น˜ ์ˆ˜ํ–‰)ํ•จ์œผ๋กœ์จ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์‹ค์ œ๋กœ ๊ฐ ํŽ˜์ด์ง€๋ฅผ ๊ฐœ๋ณ„์ ์œผ๋กœ ์„ ์–ธํ•˜๋Š” ๊ฒƒ๊ณผ ํฌ๊ฒŒ ๋‹ค๋ฅด์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ Relay๊ฐ€ react-router ์™€๋„ ํ˜ธํ™˜๋˜์ง€ ์•Š๋Š” ๊ฒƒ๊ณผ ๊ฐ™์€ ์ด์œ ์ด๋ฉฐ facebook.com์ด ๋ณต์žกํ•œ ์›น ์‚ฌ์ดํŠธ๊ฐ€ ์•„๋‹ˆ๋ผ๊ณ  ๋น„๋‚œ ํ•  ์ˆ˜๋Š” ์—†์Šต๋‹ˆ๋‹ค.

Next ๋ผ์šฐํ„ฐ๋กœ ์ž‘์—…ํ•˜๊ธฐ์œ„ํ•œ ์ฃผ์š” ์„ฑ๊ณต์ ์ธ ์ „๋žต์€ ๊ตฌ์„ฑ ๊ฐ€๋Šฅ์„ฑ (์–ด์จŒ๋“  ํ˜„๋Œ€ React์˜ ์ถ”์ง„ ์ถ”์„ธ)์œผ๋กœ ๊ธฐ์šธ์—ฌ ์ฃผ์š” ์ค‘๋ณต์—†์ด ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์žฌ์‚ฌ์šฉ ํ•  ์ˆ˜์žˆ๋Š” ๋™์‹œ์— ๋ชจ๋“  ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜์žˆ๋Š” ํšจ์œจ์ ์ธ SSR์„ ๋ณด์œ ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ( getInitialProps ๋ฅผ ํ†ตํ•ด) React ๋ Œ๋”๋Ÿฌ์™€ ๋Œ€ํ™”ํ•˜๊ธฐ ์ „์—.

๋‚˜๋Š” ๋‚˜๋ฌด๋ฅผ ๊ฑท๋Š” ๊ฒƒ์— ๋”ฐ๋ฅธ ์„ฑ๋Šฅ ์ €ํ•˜๊ฐ€ ๊ณผ์žฅ๋œ ๊ฒƒ ๊ฐ™๋‹ค. ์˜ค๋Š˜๋‚  ๋งŽ์€ ํ”„๋กœ๋•์…˜ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์ด ์˜ˆ๋ฅผ ๋“ค์–ด Apollo๋กœ์ด ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๊ณ  ์žˆ์œผ๋ฉฐ ๊ดœ์ฐฎ์€ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

๋˜ํ•œ ์„œ๋ฒ„๊ฐ€ ๋„ˆ๋ฌด ๋งŽ์€ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ์„ ์ •๋ง๋กœ ๋œ์–ด์ฃผ๊ณ  ์‹ถ๋‹ค๋ฉด CDN์—์„œ ์‘๋‹ต์„ ์บ์‹œ ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฌผ๋ก , React-router๊ฐ€ (AFAICT) ํ˜„์žฌ ๊ตฌํ˜„์—์„œ Next์™€ ๊ทผ๋ณธ์ ์œผ๋กœ ํ˜ธํ™˜๋˜์ง€ ์•Š๋Š” ์ฃผ๋œ ์ด์œ ๋ฅผ ์ง€์ ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋Š๋ฆฐ ์ฝœ๋“œ ์Šคํƒ€ํŠธ โ€‹โ€‹์‹œ๊ฐ„์œผ๋กœ ๋ฌด๋ฃŒ Heroku ๋‹ค์ด๋…ธ๋ฅผ ํ–‰๋ณตํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜๋Š” ์‚ฌ๋žŒ๋“ค์ด ์ž…์ฆํ–ˆ๋“ฏ์ด ๋งŽ์€ ์‚ฌ์ดํŠธ์—๋Š” ์‹ค์ œ๋กœ ์„ฑ๋Šฅ์ด ์ „ํ˜€ ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์™„๋ฒฝํ•˜๊ฒŒ ๋งž์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค). ๊ทธ๋Ÿฌ๋‚˜ Next๋Š” ์„œ๋ฒ„ ์‘๋‹ต ์‹œ๊ฐ„์ด ๋ˆˆ์— ๋„๊ฒŒ ๋Š๋ ค์ง€๋Š” ๊ฒƒ์— ๊ด€์‹ฌ์„ ๊ฐ–๊ธฐ ๋•Œ๋ฌธ์— ์„ฑ๋Šฅ์— ๋œ ๊ณต๊ฒฉ์ ์ด๋ผ๋ฉด์ด๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ผ๋ถ€ ๋Œ€๊ธฐ์—…๋“ค์—๊ฒŒ ์ธ๊ธฐ๊ฐ€ ์—†์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ผ๋ถ€ ์‚ฌ์ดํŠธ์—์„œ ๋ฌธ์ œ๊ฐ€๋˜์ง€ ์•Š์•˜๋‹ค๋ฉด ์‚ฌ๋žŒ๋“ค์€ React์˜ ์ŠคํŠธ๋ฆฌ๋ฐ ๋ Œ๋”๋Ÿฌ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  (๊ทธ๋ฆฌ๊ณ  ๊ฐœ์„ ์„ ๊ฐ„์ ˆํžˆ ๊ธฐ๋‹ค๋ฆฌ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค) ๋‘ ๊ฐœ์˜ ๋ Œ๋”๋ง์ด ์™„๋ฃŒ๋˜๊ธฐ ์ „์— ์‘๋‹ต์„ ์‹œ์ž‘ํ•˜์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

CDN์€ ์‘๋‹ต์„ ์บ์‹œ ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ๋งŽ์€ ๊ฐœ์ธํ™” / ๋กœ๊ทธ์ธ ์˜ต์…˜์„ ์ œ๊ฑฐํ•ฉ๋‹ˆ๋‹ค (์ ์ค‘๋ฅ ์„ ๋†’์ด๊ฑฐ๋‚˜ ํด๋ผ์ด์–ธํŠธ์— ๋Œ€ํ•œ ๋ถ€๋ถ„ ํŽ˜์ด์ง€ ๋ Œ๋”๋ง์„ ์—ฐ๊ธฐํ•˜๋ ค๋Š” ์ •๋„์™€์˜ ์ƒ์ถฉ ๊ด€๊ณ„์ด๊ธฐ ๋•Œ๋ฌธ์—). ์ „์ฒด ์•ฑ์„ CDN ์บ์‹œ ํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด CRA ๋ฐ react-snapshot ํ•˜๊ณ  ์„œ๋ฒ„๋ฅผ ์™„์ „ํžˆ ํ”ผํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ์„œ๋ฒ„๊ฐ€ ์–ผ๋งˆ๋‚˜ ๋งŽ์€ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š”์ง€์— ๋Œ€ํ•œ ์งˆ๋ฌธ์ด ์•„๋‹ˆ๋ผ ์š”์ฒญ์— ์‘๋‹ตํ•˜๋Š” ๋ฐ ๊ฑธ๋ฆฌ๋Š” ์‹œ๊ฐ„์ž…๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  Apollo๋Š” Relay์™€ ๊ฐ™์€๋ณด๋‹ค ๋…๋‹จ์ ์ด๊ณ  ์„ฑ๋Šฅ ์ง€ํ–ฅ์  ์ธ ํ”„๋ ˆ์ž„ ์›Œํฌ์— ๋น„ํ•ด ์„ฑ๋Šฅ๋ณด๋‹ค ์‚ฌ์šฉ ํŽธ์˜์„ฑ์„ ๊ฐ•์กฐํ•˜๋Š” ํ”„๋ ˆ์ž„ ์›Œํฌ์˜ ํ›Œ๋ฅญํ•œ ์˜ˆ์ž…๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์€ ๋ชจ๋‘ ์ŠคํŽ™ํŠธ๋Ÿผ์ž…๋‹ˆ๋‹ค.

๋„ค, ์ถฉ๋ถ„ํžˆ ๊ณตํ‰ํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋‚˜๋Š” remix.run์ด ์–ด๋–ป๊ฒŒ ๋ฐํ˜€ ์กŒ๋Š”์ง€ ๊ถ๊ธˆํ•ฉ๋‹ˆ๋‹ค. ์•„๋งˆ๋„ ๊ทธ๋“ค์€ react-router ์™€ ํ•จ๊ป˜ ์ž‘๋™ํ•˜๋„๋ก ์ƒˆ๋กœ์šด ์ ‘๊ทผ ๋ฐฉ์‹์„ ์ œ์‹œ ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋„ค, ์ค‘์ฒฉ ๋œ ๊ฒฝ๋กœ๊ฐ€ ํ•„์ˆ˜๋Š” ์•„๋‹ˆ์ง€๋งŒ, ๊ฒฝ๋กœ์— ๋”ฐ๋ผ ๋‚ด๋ถ€ UI์˜ ์ผ๋ถ€๋ฅผ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒƒ์ด ๋‹ค๋ฅธ ํŽ˜์ด์ง€๋ฅผ ๊ฐ€์ง€๊ณ  ๊ฐ ํŽ˜์ด์ง€๋ฅผ ๋‹ค๋ฅธ ๋ ˆ์ด์•„์›ƒ์œผ๋กœ ๋ž˜ํ•‘ํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ๋” ์ง๊ด€์ ์ด๋ผ๋Š” ๋ฐ ๋™์˜ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

๋‹ค์Œ 9.3๋กœ, ๊ฑฐ๊ธฐ์— getStaticPaths ์— ์ถ”๊ฐ€๋กœ getServerSideProps ๋„์›€์— ํ”„๋ ˆ์ž„ ์›Œํฌ๋Š” ๊ฒฝ๋กœ๊ฐ€ ๋ฃจํŠธ ๋งค๊ฐœ ๋ณ€์ˆ˜๊ฐ€์žˆ๋Š” ๊ฒฝ์šฐ ๊ฒฝ๋กœ๊ฐ€ ๋ฏธ๋ฆฌ ๋ Œ๋”๋งํ•˜๋Š” ๋ฐœ๊ฒฌ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. react-router๋กœ ๋น„์Šทํ•œ ์ ‘๊ทผ ๋ฐฉ์‹์„ ์ทจํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

@merryweather : "Next๋Š” ์„ฑ๋Šฅ์„ ์—ผ๋‘์—๋‘๊ณ  ๊ตฌ์ถ•๋˜์—ˆ์œผ๋ฉฐ, ์„œ๋ฒ„ ์ธก react-router๋Š” ๋ Œ๋”๋ง ํ•  ๋Œ€์ƒ์„ ์•Œ๊ธฐ ์ „์— DOM ํŠธ๋ฆฌ๋ฅผ ์‚ดํŽด ๋ด์•ผํ•œ๋‹ค๋Š” ์ ์—์„œ ์„ฑ๋Šฅ์— ํฐ ์˜ํ–ฅ์„ ๋ฏธ์นฉ๋‹ˆ๋‹ค."

์ˆœ์ง„ํ•œ ์งˆ๋ฌธ : ํด๋ผ์ด์–ธํŠธ์—์„œ ์ฝ”๋“œ๊ฐ€ ์‹คํ–‰๋˜๋ฉด ์ตœ์ƒ์œ„ ๋งํฌ๋ฅผ ๋ Œ๋”๋งํ•˜๊ณ  ๊ฐ€์ ธ ์˜ค๊ธฐ / ํ”„๋ฆฌ ํŽ˜์น˜ / ์บ์‹œ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ? ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์–ด๋””๋ฅผ ํƒ์ƒ‰ํ• ์ง€ ๋ชจ๋ฅด๋Š” ๊ฒฝ์šฐ ์„œ๋ฒ„์—์„œ DOM ํŠธ๋ฆฌ๋ฅผ ํƒ์ƒ‰ํ•˜๋Š” ๊ฒƒ์ด ํ•ฉ๋ฆฌ์ ์ž…๋‹ˆ๊นŒ?

์ˆœ์ง„ํ•œ ์ž‘์—… ์‹œ๋‚˜๋ฆฌ์˜ค : ํด๋ผ์ด์–ธํŠธ๊ฐ€ URL์„ ์š”์ฒญํ•˜๋ฉด ์ตœ์ƒ์œ„ ๋งํฌ์™€ ๊ธฐ๋ณธ ํ™œ์„ฑ ๋งํฌ ์ฝ˜ํ…์ธ ๋ฅผ ๋ Œ๋”๋งํ•˜๊ณ  ์š”์ฒญ์‹œ ๋‹ค๋ฅธ ๋ชจ๋“  ํ•ญ๋ชฉ์„ ajax / ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค (๋˜๋Š” ํŽ˜์ด์ง€๊ฐ€๋กœ๋“œ๋˜๋ฉด ๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ ํ”„๋ฆฌ ํŽ˜์น˜). ๋‹ค๋ฅธ ๋ชจ๋“  ํ•ญ๋ชฉ์—๋Š” ํ•˜์œ„ ์ˆ˜์ค€์ด ๋ชจ๋‘ ํฌํ•จ๋ฉ๋‹ˆ๋‹ค. ๊ฒฝ๋กœ ... ํ—น๊ตฌ๊ณ  ๋ฐ˜๋ณต ...?

@laurencefass ๊ทธ๋Ÿฌ๋‚˜ ์ตœ์ƒ์œ„ ๋งํฌ์กฐ์ฐจ๋„ ์ฝ”๋“œ์— ์žˆ์œผ๋ฉฐ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ๋ฐœ๊ฒฌํ•ด์•ผํ•ฉ๋‹ˆ๊นŒ? ์•„๋‹ˆ๋ฉด react-router์™€ ํ•จ๊ป˜ ํŒŒ์ผ ์‹œ์Šคํ…œ ๋ผ์šฐํŒ…์„ ์‚ฌ์šฉํ•˜์—ฌ ์ตœ์ƒ์œ„ ๋งํฌ๋ฅผ ์ฐพ์„ ์ˆ˜ ์žˆ๋„๋ก ํ•˜์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ?

@ avin-kavish Im์€ ๊ตฌํ˜„์— ๋Œ€ํ•œ ์„ธ๋ถ€ ์ •๋ณด์— ๋Œ€๋‹ตํ•˜๋Š” ๊ฐ€์žฅ ์ข‹์€ ์‚ฌ๋žŒ์€ ์•„๋‹ˆ์ง€๋งŒ ํด๋ผ์ด์–ธํŠธ์—์„œ๋Š” ์ดˆ๊ธฐ ํ™”๋ฉด ์ฝ˜ํ…์ธ  (์ตœ์ƒ์œ„ ๋งํฌ + ๊ธฐ๋ณธ ์ฝ˜ํ…์ธ ) ๋งŒ ๋ Œ๋”๋งํ•˜๋ฉด๋ฉ๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ๊ฒƒ์€ ๋‚ด๊ฐ€ ์ƒ๊ฐํ•˜๋Š” ์ฒซ ๋ฒˆ์งธ๋กœ๋“œ์—์„œ ์ค‘๋ณต๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋ ‡๋‹ค๋ฉด ์™œ ์„œ๋ฒ„์—์„œ DOM์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๊นŒ?

Next.js์˜ ์ฃผ์š” ๋ฌธ์ œ๋Š” ๋ผ์šฐํ„ฐ๊ฐ€ ์•„๋‹ˆ๋ผ getInitialProps , getServerProps ๋˜๋Š” getStaticProps ์˜ ๋ฐ์ดํ„ฐ ๊ฐ€์ ธ ์˜ค๊ธฐ ํŒจํ„ด์ž…๋‹ˆ๋‹ค. ์™œ ? ํ•„์š”ํ•œ ๊ตฌ์„ฑ ์š”์†Œ์— ๋Œ€ํ•œ ๋ฐ์ดํ„ฐ ๊ฒฉ๋ฆฌ๋ฅผ ์ค‘๋‹จํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๋ฉ”๋‰ด์— ๋Œ€ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ ์˜ค๋ ค๋Š” ๊ฒฝ์šฐ ์–ด๋””์—์„œ ๊ฐ€์ ธ ์˜ค๊ฒ ์Šต๋‹ˆ๊นŒ? ๋ชจ๋ฅด๊ฒ ์–ด์š”. pages ์™€ ๊ฐ™์€ ์ƒ์œ„ ๊ตฌ์„ฑ ์š”์†Œ๋Š” ๊ทธ๊ฒƒ์— ๋Œ€ํ•ด ์•„๋ฌด๊ฒƒ๋„ ์•Œ์ง€ ๋ชปํ•ฉ๋‹ˆ๋‹ค.

Next.js์˜ ์ฃผ์š” ๋ฌธ์ œ๋Š” ๋ผ์šฐํ„ฐ๊ฐ€ ์•„๋‹ˆ๋ผ getInitialProps , getServerProps ๋˜๋Š” getStaticProps ์˜ ๋ฐ์ดํ„ฐ ๊ฐ€์ ธ ์˜ค๊ธฐ ํŒจํ„ด์ž…๋‹ˆ๋‹ค. ์™œ ? ํ•„์š”ํ•œ ๊ตฌ์„ฑ ์š”์†Œ์— ๋Œ€ํ•œ ๋ฐ์ดํ„ฐ ๊ฒฉ๋ฆฌ๋ฅผ ์ค‘๋‹จํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๋ฉ”๋‰ด์— ๋Œ€ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ ์˜ค๋ ค๋Š” ๊ฒฝ์šฐ ์–ด๋””์—์„œ ๊ฐ€์ ธ ์˜ค๊ฒ ์Šต๋‹ˆ๊นŒ? ๋ชจ๋ฅด๊ฒ ์–ด์š”. pages ์™€ ๊ฐ™์€ ์ƒ์œ„ ๊ตฌ์„ฑ ์š”์†Œ๋Š” ๊ทธ๊ฒƒ์— ๋Œ€ํ•ด ์•„๋ฌด๊ฒƒ๋„ ์•Œ์ง€ ๋ชปํ•ฉ๋‹ˆ๋‹ค.

์ž์„ธํžˆ ์„ค๋ช…ํ•ด ์ฃผ์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ? ๋Œ€์ฒด ์†”๋ฃจ์…˜์€ ๋ฌด์—‡์ž…๋‹ˆ๊นŒ?

@lishine ์—ฌ๊ธฐ์—์„œ ์•ฝ๊ฐ„์˜ ์ฃผ์ œ๋ฅผ ๋ฒ—์–ด๋‚œ ๊ฒƒ์— ๋Œ€ํ•ด ์ฃ„์†กํ•˜์ง€๋งŒ ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ ๋ผ์šฐํ„ฐ๊ฐ€ ์—ฌ๊ธฐ์—์„œ ์ฃผ์š” ๋ฌธ์ œ๋ผ๋Š” ๊ฒƒ์„ ์•Œ์ง€ ๋ชปํ•ฉ๋‹ˆ๋‹ค. Next.js ๋ผ์šฐํ„ฐ๋Š” ํ›Œ๋ฅญํ•˜๊ณ  ์„ ์–ธ์ ์ด๋ฉฐ ๊ตฌ์„ฑ์— ๋Œ€ํ•œ ๊ทœ์น™์ด ์ข‹์Šต๋‹ˆ๋‹ค. Next.js์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜์—†๋Š” ์œ ์ผํ•œ ๊ฒƒ์€ getInitialProps , ...์™€ ๊ฐ™์€ ๋ฐ์ดํ„ฐ ๊ฐ€์ ธ ์˜ค๊ธฐ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.
๋‚ด ์•ฑ์—์„œ ๊ฐ ๊ตฌ์„ฑ ์š”์†Œ๋Š” graphql ๋˜๋Š” rest์— ๊ด€๊ณ„์—†์ด ๋™์ผํ•œ ์œ„์น˜, ๋™์ผํ•œ ํŒŒ์ผ์—์„œ ์ž์ฒด ๋ฐ์ดํ„ฐ๋ฅผ ์„ ์–ธํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.
์ƒ์œ„ ํŽ˜์ด์ง€ ๊ตฌ์„ฑ ์š”์†Œ๋Š” ํ•˜์œ„ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ๊ตฌ์„ฑํ•˜๊ธฐ์œ„ํ•œ ๊ฒƒ์ด๋ฉฐ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ ์˜ค๋Š” ๊ฒƒ์€ ์ž‘์—…์ด ์•„๋‹™๋‹ˆ๋‹ค. ์ž์‹ ๊ตฌ์„ฑ ์š”์†Œ๋Š” ๋ถ€๋ชจ๊ฐ€ ์•„๋‹Œ ์ž์ฒด ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์™€์•ผํ•ฉ๋‹ˆ๋‹ค.

๋ช…ํ™•์„ฑ์„ ์œ„ํ•ด ์•ฑ์— ์‚ฌ์šฉํ•˜๋Š” ์ฝ”๋“œ ์ƒ˜ํ”Œ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

const query = `
{
  result:users(
    where:{
      _and:[{
        active:{
          _eq:true
        }
      }, {
        is_exam_manager:{
          _eq:true
        }
      }]
    },
    order_by:{
      created_at:desc_nulls_last
    }
  ){
    id
    key:id
    user_code
    first_name
    last_name
    password
    active
  }
}
`
const Main = (props: any) => {
  const {
    data: { result }
  } = props
  return (
    <div>
      <Add title={'Add user'} role={'exam_manager'} />
      <Table
        columns={columns}
        dataSource={result}
        bordered={true}
        size={'small'}
      />
    </div>
  )
}
const MainWithData = graphql(query)(Main)
export default MainWithData

๋ณด์‹œ๋‹ค์‹œํ”ผ ์ž์ฒด ๋ฐ์ดํ„ฐ๊ฐ€์žˆ๋Š” ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ํ•˜๋‚˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์›ํ•˜๋Š” ๊ณณ์— ๋‘˜ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฌผ๋ก  Next.js ํŒจํ„ด์„ ์•„๋ฌด ๋ฌธ์ œ์—†์ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ์ œ ๊ฒฝ์šฐ์—๋Š” ๋‚˜์ค‘์— ์‰ฝ๊ฒŒ ์œ ์ง€ ๊ด€๋ฆฌํ•˜๊ณ  ๋ฆฌํŒฉํ† ๋งํ•˜๊ธฐ ์œ„ํ•ด ๊ฐ€๋Šฅํ•œ ํ•œ ๋ฐ์ดํ„ฐ ๋ฐ ๊ตฌ์„ฑ ์š”์†Œ์— ๋Œ€ํ•œ ๊ฒฉ๋ฆฌ๋ฅผ ์„ ํ˜ธํ•ฉ๋‹ˆ๋‹ค.

๋‚ด ์•ฑ์—์„œ ๊ฐ ๊ตฌ์„ฑ ์š”์†Œ๋Š” graphql ๋˜๋Š” rest์— ๊ด€๊ณ„์—†์ด ๋™์ผํ•œ ์œ„์น˜, ๋™์ผํ•œ ํŒŒ์ผ์—์„œ ์ž์ฒด ๋ฐ์ดํ„ฐ๋ฅผ ์„ ์–ธํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.
์ƒ์œ„ ํŽ˜์ด์ง€ ๊ตฌ์„ฑ ์š”์†Œ๋Š” ํ•˜์œ„ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ๊ตฌ์„ฑํ•˜๊ธฐ์œ„ํ•œ ๊ฒƒ์ด๋ฉฐ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ ์˜ค๋Š” ๊ฒƒ์€ ์ž‘์—…์ด ์•„๋‹™๋‹ˆ๋‹ค. ์ž์‹ ๊ตฌ์„ฑ ์š”์†Œ๋Š” ๋ถ€๋ชจ๊ฐ€ ์•„๋‹Œ ์ž์ฒด ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์™€์•ผํ•ฉ๋‹ˆ๋‹ค.

์ €๋„ ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
๋”ฐ๋ผ์„œ SSR ๊ฐ€์ ธ ์˜ค๊ธฐ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
๊ทธ๋ ‡๋‹ค๋ฉด ์‚ฌ๋žŒ๋“ค์€ ์‹ค์ œ๋กœ Next.js๋กœ SSR ๊ฐ€์ ธ ์˜ค๊ธฐ๋ฅผ ์–ด๋–ป๊ฒŒ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๊นŒ?!

@linshine ์šฐ๋ฆฌ๋Š” ์ตœ์ƒ์œ„ ํŽ˜์ด์ง€ ์ˆ˜์ค€์—์„œ ํ•„์š”ํ•œ ๊ฒƒ์„ ๋‹ค์šด๋กœ๋“œํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

@lishine ์—ฌ๊ธฐ์—์„œ ์•ฝ๊ฐ„์˜ ์ฃผ์ œ๋ฅผ ๋ฒ—์–ด๋‚œ ๊ฒƒ์— ๋Œ€ํ•ด ์ฃ„์†กํ•˜์ง€๋งŒ ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ ๋ผ์šฐํ„ฐ๊ฐ€ ์—ฌ๊ธฐ์—์„œ ์ฃผ์š” ๋ฌธ์ œ๋ผ๋Š” ๊ฒƒ์„ ์•Œ์ง€ ๋ชปํ•ฉ๋‹ˆ๋‹ค. Next.js ๋ผ์šฐํ„ฐ๋Š” ํ›Œ๋ฅญํ•˜๊ณ  ์„ ์–ธ์ ์ด๋ฉฐ ๊ตฌ์„ฑ์— ๋Œ€ํ•œ ๊ทœ์น™์ด ์ข‹์Šต๋‹ˆ๋‹ค. Next.js์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜์—†๋Š” ์œ ์ผํ•œ ๊ฒƒ์€ getInitialProps , ...์™€ ๊ฐ™์€ ๋ฐ์ดํ„ฐ ๊ฐ€์ ธ ์˜ค๊ธฐ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.
๋‚ด ์•ฑ์—์„œ ๊ฐ ๊ตฌ์„ฑ ์š”์†Œ๋Š” graphql ๋˜๋Š” rest์— ๊ด€๊ณ„์—†์ด ๋™์ผํ•œ ์œ„์น˜, ๋™์ผํ•œ ํŒŒ์ผ์—์„œ ์ž์ฒด ๋ฐ์ดํ„ฐ๋ฅผ ์„ ์–ธํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.
์ƒ์œ„ ํŽ˜์ด์ง€ ๊ตฌ์„ฑ ์š”์†Œ๋Š” ํ•˜์œ„ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ๊ตฌ์„ฑํ•˜๊ธฐ์œ„ํ•œ ๊ฒƒ์ด๋ฉฐ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ ์˜ค๋Š” ๊ฒƒ์€ ์ž‘์—…์ด ์•„๋‹™๋‹ˆ๋‹ค. ์ž์‹ ๊ตฌ์„ฑ ์š”์†Œ๋Š” ๋ถ€๋ชจ๊ฐ€ ์•„๋‹Œ ์ž์ฒด ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์™€์•ผํ•ฉ๋‹ˆ๋‹ค.

๋ช…ํ™•์„ฑ์„ ์œ„ํ•ด ์•ฑ์— ์‚ฌ์šฉํ•˜๋Š” ์ฝ”๋“œ ์ƒ˜ํ”Œ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

...

๋ณด์‹œ๋‹ค์‹œํ”ผ ์ž์ฒด ๋ฐ์ดํ„ฐ๊ฐ€์žˆ๋Š” ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ํ•˜๋‚˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์›ํ•˜๋Š” ๊ณณ์— ๋‘˜ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฌผ๋ก  Next.js ํŒจํ„ด์„ ์•„๋ฌด ๋ฌธ์ œ์—†์ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ์ œ ๊ฒฝ์šฐ์—๋Š” ๋‚˜์ค‘์— ์‰ฝ๊ฒŒ ์œ ์ง€ ๊ด€๋ฆฌํ•˜๊ณ  ๋ฆฌํŒฉํ† ๋งํ•˜๊ธฐ ์œ„ํ•ด ๊ฐ€๋Šฅํ•œ ํ•œ ๋ฐ์ดํ„ฐ ๋ฐ ๊ตฌ์„ฑ ์š”์†Œ์— ๋Œ€ํ•œ ๊ฒฉ๋ฆฌ๋ฅผ ์„ ํ˜ธํ•ฉ๋‹ˆ๋‹ค.

@ revskill10 ์ž์‹์ด ๋ฐ์ดํ„ฐ ์กฐ๊ฐ์„ ์„ ์–ธํ•˜๊ณ  ๋ถ€๋ชจ๊ฐ€ ์ตœ์ƒ์œ„ ์ฟผ๋ฆฌ์— ํ•ด๋‹น ์กฐ๊ฐ์„ ํฌํ•จํ•˜๋„๋ก ํ•  ์ˆ˜์—†๋Š” ์ด์œ ๋Š” ๋ฌด์—‡์ž…๋‹ˆ๊นŒ? ํŠนํžˆ ํ•˜์œ„ ๊ด€๋ จ ์กฐ๊ฐ์„ ๋” ๋งŽ์ด ๋งŒ๋“ค๋ฉด ์™„๋ฒฝํ•œ ๋ฐ์ดํ„ฐ ๊ฒฉ๋ฆฌ๊ฐ€ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ์ž์‹ ์กฐ๊ฐ์ด์žˆ๋Š” ๋ถ€๋ชจ ์ฟผ๋ฆฌ๋ฅผ ๊ฐ–๋Š” ๊ฒƒ์€ JSX์—์„œ ์ž์‹์„ ์„ ์–ธํ•˜๋Š” ๊ฒƒ๊ณผ ๋‹ค๋ฅด์ง€ ์•Š์œผ๋ฏ€๋กœ ๋™์ผํ•œ ์ˆ˜์ค€์˜ ๊ฒฐํ•ฉ์„ ๊ฐ€์ง€์ง€ ๋งŒ ์š”์ฒญ ํญํฌ๋ฅผ ํ”ผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค (์Šฌํ”„๊ฒŒ๋„ REST์—์„œ๋Š” ํ›จ์”ฌ ๋” ์–ด๋ ต์Šต๋‹ˆ๋‹ค).

Relay-Next ์•ฑ์ด ์žˆ์œผ๋ฉฐ์ด ํŒจํ„ด์€ ๋ฐ์ดํ„ฐ ์บก์Šํ™” ๋ฐ ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๊ตฌ์„ฑ์œผ๋กœ ์™„๋ฒฝํ•˜๊ฒŒ ์ž‘๋™ํ•˜๋ฉฐ getInitialProps ๋ฅผ ์‰ฝ๊ฒŒ ํ™œ์šฉํ•ฉ๋‹ˆ๋‹ค.

@merrywhether much harder in REST ์— ๋Œ€ํ•ด์„œ๋Š” ๋งํ•  ๊ฒƒ๋„์—†๊ณ , ์ ‘๊ทผ ๋ฐฉ์‹์— ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์–ด๋–ค fragments ๊ฐ€ SSG / SSR์ด ๋ ์ง€ ์•„๋‹ˆ๋ฉด CSR์ด ๋ ์ง€ ๊ฒฐ์ •ํ•  ์ˆ˜ ์—†๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
๋‚ด ์ ‘๊ทผ ๋ฐฉ์‹์—์„œ๋Š” { noSSR: true/false} ํ•ด๋‹น ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ๊ฐ€์ ธ ์˜ค๋Š” ๊ฒƒ๋งŒ ํผ ์‰ฝ์Šต๋‹ˆ๋‹ค.

์ฃผ์š” ๋ผ์šฐํŒ… ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์™€ ๊ธฐ๋ณธ ๊ตฌํ˜„์„ ๊ณต์œ ํ•˜์ง€ ์•Š๋Š” ๊ณต๊ธ‰ ์—…์ฒด๋ณ„ ๋ผ์šฐํŒ… ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ๋Œ€ํ•œ ์ข…์†์€ ๋งค์šฐ ์šฐ๋ ค๋˜๋Š” ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค.

์ตœ๊ทผ์— Next.js๋ฅผ ๊ฒ€ํ† ํ•˜์—ฌ ํ˜„์žฌ ํด๋ผ์ด์–ธํŠธ๋ฅผ ์œ„ํ•ด ๊ตฌ์ถ•๋˜๋Š” ์—ฌ๋Ÿฌ ํ”„๋ŸฐํŠธ ์—”๋“œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜๊ฐ„์— ๊ณต์œ ๋˜๋Š” ๊ณตํ†ต ์ฝ”์–ด์˜ ๊ธฐ๋ฐ˜์œผ๋กœ ์‚ฌ์šฉํ•ด์•ผํ•˜๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ํ‰๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค. Next.js์—๋Š” ์ž ์žฌ๋ ฅ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๋ผ์šฐํ„ฐ๋Š” ๋‚ด๊ฐ€ Next.js๋ฅผ ๊ฑฐ๋ถ€ํ•˜๊ณ  ๋Œ€์‹  CRA๋ฅผ ์ด๋Ÿฌํ•œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๊ธฐ๋ฐ˜์œผ๋กœ ์œ ์ง€ํ•˜๊ฒŒ ๋œ ์ฃผ์š” ์ด์œ  ์ค‘ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค.

react-router / @reach/router ์˜ ๊ตฌ์„ฑ ์š”์†Œ ๊ธฐ๋ฐ˜ ์ตœ์ƒ์œ„ API๋ฅผ SSR์˜ ๊ธฐ๋ฐ˜์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์–ด๋ ค์›€์„ ์ดํ•ดํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ด๊ฒƒ์ด ๊ธฐ๋ณธ ๊ตฌํ˜„์ด ์™„์ „ํžˆ ๋งž์ถคํ™” ๋œ ์ด์œ ๋Š” ์•„๋‹™๋‹ˆ๋‹ค. Gatsby์˜ SSG๋Š” Next.js์™€ ๊ฐ™์€ ๊ด€์‹ฌ์‚ฌ๋ฅผ ๊ฐ–๊ณ  ์žˆ์œผ๋ฉฐ ํŒŒ์ผ ๊ธฐ๋ฐ˜ ๋ผ์šฐํŒ… ๊ตฌ์กฐ์— ์ค€ ์œ ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๋‚ด ์ดํ•ด์— Gatsby๋Š” ํœ ์„ ์žฌ๋ฐœ ๋ช…ํ•˜๊ฑฐ๋‚˜ ๋‹ค๋ฅธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ ์‚ฌ์šฉํ•˜๋Š” Link API์™€ ์ผ์น˜ํ•˜์ง€ ์•Š๋Š” Link API๋ฅผ ๋…ธ์ถœํ•˜๋Š” ๋Œ€์‹  ๋ผ์šฐํŒ… ๊ตฌํ˜„์„ ๊ฐ•ํ™”ํ•˜๊ธฐ ์œ„ํ•ด ํ›„๋“œ ์•„๋ž˜์—์„œ @reach/router ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

@dantman Next.js ๋Œ€์•ˆ์œผ๋กœ ๋ฌด์—‡์„ ์„ ํƒํ–ˆ๋Š”์ง€ ๋ฌผ์–ด๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์„œ๋ฒ„ ์ธก ๋ Œ๋”๋ง์ด ํ•„์š”ํ•˜๋‹ค๊ณ  ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค .... ์ €๋Š” After.js๋ฅผ ์‚ฌ์šฉํ•ด ๋ณด์•˜์Šต๋‹ˆ๋‹ค. Zeit์—์„œ ์ง€์›ํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ Next.js์—์„œ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•œ ์˜๊ฐ / ์•„์ด๋””์–ด๋ฅผ ์ œ๊ณต ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

@dantman Next.js ๋Œ€์•ˆ์œผ๋กœ ๋ฌด์—‡์„ ์„ ํƒํ–ˆ๋Š”์ง€ ๋ฌผ์–ด๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์„œ๋ฒ„ ์ธก ๋ Œ๋”๋ง์ด ํ•„์š”ํ•˜๋‹ค๊ณ  ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค .... ์ €๋Š” After.js๋ฅผ ์‚ฌ์šฉํ•ด ๋ณด์•˜์Šต๋‹ˆ๋‹ค. Zeit์—์„œ ์ง€์›ํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ Next.js์—์„œ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•œ ์˜๊ฐ / ์•„์ด๋””์–ด๋ฅผ ์ œ๊ณต ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ฃ„์†กํ•ฉ๋‹ˆ๋‹ค. ๋„์›€์ด๋˜๋Š” ๋‹ต๋ณ€์ด ์—†์Šต๋‹ˆ๋‹ค. SSR์€ ์–ด๋ ค์šด ์š”๊ตฌ ์‚ฌํ•ญ์ด ์•„๋‹ˆ์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ํ”„๋กœํ†  ํƒ€์ž…์— ์‚ฌ์šฉ ๋œ CRA๋ฅผ ๊ณ„์† ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.

Next.js๋Š” ์ตœ๊ทผ์— SSR / SSG / ํด๋ผ์ด์–ธํŠธ ์ „์šฉ ํŽ˜์ด์ง€๋ฅผ ํ˜ผํ•ฉํ•˜๊ณ  ๋™ํ˜• ์•ฑ ๋˜๋Š” ์ •์  / PWA ์•ฑ์œผ๋กœ ์‹คํ–‰ํ•  ์ˆ˜์žˆ๋Š” ๊ธฐ๋Šฅ์„ ์–ป์—ˆ ๊ธฐ ๋•Œ๋ฌธ์— ๋ฒ”์šฉ ํ”„๋ ˆ์ž„ ์›Œํฌ๋กœ์„œ์˜ ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ์Šต๋‹ˆ๋‹ค. WebPack ์‚ฌ์šฉ์ž ์ •์˜๋Š” CRA๊ฐ€ globalize-compiler๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์–ด๋ ต๊ฒŒ ๋งŒ๋“ค๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์œ ํ˜น์ ์ด์—ˆ์Šต๋‹ˆ๋‹ค. Next.js ์„œ๋ฒ„๋Š” GraphQL / REST ๋ธŒ๋ฆฌ์ง€๋ฅผ์œ„ํ•œ API ์„œ๋ฒ„๊ฐ€ ํ•„์š”ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ค‘๋ฆฝ์  / ๊ธ์ •์ ์ด์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  SSR / SSG์˜ ์˜ต์…˜์€ ๊ธ์ •์ ์ด์—ˆ์Šต๋‹ˆ๋‹ค. ํ•ต์‹ฌ์„ ๊ตฌ์ถ• ํ•  ๋•Œ 6 ๊ฐœ์˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ๊ธฐ๋ฐ˜์„๋‘๊ณ  ์žˆ์œผ๋ฉฐ ๋ฏธ๋ž˜์— ์œ ์šฉ ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์€ ๋ถˆ๊ฐ€๋Šฅํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ Next.js์˜ SSR์ด ์ž‘๋™ํ•˜๋Š” ๋ฐฉ์‹์—๋„ ๋ช‡ ๊ฐ€์ง€ ๋ฌธ์ œ๊ฐ€ ์žˆ์—ˆ์œผ๋ฉฐ ์ด๋Ÿฌํ•œ ๊ธ์ •์  ์ธ ์ ์€ ๋ผ์šฐํ„ฐ๋กœ ์ธํ•œ ๋ฌธ์ œ์˜ ๊ฐ€์น˜๊ฐ€ ์—†์—ˆ์Šต๋‹ˆ๋‹ค.

@dantman

์ฃผ์š” ๋ผ์šฐํŒ… ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์™€ ๊ธฐ๋ณธ ๊ตฌํ˜„์„ ๊ณต์œ ํ•˜์ง€ ์•Š๋Š” ๊ณต๊ธ‰ ์—…์ฒด๋ณ„ ๋ผ์šฐํŒ… ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ๋Œ€ํ•œ ์ข…์†์€ ๋งค์šฐ ์šฐ๋ ค๋˜๋Š” ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค.

๋›ฐ์–ด๋‚œ ์•ˆ์ •์„ฑ๊ณผ "์ œํ’ˆ / ์‹œ์žฅ ์ ํ•ฉ์„ฑ"์œผ๋กœ ์ธํ•ด 3 ๋…„ ๋™์•ˆ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์€ API๋กœ ์˜คํ”ˆ ์†Œ์Šค ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ "์ž ๊ธˆ"์œผ๋กœ ํ•œ์ •ํ•˜๋Š” ๊ฒƒ์€ ๋งค์šฐ ์ด์ƒํ•ฉ๋‹ˆ๋‹ค.

Next.js๋Š” ์„ฑ๊ณต ํ–ˆ์œผ๋ฉฐ ๋ผ์šฐํ„ฐ ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ 

๋งŽ์€ ์‚ฌ๋žŒ๋“ค์ด ์ œ๊ฐ€ ํŠธ์œ„ํ„ฐ์— ๋Œ“๊ธ€์„๋‹ค๋Š” ๊ฒƒ์„ ๋ณด์•˜ ๋“ฏ์ด, ์˜›๋‚ ์— ์šฐ๋ฆฌ๋Š” ์ผ๋ถ€ ๋ผ์šฐํ„ฐ์—์„œ ๋ณ‘ํ•ฉํ•˜๋Š” ๊ฒƒ์„ ์ง„์ง€ํ•˜๊ฒŒ ์ฆ๊ฒผ์Šต๋‹ˆ๋‹ค (ํ•˜์ง€๋งŒ Reach ๋˜๋Š” React Router ์ค‘ ์–ด๋Š ๊ฒƒ์ด ํ‘œ์ค€์ธ์ง€, ์–ด๋–ค ์ฃผ์š” ๋ฒ„์ „์ธ์ง€ ํ˜ผ๋ž€ ์Šค๋Ÿฝ์ง€๋งŒ). ๊ทธ๋Ÿฌ๋‚˜ ์„ธ์ƒ์€ ์šฐ๋ฆฌ๋ฅผ ๋‹ค๋ฅธ ํฅ๋ฏธ๋กœ์šด ๋ฐฉํ–ฅ์œผ๋กœ ์ด๋Œ์—ˆ์Šต๋‹ˆ๋‹ค. ์‹ค์ œ๋กœ ๋ชจ๋“  ์‚ฌ๋žŒ๋“ค์ด Next.js๋กœ ๊ณ„์† ์„ฑ๊ณตํ•˜๊ณ  ๋ฉ‹์ง„ ์ œํ’ˆ์„ ๊ตฌ์ถ•ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ์‹ค์ œ๋กœ ์ถ”๊ฐ€์˜ ์š”์ ์ด ๋ฌด์—‡์ธ์ง€ ๋ชฐ๋ž์Šต๋‹ˆ๋‹ค.

๋‹ค๋ฅธ ๋ผ์šฐํ„ฐ API๋ฅผ ์›ํ•˜๋Š” ์ด์œ ๋ฅผ ์‚ฌ๋žŒ๋“ค์—๊ฒŒ ์‹ค์ œ๋กœ ๋ฌผ์–ด๋ณผ ๋•Œ ๊ฐ€์žฅ ์ž์ฃผ ๋“ฑ์žฅํ•˜๋Š” ์ด์œ ๋Š” ์‚ฌ๋žŒ๋“ค์ด ๋ผ์šฐํ„ฐ์— ๊ตฌ์ถ• ๋œ ์ž์ฒด ๊ฐœ๋ฐœ ํ”„๋ ˆ์ž„ ์›Œํฌ ์†”๋ฃจ์…˜์— ๊ฐ‡ํ˜€ ์žˆ๊ณ  ๋ถˆ๋งŒ์Šค๋Ÿฌ์›Œ์„œ Next๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ํ•˜๊ธฐ๋ฅผ ๊ธฐ๋‹ค๋ฆด ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. . ์ œํ’ˆ ๋””์ž์ธ์— ๋ฟŒ๋ฆฌ๋ฅผ ๋‘” ์ด์œ ๊ฐ€ ์•„๋‹ˆ ์—ˆ์Šต๋‹ˆ๋‹ค.

Next๊ฐ€ ๋ผ์šฐํ„ฐ ๋•๋ถ„์— ์„ฑ๊ณตํ–ˆ๋‹ค๊ณ  ๋งํ•˜๋ฉด ๋‘ ๊ฐ€์ง€ ๋ฌธ์ œ๊ฐ€ ์ œ๊ฑฐ ๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.
1๏ธโƒฃ ๋ผ์šฐํ„ฐ๋ฅผ ์„ ํƒํ•ด์•ผํ•œ๋‹ค๋Š” ์ƒ๊ฐ . ์ด๊ฒƒ์„ ์ œ๊ฑฐํ•˜๋Š” ๊ฒƒ์€ ๋Œ์ด์ผœ ๋ณด๋ฉด ํ›Œ๋ฅญํ•œ ๊ฒฐ์ •์ž…๋‹ˆ๋‹ค. ์•ˆ์ •์ ์ธ ๋ผ์šฐํ„ฐ๋ฅผ ๊ฐ–์ถ˜ Next.js๊ฐ€ ์กด์žฌํ•˜๋Š” ๋™์•ˆ ๋ผ์šฐํ„ฐ ์„ธ๊ณ„๋Š” ๋ถ„์—ด๋˜์–ด ๋ชจ๋“  ์ข…๋ฅ˜์˜ API ๋ณ€๊ฒฝ์„ ์‹œ์ž‘ํ–ˆ์Šต๋‹ˆ๋‹ค.

2๏ธโƒฃ ๋ผ์šฐํ„ฐ์˜ ํ•™์Šต ๊ณก์„  . ๋ผ์šฐํŒ…์— ๋Œ€ํ•œ ๋งŽ์€ ์›Œํฌ์ƒต๊ณผ ์ž์Šต์„œ๊ฐ€ ์ œ๊ณต๋˜์—ˆ์ง€๋งŒ Next.js ํŒŒ์ผ ์‹œ์Šคํ…œ ์šฐ์„  ๋ผ์šฐํŒ…์€ ์„ค๋ช…ํ•˜๋Š” ๋ฐ 2 โ€‹โ€‹์ดˆ๊ฐ€ ๊ฑธ๋ฆฌ๋ฉฐ ๋†€๋ผ์šด ๊ฒƒ์„ ๋นŒ๋“œ ํ•  ์ˆ˜์žˆ๋Š” ํ”Œ๋žซํผ์„ ์ œ๊ณตํ•˜๋ฉฐ ์ œํ’ˆ ๊ฐœ๋ฐœ๋กœ ๋ฐ”๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค.

์ด ๋งˆ์ง€๋ง‰ ์š”์ ์„ ๊ฐ•์กฐํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. Next.js์— ๊ตฌ์ถ• ๋œ ์„ธ๊ณ„์—์„œ ๊ฐ€์žฅ ๋น ๋ฅด๊ฒŒ ์„ฑ์žฅํ•˜๋Š” ์ตœ์‹  ์›น ์‚ฌ์ดํŠธ ์ค‘ ํ•˜๋‚˜ ์ธ TikTok.com์„ ๊ณ ๋ คํ•ด๋ณด์„ธ์š”. ํ•ด๋‹น ์›น ์‚ฌ์ดํŠธ์˜ ์ „์ฒด ๋ผ์šฐํŒ… ํ† ํด๋กœ์ง€๋Š” 2 ์ดˆ ํ•™์Šต ๊ณก์„ ์œผ๋กœ ์„ค๋ช… ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. https://www.tiktok.com/@sheezus.christ/video/6824007862197439750 ์€ pages/[user]/video/[id].js ์ด๊ณ  https://www.tiktok.com/trending ์€ pages/trending.js

ํ•˜์ด๋ธŒ๋ฆฌ๋“œ ์ •์  / SSG / SSR๊ณผ ๊ฐ™์ด ๊ท€ํ•˜๊ฐ€ ์–ธ๊ธ‰ ํ•œ ์ตœ๊ทผ Next.js ํ˜์‹  ์ค‘ ์ƒ๋‹น์ˆ˜๋Š” ๋ผ์šฐํ„ฐ ์„ค๊ณ„๋ฅผ ํ†ตํ•ด ํ™œ์„ฑํ™”๋ฉ๋‹ˆ๋‹ค. ์‚ฌ์‹ค, ๋ผ์šฐํ„ฐ๋Š” ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ๋” ์ ์€ JS๋ฅผ ์ œ๊ณตํ•˜๊ธฐ ์œ„ํ•ด ์•ž์œผ๋กœ ๋‚˜์˜ฌ ๋‹ค๋ฅธ ๋งŽ์€ ์œ ์‚ฌํ•œ ์ตœ์ ํ™”๋ฅผ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ Next.js์˜ SSR์ด ์ž‘๋™ํ•˜๋Š” ๋ฐฉ์‹์—๋„ ๋ช‡ ๊ฐ€์ง€ ๋ฌธ์ œ๊ฐ€ ์žˆ์—ˆ์œผ๋ฉฐ ์ด๋Ÿฌํ•œ ๊ธ์ •์  ์ธ ์ ์€ ๋ผ์šฐํ„ฐ๋กœ ์ธํ•œ ๋ฌธ์ œ์˜ ๊ฐ€์น˜๊ฐ€ ์—†์—ˆ์Šต๋‹ˆ๋‹ค.

์ด๊ฒƒ์— ๋Œ€ํ•ด ๋“ฃ๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. ์œ„์˜ ์˜ˆ์ œ๋Š” Next.js ํ•˜์ด๋ธŒ๋ฆฌ๋“œ ์ •์  / SSR๋กœ ๊ตฌ๋™๋˜๋ฉฐ ์ „๋ฐ˜์ ์œผ๋กœ ๋งŽ์€ ์„ฑ๊ณต์„ ๊ฑฐ๋‘์—ˆ์Šต๋‹ˆ๋‹ค!

์ด๊ฒƒ์€ ์ •๋ง ์žฌ๋ฏธ์žˆ๋Š” ์Šค๋ ˆ๋“œ์ž…๋‹ˆ๋‹ค. Next๋Š” ํญํฌ ๋ผ์šฐํŒ… (react-router ๋ฐ ์นœ๊ตฌ๋ผ๊ณ ๋„ ํ•จ)์„ ํ”ผํ•ด์•ผํ•˜๋Š” ๊ตฌ์ฒด์ ์ธ ์ด์œ ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. getInitialProps ๋Š” ๋งŽ์€ ์„ฑ๋Šฅ ์ตœ์ ํ™”๋ฅผ ๊ฐ€๋Šฅํ•˜๊ฒŒํ•˜๊ณ , ํŠนํžˆ ์ผ๋ถ€ ์‚ฌ๋žŒ๋“ค์ด ํŠน๋ณ„ํžˆ ์ด๋Ÿฌํ•œ ์ตœ์ ํ™”๋ฅผ ์›ํ•˜๊ธฐ ๋•Œ๋ฌธ์— Next์˜ ์ ‘๊ทผ ๋ฐฉ์‹์€ ๊ฝค ์ธ๊ธฐ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์„ฑ๋Šฅ์€ ๋””์ž์ธ ํŠธ๋ ˆ์ด๋“œ ์˜คํ”„์™€ ํ•จ๊ป˜ ์ œ๊ณต๋˜๋ฉฐ ๋•Œ๋กœ๋Š” ์„ฑ๋Šฅ๋ณด๋‹ค ๋””์ž์ธ์„ ์„ ํƒํ•˜๋Š” ๊ฒƒ์„ ์„ ํ˜ธ ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ๋„๊ตฌ๊ฐ€ ์ž˜๋ชป๋˜๋Š” ๊ฒƒ์€ ์•„๋‹ˆ๋ฉฐ ํŠน์ • ํ”„๋กœ์ ํŠธ์— ๋Œ€ํ•ด ์ž˜๋ชป๋œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ถ๊ทน์ ์œผ๋กœ react-router๋Š” ๋ชจ๋“  ๋ผ์šฐํŒ… ์†”๋ฃจ์…˜์ด ์•„๋‹™๋‹ˆ๋‹ค. Next์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์žฅ๋‹จ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค. FWIW, Facebook์€ react-router๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์œผ๋ฉฐ ์•„๋งˆ๋„ React ์‚ฌ์šฉ์— ๋Œ€ํ•ด ํ•œ๋‘ ๊ฐ€์ง€๋ฅผ ์•Œ๊ณ ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋Œ€์•ˆ์ด์žˆ๋Š” ๊ฒƒ์€ ๊ดœ์ฐฎ์Šต๋‹ˆ๋‹ค. ์‹ค์ œ๋กœ JS ์ƒํƒœ๊ณ„์˜ ๊ฐ€์žฅ ํฐ ์žฅ์  ์ค‘ ํ•˜๋‚˜๋Š” ์•„์ด๋””์–ด์˜ ์˜์—ญ์—์„œ ์„œ๋กœ ๋‹ค๋ฅธ ์š”์†Œ๊ฐ€ ๊ฒฝ์Ÿํ•˜๊ฒŒํ•˜๊ณ  ๊ถ๊ทน์ ์œผ๋กœ ์šฐ๋ฆฌ ๋ชจ๋‘๊ฐ€ ์•ž์œผ๋กœ ๋‚˜์•„๊ฐˆ ์ˆ˜ ์žˆ๋„๋กํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋ฌธ์ œ๋ฅผ ๋งˆ๋ฌด๋ฆฌํ•˜๋Š” ์ค‘์ด๋ฏ€๋กœ ๋ผ์šฐํŒ… ๊ธฐ๋Šฅ์— ๋Œ€ํ•œ ์˜๊ฒฌ, ๊ธฐ๋Šฅ ์š”์ฒญ ๋ฐ ๋ฒ„๊ทธ ๋ณด๊ณ ์„œ์— ํ•ญ์ƒ ์—ด๋ ค ์žˆ์Œ์„ ๋ถ„๋ช…ํžˆํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.

์ด์ƒ์ ์œผ๋กœ๋Š” ์ œํ’ˆ ์ค‘์‹ฌ์ ์ธ ๊ฒƒ์ž…๋‹ˆ๋‹ค ( "X๋ฅผํ•ด์•ผํ•˜์ง€๋งŒ ๋ถˆ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค"๋˜๋Š” "Y๋Š” ๊ฐ€๋Šฅํ•˜์ง€๋งŒ ์ธ์ฒด ๊ณตํ•™์ ์ด์ง€ ์•Š์Œ"). ์šฐ๋ฆฌ๋Š” ํ•ญ์ƒ ํ›Œ๋ฅญํ•œ ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์œผ๋กœ ๋ฆฐ ์›น ์‚ฌ์ดํŠธ์™€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋งŒ๋“œ๋Š” ๋ฐ ๋„์›€์ด๋˜๋Š” ๊ฐœ์„  ์‚ฌํ•ญ์„ ์ฐพ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค ๐Ÿค—

@rauchg ๋งํฌ ์— href ๋ฐ as ๋‘ ๊ฐœ์˜ ์†Œํ’ˆ์ด์žˆ๋Š” ์ด์œ ๋ฅผ ์„ค๋ช…ํ•ด ์ฃผ์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ? as prop์˜ ๊ฐ’์„ ๊ธฐ๋ฐ˜์œผ๋กœ ์˜๋„ ํ•œ ํŽ˜์ด์ง€๋ฅผ ์ถ”๋ก  ํ•  ์ˆ˜์—†๋Š” ์ด์œ ๋Š” ๋ฌด์—‡์ž…๋‹ˆ๊นŒ?

ํ‘œํ˜„์˜ ์˜ˆ๋ฅผ ๋“ค์–ด ๋‚ด๊ฐ€ ๊ฐ™์€ ๊ฒฝ๋กœ๊ฐ€์žˆ๋Š” ๊ฒฝ์šฐ /blog/:slug , ๋‚œ ๊ทธ๋ƒฅ์— HTTP ์š”์ฒญ์„ ๋ณด๋‚ผ ์ˆ˜ /blog/hello-world ํ•˜๊ณ  ๊ทธ๊ฒƒ์— ๋ฐœ ๋ผ์šฐํ„ฐ๋ฅผ ๊ธฐ๋Œ€ํ•ฉ๋‹ˆ๋‹ค. /blog/:slug ์™€ blog/hello-world ๋ฅผ ๋ชจ๋‘ ์„œ๋ฒ„๋กœ ๋ณด๋‚ผ ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

@ avin-kavish ์ข‹์€ ์งˆ๋ฌธ์ž…๋‹ˆ๋‹ค. URL์— ํ‘œ์‹œ๋˜๋Š” ๋‚ด์šฉ๊ณผ๋กœ๋“œ ํ•  ํŽ˜์ด์ง€ ์‚ฌ์ด์—๋Š” ์ค‘์š”ํ•œ ์ฐจ์ด๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์‚ฌ์‹ค TikTok์€์ด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํŠน์ • ํ•ญ๋ชฉ์„ ๋ชจ๋‹ฌ๋กœ ๋ Œ๋”๋งํ•˜๋ฏ€๋กœ ํŽ˜์ด์ง€๋ฅผ ์ƒˆ๋กœ ๊ณ ์น˜๋ฉด ๋‹ค๋ฅธ ํŽ˜์ด์ง€๊ฐ€๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์—ฌ๊ธฐ์„œ ํ•œ ๊ฐ€์ง€ ํฐ ๊ฐœ์„  ์˜์—ญ์€ ํŒŒ์ผ ์‹œ์Šคํ…œ์—์žˆ๋Š” ์œ ํšจํ•œ ํŽ˜์ด์ง€๋ฅผ ์ฐธ์กฐํ•˜๋„๋ก ์ •์ ์œผ๋กœ ์ ์šฉํ•ด์•ผํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด์— ๋Œ€ํ•œ ํ† ๋ก ์„ ๋งŒ๋“ค๊ณ  ํƒœ๊ทธ๋ฅผ ์ง€์ •ํ•˜์—ฌ ํ›„์† ์กฐ์น˜๋ฅผ ์ทจํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค!

https://github.com/zeit/next.js/issues/8207์— ๋Œ€ํ•œ ๋ฌธ์ œ๊ฐ€ ์ด๋ฏธ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

๋ˆ„๊ตฐ๊ฐ€๊ฐ€ ๋‚˜์ฒ˜๋Ÿผ ๋ชจ๋“  ๊ฒƒ์„ ๋‹ค์‹œ ๋ Œ๋”๋งํ•˜์ง€ ์•Š๊ณ  ์ƒˆ ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•  ์ˆ˜์žˆ๋Š” "์ค‘์ฒฉ ๋œ ๊ฒฝ๋กœ"๊ธฐ๋Šฅ๊ณผ ๊ฐ™์€ ๋ฐ˜์‘ ๋ผ์šฐํ„ฐ๋กœ์ด ๋ฌธ์ œ๋ฅผ ๋ณธ ๊ฒฝ์šฐ ์‹ค์ œ๋กœ๋ณด๊ณ  ํˆฌํ‘œ ํ•  ์ˆ˜์žˆ๋Š” ์ „์šฉ ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‚˜๋Š” ๋ฐฉ๊ธˆ ๊ทธ๊ฒƒ์— ๋Œ€ํ•ด ์•Œ์•„ ๋ƒˆ์Šต๋‹ˆ๋‹ค : https://github.com/zeit/next.js/issues/8193

ํ—‰

์ด ๋‚ด ๊ธฐ๋ณธ ๋ฌธ์ œ์—์„œ ๋ช…ํ™•ํ•˜๊ฒŒํ•˜๊ธฐ ์œ„ํ•ดํ•˜๋Š” ๊ฒƒ์€ RR / ๋„๋‹ฌ ์Šคํƒ€์ผ์˜ ๊ตฌ์„ฑ ์š”์†Œ API์˜ ๋ถ€์กฑ ์•„๋‹ˆ๋‹ค, ๋‚˜๋Š” SSR ์ˆ˜์žˆ๋Š” ํŒŒ์ผ / ์„ค์ • ๊ธฐ๋ฐ˜์˜ API์™€ ์ž˜์ž…๋‹ˆ๋‹ค. ๋‚˜๋Š” ๋ฏธ๋ž˜์— Suspense๊ฐ€ ๋Œ€์ฒด SSR / ๋ผ์šฐํŒ… API๋ฅผ ์‹คํ–‰ ๊ฐ€๋Šฅํ•˜๊ฒŒ ๋งŒ๋“ค ์ˆ˜์žˆ์„ ๊ฒƒ์ด๋ผ๊ณ  ์•ฝ๊ฐ„ ๋‚™๊ด€์ ์ด์ง€๋งŒ. ๋‚ด ์ฃผ์š” ๋ฌธ์ œ๋Š” ๋ผ์šฐํ„ฐ๊ฐ€ ๋” ๋„“์€ React ์ปค๋ฎค๋‹ˆํ‹ฐ์˜ ์ผ๋ถ€์™€ ๊ณต์œ ํ•˜๋Š” ๋Œ€์‹  ๋‹ค์‹œ ๊ตฌํ˜„๋˜๋Š” ๊ตฌํ˜„์— ๋Œ€ํ•œ ์ผ๋ฐ˜์ ์ธ ๋ฌธ์ œ๋กœ ์™„์ „ํžˆ ์‚ฌ์šฉ์ž ์ง€์ •๋œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋‚˜๋Š” Gatsby์˜ ์ ‘๊ทผ ๋ฐฉ์‹์ด ์ˆ˜์šฉ ๊ฐ€๋Šฅํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. SSG ๊ฐ€๋Šฅ ํŒŒ์ผ + ๊ตฌ์„ฑ ๊ธฐ๋ฐ˜ ๋ผ์šฐํŒ… API๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์œผ๋ฉฐ ์ž์ฒด ํ–ฅ์ƒ๋œ ๋งํฌ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ๋‚ด ๋ณด๋ƒ…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๊ทธ๋“ค์€ @reach/router ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ธฐ๋ณธ ๊ตฌํ˜„์„ ๊ฐ•ํ™”ํ•ฉ๋‹ˆ๋‹ค.

์ฃผ์š” ๋ผ์šฐํŒ… ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์™€ ๊ธฐ๋ณธ ๊ตฌํ˜„์„ ๊ณต์œ ํ•˜์ง€ ์•Š๋Š” ๊ณต๊ธ‰ ์—…์ฒด๋ณ„ ๋ผ์šฐํŒ… ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ๋Œ€ํ•œ ์ข…์†์€ ๋งค์šฐ ์šฐ๋ ค๋˜๋Š” ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค.

๋›ฐ์–ด๋‚œ ์•ˆ์ •์„ฑ๊ณผ "์ œํ’ˆ / ์‹œ์žฅ ์ ํ•ฉ์„ฑ"์œผ๋กœ ์ธํ•ด 3 ๋…„ ๋™์•ˆ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์€ API๋กœ ์˜คํ”ˆ ์†Œ์Šค ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ "์ž ๊ธˆ"์œผ๋กœ ํ•œ์ •ํ•˜๋Š” ๊ฒƒ์€ ๋งค์šฐ ์ด์ƒํ•ฉ๋‹ˆ๋‹ค.

๋ผ์šฐํ„ฐ๋Š” ๋ณธ์งˆ์ ์œผ๋กœ Next.js์— ์—ฐ๊ฒฐ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ํ•œ ๊ฐ€์ง€ ์ด์œ ๋กœ Next.js๋ฅผ ์ฑ„ํƒํ•œ๋‹ค๋Š” ๊ฒƒ์€ ๋ผ์šฐํ„ฐ์— ๋ฌถ์—ฌ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. Next.js๋ฅผ ์ฑ„ํƒํ•˜๊ณ  ๋‚˜์ค‘์— next / router์— ์šฐ๋ฆฌ๊ฐ€ํ•˜๋ ค๋Š” ์ผ์„ ๋ฐฉํ•ดํ•˜๋Š” ํ•œ๊ณ„๊ฐ€ ์žˆ์Œ์„ ๋ฐœ๊ฒฌํ•˜๋ฉด ํ•ฉ๋ฆฌ์ ์ธ ํƒˆ์ถœ ํ•ด์น˜๊ฐ€ ์ „ํ˜€ ์—†์Šต๋‹ˆ๋‹ค. "Lock-in"์€ ๊ทธ๊ฒƒ์— ๋Œ€ํ•œ ์™„๋ฒฝํ•œ ์„ค๋ช…์ž…๋‹ˆ๋‹ค.

๋ฝ์ธ๋งŒ์œผ๋กœ๋Š” ํฐ ๋ฌธ์ œ๊ฐ€๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. Gatsby์˜ @reach/router ๋„ ์ข…์†๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ @reach/router ๋Š” Gatsby ์™ธ๋ถ€์—์„œ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ์ „์ฒด ๋ผ์šฐํ„ฐ ์Šคํƒ์„ ์œ ์ง€ํ•˜๊ธฐ ์œ„ํ•ด Gatsby ์ปค๋ฎค๋‹ˆํ‹ฐ ๋งŒ ์‹ ๋ขฐํ•  ํ•„์š”๋Š” ์—†์Šต๋‹ˆ๋‹ค. ๋‚˜๋Š” ๋” ํฐ ์ปค๋ฎค๋‹ˆํ‹ฐ๊ฐ€ ๊ทธ๊ฒƒ์— ์˜์กดํ•˜๊ณ  ๋” ๋งŽ์€ ์ดํ•ด ๊ด€๊ณ„์ž๊ฐ€ (๋ผ์šฐํŒ… ์Šคํƒ์— ํŠน์ •ํ•œ) ๊ด€๋ จ๋˜์–ด ์œ ์ง€๋˜๊ณ , ์–ด๋ ค์šด ๋ผ์šฐํŒ… ๋ฌธ์ œ (์˜ˆ : ์ ‘๊ทผ์„ฑ)๋ฅผ ๋”ฐ๋ผ ์žก์œผ๋ฉฐ, ๋” ๋‹ค์–‘ํ•œ ์ปค๋ฎค๋‹ˆํ‹ฐ์— ์˜์กดํ•˜๊ณ  ์žˆ๋‹ค๊ณ  ๋ฏฟ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์•ž์œผ๋กœ ๋ฐœ์ƒํ•  ์ˆ˜์žˆ๋Š” ์ž ์žฌ์ ์œผ๋กœ ์‹ฌ๊ฐํ•œ ๋ฌธ์ œ๋ฅผ ๊ณต์œ  ํ•  ๊ฐ€๋Šฅ์„ฑ์ด ๋†’์Šต๋‹ˆ๋‹ค.

์–ด๋–ค ๊ฒƒ์ด ๋‹น์‹ ์˜ ๋งˆ์Œ ์†์—์žˆ๋Š” ํ‘œ์ค€, Reach ๋˜๋Š” React Router, ๊ทธ๋ฆฌ๊ณ  ์–ด๋–ค ์ฃผ์š” ๋ฒ„์ „์ธ์ง€ ํ˜ผ๋ž€ ์Šค๋Ÿฝ์ง€๋งŒ

<Link> ์˜ ์‹ค์งˆ์ ์ธ ํ‘œ์ค€ ์ธก๋ฉด์—์„œ. Reach์™€ React Router (RR)๋Š” ๋ชจ๋‘ ๋งค์šฐ ์œ ์‚ฌํ•œ API๋ฅผ ๊ณต์œ ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด <Link to='/about'>About</Link> ๋Š” RR๊ณผ Reach ๋ชจ๋‘์—์„œ ์œ ํšจํ•ฉ๋‹ˆ๋‹ค (๋ฌผ๋ก  ํ™•์žฅ Gatsby). ์ด๊ฒƒ์€ Next.js์˜ ํŠน์ดํ•œ <Link href='/about'><a>About</a></Link> ๋ฅผ ํ›จ์”ฌ ๋” ์–ด๋ฆฌ๋‘ฅ์ ˆํ•˜๊ฒŒ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

Next.js๊ฐ€ ์‚ฌ์šฉํ•ด์•ผํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•˜๋Š” ์ธก๋ฉด์—์„œ. Next.js๊ฐ€ ์ด๋ฏธ ํ•˜๋‚˜๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋‹ค๋ฉด ํŠน์ • ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ๋ฌถ์—ฌ ์žˆ์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค. ๋‚ด ์ฃผ์š” ๊ด€์‹ฌ์‚ฌ๋Š” ๋ผ์šฐํŒ… ๊ตฌํ˜„์ด Next.js ์™ธ๋ถ€์˜ ๋” ๋„“์€ ์ปค๋ฎค๋‹ˆํ‹ฐ์™€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์™€ ๊ณต์œ ๋œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์‹ค์ œ๋กœ ๊ทธ๊ฒƒ์€ ์ƒ๋Œ€์ ์œผ๋กœ ๋…ผ์Ÿ์˜ ์—ฌ์ง€๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ง€๊ธˆ๊นŒ์ง€ ๋Œ€๊ทœ๋ชจ ์‚ฌ์šฉ์ž ๊ธฐ๋ฐ˜์˜ RR ๋ฐ Reach ์™ธ์—๋Š” React ๋ผ์šฐํ„ฐ๋ฅผ ๋ณด์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  RR๊ณผ Reach๋Š” ํ•˜๋‚˜์˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ๋  ๊ฒƒ์ด๋ฏ€๋กœ ์ตœ์ข… ๊ฒฐ๊ณผ๋กœ ์‹œ์ž‘ํ•˜๋Š” ๊ฒƒ์ด ๋™์ผํ•ฉ๋‹ˆ๋‹ค.

์–ผ๋งˆ ์ „์— Next๋ฅผ ์‹œ๋„ํ–ˆ์ง€๋งŒ ๋ผ์šฐํ„ฐ์˜ ์œ ์—ฐ์„ฑ์ด ๋ถ€์กฑํ•˜์—ฌ After.js https://github.com/jaredpalmer/after.js?utm_source=hashnode.com ์ด๋ผ๋Š” Razzle ๊ตฌํ˜„์„ ๋ฐœ๊ฒฌํ–ˆ์Šต๋‹ˆ๋‹ค

React Router๋Š” ๋‹จ์ง€ ํŒจํ‚ค์ง€์ด๋ฏ€๋กœ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์—†์œผ๋ฉฐ ๋ Œ๋”๋ง์„ ํด๋ผ์ด์–ธํŠธ ์ธก์œผ๋กœ ๋งŒ ์ œํ•œํ•˜์—ฌ ํ•„์š”ํ•œ ๊ณณ์—์„œ SPA์ฒ˜๋Ÿผ ์ž‘๋™ํ•˜๊ณ  ์ค‘์ฒฉ ๋œ ๊ตฌ์„ฑ ์š”์†Œ ๊ฒฝ๋กœ๋ฅผ ์ œ๊ณต ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ? React ๋ผ์šฐํ„ฐ๋Š” ํŽ˜์ด์ง€์— (์ž ์žฌ์ ์œผ๋กœ) ํฌํ•จ๋˜๊ณ  ๋‹ค๋ฅธ ๊ตฌ์„ฑ ์š”์†Œ์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ Next.js ํŽ˜์ด์ง€ ๋ผ์šฐํ„ฐ์™€ ํ•จ๊ป˜๋กœ๋“œ๋˜๋Š” ๊ตฌ์„ฑ ์š”์†Œ ์ง‘ํ•ฉ ์ผ ๋ฟ์ž…๋‹ˆ ๊นŒ?

zeit์ด RR์„ ํ†ตํ•ฉ ํ•  ๊ณ„ํš์ด๋ผ๋Š” ์ด์ „ ์Šค๋ ˆ๋“œ๋ฅผ ์ฝ์—ˆ๋Š”๋ฐ ์˜ค๋Š˜๋‚ ์—๋„ ์—ฌ์ „ํžˆ ์‚ฌ์‹ค์ž…๋‹ˆ๊นŒ?

์ตœํ›„์˜ ์ˆ˜๋‹จ์œผ๋กœ next.js ๋ผ์šฐํ„ฐ์— ์ค‘์ฒฉ ๋œ ๊ฒฝ๋กœ๋ฅผ ํ—ˆ์šฉํ•˜์ง€ ์•Š๋Š” ์ด์œ ๋Š” ๋ฌด์—‡์ด๋ฉฐ ์ด๋Ÿฌํ•œ ์˜์—ญ์ด ์‚ฌ์ „ ๋ Œ๋”๋ง๋˜์ง€ ์•Š์„ ๊ฒƒ์ž„์„ ๋ถ„๋ช…ํžˆํ•ฉ๋‹ˆ๋‹ค. ์ตœ์†Œํ•œ ๊ฒฝ๋กœ์— ๋”ฐ๋ผ ํŽ˜์ด์ง€์˜ ํ•˜์œ„ ๋ฆฌ์†Œ์Šค๊ฐ€ ๋ณ€๊ฒฝ๋˜๊ธฐ๋ฅผ ์›ํ•  ๋•Œ ํ•„์—ฐ์ ์œผ๋กœ ์ž‘์„ฑํ•ด์•ผํ•˜๋Š” if ์กฐ๊ฑด์„ ์ž‘์„ฑํ•˜์ง€ ์•Š์œผ๋ ค๋Š” ๋…ธ๋ ฅ์„ ์ ˆ์•ฝ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ๋ฌธ์ œ์— ๋Œ€ํ•œ ํˆฌํ‘œ๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

์–ธ๊ธ‰๋˜์ง€ ์•Š์€ ๋˜ ๋‹ค๋ฅธ ํ”„๋กœ๋Š” RR์ด ๋” ํ…Œ์ŠคํŠธ ๊ฐ€๋Šฅํ•˜๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. (AFAIK๋Š” ๋ผ์šฐํ„ฐ ํ…Œ์ŠคํŠธ๋ฅผ์œ„ํ•œ ๊ณต์‹ nextjs API๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค) ํ…Œ์ŠคํŠธ ๋ฐ ์Šคํ† ๋ฆฌ๋ฅผ ๋ž˜ํ•‘ํ•˜๊ธฐ์œ„ํ•œ MemoryRouter๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

Next.js์—๋Š” ๋งŽ์€ ์ข‹์€ ๊ธฐ๋Šฅ (์ž๋™ WebPack, ์ •์  ํŒŒ์ผ ๋ฐ CRA์™€ ๊ฐ™์€ TypeScript๊ฐ€ ์žˆ์ง€๋งŒ PWA, API ๊ฒฝ๋กœ, ์„œ๋ฒ„๋ฆฌ์Šค ์ง€์›, ๋น ๋ฅธ ์ƒˆ๋กœ ๊ณ ์นจ, ์›น + ๋„ค์ดํ‹ฐ๋ธŒ ์•ฑ์— ๋Œ€ํ•œ ์‹คํ—˜์ ์ธ Expo ์ง€์›)๊ณผ ์ฝ”์–ด๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. API๊ฐ€ ํ›Œ๋ฅญํ•˜์ง€ ์•Š๋”๋ผ๋„ SSR ๋ฐ SSG ์šฉ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋‚ด์žฅ ๋ผ์šฐํŒ… ์‹œ์Šคํ…œ๊ณผ SSR / SSG๊ฐ€ ์ผ๋ถ€๋ฅผ ์œ„ํ•ด ์ž‘๋™ํ•˜๋Š” ๋™์•ˆ; ๋‹ค๋ฅธ ์‚ฌ๋žŒ๋“ค์—๊ฒŒ๋Š” ๋‘ API์˜ ํ•œ๊ณ„๊ฐ€ ํ•ด๋‹น ํ”„๋กœ์ ํŠธ์— ๋Œ€ํ•ด ์ž˜๋ชป๋œ ํŠธ๋ ˆ์ด๋“œ ์˜คํ”„๋ฅผ ์ œ๊ณตํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๊ฐœ๋ฐœ์„ ๋ฐฉํ•ดํ•ฉ๋‹ˆ๋‹ค.

ํƒ€ํ˜‘์€ ์–ด๋–ป์Šต๋‹ˆ๊นŒ. Next.js์—๋Š” ์ด๋ฏธ ํ”Œ๋Ÿฌ๊ทธ์ธ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋ผ์šฐํ„ฐ๋ฅผ ๋‚ด๋ถ€์ ์œผ๋กœ ๊ต์ฒดํ•˜๋Š” ๋Œ€์‹  Next.js์˜ ์ฝ”์–ด์—์„œ ๋ผ์šฐํ„ฐ์™€ SSR API (์˜ˆ : ๊ฒฝ๋กœ ํŒŒ์ผ์˜ getStaticProps / getServerSideProps )๋ฅผ ๋ถ„๋ฆฌํ•˜๋ฉด ์–ด๋–จ๊นŒ์š”? ์˜ˆ๋ฅผ ๋“ค์–ด ๋งค์šฐ ๊ธฐ๋ณธ์ ์ธ ํ•ต์‹ฌ ๋ถ€๋ถ„์„ @next/core ๋„ฃ๊ณ  ํ˜„์žฌ ์˜๊ฒฌ์ด์žˆ๋Š” ๋ผ์šฐํ„ฐ์™€ get*Props API๋ฅผ @next/router ๋กœ ์ด๋™ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹จ์ˆœ์„ฑ๊ณผ ์ด์ „ ๋ฒ„์ „๊ณผ์˜ ํ˜ธํ™˜์„ฑ์„ ์œ„ํ•ด next ๋Š” @next/core ๋ฅผ ๋‹ค์‹œ ๋‚ด๋ณด๋‚ด๊ณ  Vercel์ด ์„ ํ˜ธํ•˜๋Š” ๋ผ์šฐํ„ฐ๋กœ ๋ฏธ๋ฆฌ ๊ตฌ์„ฑ๋˜์–ด ์ œ๊ณต๋˜๋Š” ํ”„๋ ˆ์ž„ ์›Œํฌ๊ฐ€ ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ปค๋ฎค๋‹ˆํ‹ฐ๊ฐ€ Next.js์˜ ์ข‹์€ ๋ถ€๋ถ„์„ ๋ชฉ์š•๋ฌผ๊ณผ ํ•จ๊ป˜ ๋ฒ„๋ ค์•ผํ•˜๋Š” ํ”„๋กœ์ ํŠธ์— ๋” ์ ํ•ฉํ•œ ์„œ๋กœ ๋‹ค๋ฅธ ์ ˆ์ถฉ์•ˆ์œผ๋กœ ๋ผ์šฐํ„ฐ ๋ฐ SSR / SSG API๋ฅผ ๊ฐœ๋ฐœํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€๋Šฅํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

Next.js ์ฝ”์–ด๊ฐ€ ์ œ๊ณตํ•˜๊ธฐ ์œ„ํ•ด ๋ผ์šฐํ„ฐ ํ”Œ๋Ÿฌ๊ทธ์ธ์ด ํ•„์š”ํ•œ ์‚ฌํ•ญ์— ๋Œ€ํ•œ ๋ช‡ ๊ฐ€์ง€ ์ƒ๊ฐ :

  • {url, body ๋“ฑ} ์š”์ฒญ์ด ์ฃผ์–ด์ง€๋ฉด ์ฝ”์–ด๋Š” ๋ผ์šฐํ„ฐ ํ”Œ๋Ÿฌ๊ทธ์ธ์ด์ด ์š”์ฒญ์„ ๋ฌธ์„œ (๋ฌธ์ž์—ด ๋˜๋Š” ์ŠคํŠธ๋ฆฌ๋ฐ)๋กœ ๋ Œ๋”๋งํ•˜๊ฑฐ๋‚˜ ์‘๋‹ต (์˜ˆ : 404 ๋˜๋Š” ๋ฆฌ๋””๋ ‰์…˜)์„ ๋˜์งˆ ๊ฒƒ์œผ๋กœ ์˜ˆ์ƒํ•ฉ๋‹ˆ๋‹ค.
  • ๋‚ด๋ณด๋‚ผ ๋•Œ ์ฝ”์–ด๋Š” ๋ผ์šฐํ„ฐ ํ”Œ๋Ÿฌ๊ทธ์ธ์ด ๋ Œ๋”๋งํ•ด์•ผํ•˜๋Š” ํŽ˜์ด์ง€ ๋ชฉ๋ก์„ ์ œ๊ณต ํ•  ๊ฒƒ์œผ๋กœ ์˜ˆ์ƒํ•ฉ๋‹ˆ๋‹ค.

@next/router ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜์—ฌ API๋ฅผ ํ†ตํ•ด ๋™์ผํ•œ ํŒจํ„ด์„ ๊ตฌํ˜„ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

  • ์š”์ฒญ์ด ์ฃผ์–ด์ง€๋ฉด ๋‹ด๋‹น ๊ฒฝ๋กœ ํŒŒ์ผ์„ ์‹๋ณ„ํ•˜๊ณ  ์ •์ƒ์ ์œผ๋กœ ๋ Œ๋”๋งํ•ฉ๋‹ˆ๋‹ค.
  • ํด๋ผ์ด์–ธํŠธ์—์„œ SSR API๋ฅผ ํ˜ธ์ถœ ํ• ์‹œ๊ธฐ๋ฅผ ์•Œ๊ณ  ํ•„์š”ํ•œ ๊ฒฝ๋กœ๋ฅผ ๋ Œ๋”๋งํ•˜๊ธฐ ์œ„ํ•ด ํ˜„์žฌ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ๊ณผ ์œ ์‚ฌํ•œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒฝ์šฐ (API ๊ธฐ๋ฐ˜ SSR API๋ฅผ ์ •์ƒ์ ์ธ API ๊ฒฝ๋กœ๋กœ ์ด๋™ํ•  ์ˆ˜ ์žˆ์Œ)
  • ํŽ˜์ด์ง€ ํŒŒ์ผ ํŠธ๋ฆฌ ๋ฐ getStaticPaths ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋‚ด๋ณด๋‚ด๊ธฐ์‹œ ์ •์  ํŽ˜์ด์ง€ ๋ชฉ๋ก ์ œ๊ณต

@apollo/react-ssr ์™€ ํ•จ๊ป˜ React Router v6์„ ์‚ฌ์šฉํ•˜๊ณ  react-ssr-prepass ๋˜๋Š” react@experimental ์™€ ํ•จ๊ป˜ Suspense๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ผ์šฐํ„ฐ ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์‹คํ—˜ํ•˜๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋™ํ˜• SSR ๊ฒฝ๋กœ์— ๋Œ€ํ•œ SSR ์ „์šฉ ๊ฒฝ๋กœ๋ฅผ ํฌ๊ธฐํ•˜๊ณ  get*Props ์Šคํƒ€์ผ API๋ฅผ ์ œํ•œํ•˜์ง€ ์•Š๊ณ  SSR / SSG๋ฅผ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค.

๋‚ด๊ฐ€ ๊นจ๋‹ฌ์€ ๊ฒƒ์€ ์ค‘์ฒฉ ๋ผ์šฐํŒ… + SSG๋ฅผ ํ˜„์žฌ API๋ฅผ ์†์ƒ์‹œํ‚ค์ง€ ์•Š๊ณ  ๋‹ฌ์„ฑ ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ํ˜„์žฌ getStaticPaths ๊ฐ€) ์žˆ์œผ๋ฏ€๋กœ์ด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์‚ฌ์ „ ๋ Œ๋”๋ง์„ ์œ„ํ•ด ์ค‘์ฒฉ ๋œ ๊ฒฝ๋กœ๋ฅผ ํžŒํŠธ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค๋ฉด

/foo/[...slug] ๊ฒฝ๋กœ๊ฐ€ ์ฃผ์–ด์ง€๋ฉด

function FooPage() {

  return (
      <Switch>
          <Route path="/foo/bar">
              <SomeResource />
              <Route path={`${parenthPath}/baz`} component={SomeSubResource} />
          </Route>
          .... more routes
      </Switch>
  )
}

๋ฏธ๋ฆฌ ๋ Œ๋”๋ง ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

export async function getStaticPaths() {

  return {
    paths: [
      { slug: [ 'bar' ] },
      { slug: [ 'bar', 'baz' ] },
    ],
  }
}

ํ˜„์žฌ ์ƒํ™ฉ์—์„œ next.js๋Š” ๋ฐ˜์‘ ํ˜• ํŽ˜์ด์ง€ ์ƒ์„ฑ์˜ ํŽธ์˜์„ฑ์„ ๊ฐ–์ถ˜ ์„œ๋ฒ„ ์ธก ํ”„๋ ˆ์ž„ ์›Œํฌ์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค. react-router ๋งŒํผ ๊ฐ•๋ ฅํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋””๋ ‰ํ† ๋ฆฌ ๊ธฐ๋ฐ˜ ๋ผ์šฐํŒ…์€ ์•ž์—์„œ ์–ธ๊ธ‰ํ–ˆ๋“ฏ์ด tiktok๊ณผ ๊ฐ™์€ ์†Œ๋น„์ž ๋Œ€๋ฉด ์‚ฌ์ดํŠธ๋ฅผ ๊ตฌ์ถ•ํ•˜๋Š” ๋ฐ ์ ํ•ฉ ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ๋ณต์žกํ•œ ๋ฐ์ดํ„ฐ ๊ธฐ๋ฐ˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ํฌํ„ธ์˜ ๊ฒฝ์šฐ ์ค‘์ฒฉ ๋ผ์šฐํŒ…์ด ์—ฌ์ „ํžˆ ์™•์ž…๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด ๋‹จ์ผ ํŽ˜์ด์ง€ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์ด ์ฒ˜์Œ์— ๋งŒ๋“ค์–ด์ง„ ์ด์œ ์ด๋ฉฐ ์ „์ฒด ํŽ˜์ด์ง€๋ฅผ ๊ต์ฒดํ•˜์ง€ ์•Š๊ณ ๋„ UI์˜ ์ผ๋ถ€๋ฅผ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ๋ฆฌ์†Œ์Šค-ํ•˜์œ„ ๋ฆฌ์†Œ์Šค ๊ด€๊ณ„๋ฅผ ๋งค์šฐ ํŽธ๋ฆฌํ•˜๊ฒŒ ๋ชจ๋ธ๋งํ•˜๋Š” ๋ฐ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ˜„์žฌ ์ „์ž ์ƒ๊ฑฐ๋ž˜ ์‚ฌ์ดํŠธ์™€ ๊ฐ™์€ ์†Œ๋น„์ž ์‚ฌ์ดํŠธ์˜ ๊ณต๊ฐœ ํŽ˜์ด์ง€๋ฅผ ๊ตฌ์ถ•ํ•˜๋ ค๋ฉด next.js ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ๊ด€๋ฆฌ์ž, ๊ตฌ๋งค์ž ๋ฐ ํŒ๋งค์ž ํฌํ„ธ๊ณผ ๊ฐ™์€ ๋น„๊ณต๊ฐœ ์˜์—ญ์„ ๊ตฌ์ถ•ํ•ด์•ผ ํ•  ๋•Œ๋Š” CRA๋กœ ์ „ํ™˜ํ•˜์‹ญ์‹œ์˜ค.

@ avin-kavish์˜ ์ฃผ์š” ๋ฌธ์ œ๋Š” ์ž‘๋™ํ•˜๋„๋ก ๋งŒ๋“œ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์ตœ์ ํ™”ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. Next.js ๊ธฐ๋ณธ์˜ ๊ฐ ํŽ˜์ด์ง€์—๋Š” ์ž์ฒด ๋ฒˆ๋“ค์ด ์žˆ์œผ๋ฉฐ ์†๋„์— ์ตœ์ ํ™”๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

ํ•œ ํŽ˜์ด์ง€์— ๋งŽ์€ ์ฝ˜ํ…์ธ  / ํ•˜์œ„ ์ฝ˜ํ…์ธ ๋ฅผ ์ถ”๊ฐ€ํ•˜๊ธฐ ์‹œ์ž‘ํ•˜๋ฉด ๊ฒฐ๊ตญ์—๋Š” ์ƒ๋‹นํžˆ ํฐ ๋ฒˆ๋“ค๋กœ ๋๋‚  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค (๊ทธ ์ž์ฒด๋กœ๋Š” "๋”์ฐํ•œ"๊ฒƒ์€ ์•„๋‹ˆ์ง€๋งŒ ์žฅ๋‹จ์ ). next/dynamic ์ƒ๊ฐ์œผ๋กœ ์ˆ˜๋™ ์ตœ์ ํ™”๋ฅผ ์ˆ˜ํ–‰ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. :)

@rauchg ์œ ์ผํ•œ ์ฐจ์›์€ ๋‹ค์Œ ๋ผ์šฐํ„ฐ๊ฐ€ ์ข‹์€์ง€ ๋‚˜์œ์ง€ ์—ฌ๋ถ€๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค. ๋˜ ๋‹ค๋ฅธ ๋งค์šฐ ์ค‘์š”ํ•œ ๊ฒƒ์€ next.js ๋ฐ ์ปค๋ฎค๋‹ˆํ‹ฐ ์ง€์›๊ณผ์˜ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์ด๋ฉฐ https://github.com/vercel/next.js/issues/1632#issuecomment -633310614๊ฐ€ ์ž˜ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค. Next.js๋Š” ๊ณ ํ’ˆ์งˆ SSR ์•ฑ์— ํ•„์š”ํ•œ ๋งŽ์€ ์ƒ์šฉ๊ตฌ๋ฅผ ์ถ”์ƒํ™” ํ•  ์ˆ˜์žˆ๋Š” ์ข‹์€ ์†”๋ฃจ์…˜์ด๋ฉฐ, ๋”ฐ๋ผ์„œ ๋งŽ์€ ์›น ์•ฑ์—์„œ ๋งค์šฐ ๋งค๋ ฅ์ ์ธ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ๋Œ€์ƒ์ž…๋‹ˆ๋‹ค. ํ˜„์žฌ ๋ฌธ์ œ๋Š” next.js๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ํ•˜๊ธฐ ์œ„ํ•ด ์™„์ „ํ•œ ๋ผ์šฐํŒ… ์žฌ ์ž‘์„ฑ์ด ํ•„์š”ํ•˜๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ด์ „์— @dantman์ด ์ œ์•ˆํ•œ ํ”Œ๋Ÿฌ๊ทธ ํ˜• ๋ผ์šฐํŒ…์€์ด ๋ฌธ์ œ๋ฅผ ๋งค์šฐ ์šฐ์•„ํ•œ ๋ฌธ์ œ๋กœ ํ•ด๊ฒฐํ•˜๊ณ  ๋ˆ„๊ตฌ์—๊ฒŒ๋„ ์›์น™์„ ํŒ๋งคํ•˜๋„๋ก ์š”๊ตฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค ๐Ÿ˜‰

react-router (๋ฐ ์ค‘์ฒฉ ๋ผ์šฐํŒ… ์†”๋ฃจ์…˜)์˜ ๋ฌธ์ œ๋Š” ์ฝ”๋“œ ์ž์ฒด๋ฅผ ์‹คํ–‰ (๋˜๋Š” ์‹œ๋ฎฌ๋ ˆ์ด์…˜)ํ•˜์ง€ ์•Š๊ณ ๋Š” ํŠน์ • URL์— ๋Œ€ํ•œ ๊ด€๋ จ ์ฝ”๋“œ ๊ฒฝ๋กœ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์— ์ •์  ๋ถ„์„์„ ํ›จ์”ฌ ์–ด๋ ต๊ฒŒ ๋งŒ๋“ ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋‹ค์Œ์€ ๋‹จ์ˆœํžˆ "์›น ํŽ˜์ด์ง€์— UI ๋ฐฐ์น˜"ํ”„๋ ˆ์ž„ ์›Œํฌ ์ด์ƒ์ž…๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด Chrome ํŒ€๊ณผ ํ˜‘๋ ฅํ•˜์—ฌ ๋”์šฑ ์ตœ์ ํ™” ๋œ ๋ฒˆ๋“ค๋ง ์ „๋žต์„ ๊ฐœ๋ฐœํ–ˆ์Šต๋‹ˆ๋‹ค.

react-router ์‚ฌ์šฉ์ž๋Š” ๊ทธ ์ฑ…์ž„์„ ์ตœ์ข… ์‚ฌ์šฉ์ž์—๊ฒŒ ์ „์ ์œผ๋กœ ์œ„์ž„ํ•˜๊ธฐ ๋•Œ๋ฌธ์— react-loadable์„ ์ง์ ‘ ์‚ฌ์šฉํ•˜๋Š” ๋ฐ ์ต์ˆ™ํ•˜์ง€๋งŒ Next๋Š” ์‰ฝ์ง€ ์•Š์€ ์ถ”์ƒํ™”์™€ ์ž๋™ํ™”๋ฅผ ์‹œ๋„ํ•ฉ๋‹ˆ๋‹ค. ์ œ์•ˆ ๋œ ํ”Œ๋Ÿฌ๊ทธ ํ˜• ๋ผ์šฐํ„ฐ ์ ‘๊ทผ ๋ฐฉ์‹์€ ๋™์ผํ•œ ์œ ํ˜•์˜ ์ถœ๋ ฅ์„ ์–ป๊ธฐ ์œ„ํ•ด ํ”„๋ ˆ์ž„ ์›Œํฌ์— ๊ด‘๋ฒ”์œ„ํ•œ ๋นŒ๋“œ ์‹œ๊ฐ„ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•˜๋Š” ๋ผ์šฐํ„ฐ ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ํฌํ•จํ•ด์•ผ ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋ชจ๋“  ๋ผ์šฐํ„ฐ๋Š” ์ž์ฒด ํŒจํ„ด์„ ๊ธฐ๋ฐ˜์œผ๋กœ ์ด๋Ÿฌํ•œ ์ •๋ณด๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ์•„์•ผํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

์ˆœ์ „ํžˆ ์ถ”์ธก์ด์ง€๋งŒ React๊ฐ€ Suspense๋ฅผ ์™„๋ฃŒํ•˜๋Š” ๋™์•ˆ ๋งŽ์€ ๊ฒƒ๋“ค์ด ๋ฆผ๋ณด์— ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ์ฒซ ๋ฒˆ์งธ ํด๋ž˜์Šค ํŒจํ„ด์ด ๋ชจ๋“  ๋ผ์šฐํ„ฐ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ํฐ ์˜ํ–ฅ์„ ๋ฏธ์น˜๊ณ  ๋น„๋™๊ธฐ /๋กœ๋“œ ๊ฐ€๋Šฅ ๋นŒ๋“œ๋ฅผ์œ„ํ•œ ๊ตฌ์ฒด์ ์ธ ๊ธฐ๋ฐ˜์„ ์ œ๊ณตํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋ฒˆ๋“ค ํŒจํ„ด.

์งง์€ ์ด์•ผ๊ธฐ / ์•„๋ž˜์— ๋Œ€ํ•œ ์ข‹์€ ์š”์•ฝ : "๋ชจ๋“  ์†”๋ฃจ์…˜์— ์ ํ•ฉํ•œ ๋‹จ์ผ ํฌ๊ธฐ"๋ผ๋Š” ๊ฒƒ์€ ์—†์Šต๋‹ˆ๋‹ค. ๋ชจ๋“  ๊ฒƒ์€ ์žฅ๋‹จ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค. Next.js๊ฐ€ ํ˜„์žฌํ•˜๋Š” ๋ฐฉ์‹์˜ ๋ชจ๋“  "์žฅ์ "์—๋Š” ๋‹จ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐ€์žฅ ์ค‘์š”ํ•œ ์žฅ์  / ๋‹จ์ ์€ ๊ฐ ํ”„๋กœ์ ํŠธ๋งˆ๋‹ค ๋‹ค๋ฆ…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ํ”Œ๋Ÿฌ๊ทธ ํ˜• ๋ผ์šฐํ„ฐ / ssg / ssr ์•„ํ‚คํ…์ฒ˜์— ๋Œ€ํ•œ ๊ถŒ์žฅ ์‚ฌํ•ญ์ž…๋‹ˆ๋‹ค. ํ”„๋กœ์ ํŠธ๋งˆ๋‹ค ๋‹ค๋ฅธ ๊ฒƒ์ด ํ•„์š”ํ•˜๋ฉฐ ํ˜„์žฌ Next.js๋Š” ์ ˆ์ถฉ์— ๋Œ€ํ•œ ์šฐ์„  ์ˆœ์œ„๊ฐ€ Next.js์—์„œ ํ•˜๋“œ ์ฝ”๋”ฉ๋˜๋Š” ๋ฐฉ์‹๊ณผ ์ผ์น˜ํ•˜๋Š” ํ”„๋กœ์ ํŠธ์—์„œ๋งŒ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.

react-router (๋ฐ ์ค‘์ฒฉ ๋ผ์šฐํŒ… ์†”๋ฃจ์…˜)์˜ ๋ฌธ์ œ๋Š” ์ฝ”๋“œ ์ž์ฒด๋ฅผ ์‹คํ–‰ (๋˜๋Š” ์‹œ๋ฎฌ๋ ˆ์ด์…˜)ํ•˜์ง€ ์•Š๊ณ ๋Š” ํŠน์ • URL์— ๋Œ€ํ•œ ๊ด€๋ จ ์ฝ”๋“œ ๊ฒฝ๋กœ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์— ์ •์  ๋ถ„์„์„ ํ›จ์”ฌ ์–ด๋ ต๊ฒŒ ๋งŒ๋“ ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์†”์งํžˆ SSG๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ๋น„ ๋™์  ๊ฒฝ๋กœ๊ฐ€ ๋งŽ์€ ๊ฒฝ์šฐ์—๋งŒ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. ๋ชจ๋“  ๊ฒฝ๋กœ๊ฐ€ SSG ๋˜๋Š” ํด๋ผ์ด์–ธํŠธ ์ „์šฉ์ด๋ฉด ์œ ์šฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ๋กœ๊ฐ€ ๋™์ ์ด๋ฉด getStaticPaths ์‚ฌ์šฉํ•˜์—ฌ ๋ช…์‹œ ์ ์œผ๋กœ ์„ ์–ธํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. ์ˆ˜์ •์—†์ด ์›์‹œ react-router๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ๋ช…์‹œ ์ ์œผ๋กœ ์ •์  ๊ฒฝ๋กœ๋ฅผ ์ •์˜ํ•˜๋„๋ก ์š”์ฒญํ•˜๋Š” ๊ฐ€์ƒ์˜ Next.js ํ”Œ๋Ÿฌ๊ทธ์ธ์—์„œ ๊ฒฝ๋กœ๋ฅผ ๋ช…์‹œ ์ ์œผ๋กœ ์ •์˜ํ•˜๋Š” ๊ฒƒ๊ณผ ๋™์ผํ•œ ์ž‘์—…๋Ÿ‰์ž…๋‹ˆ๋‹ค.

ํ™•์‹คํžˆ ์ด์ ์ด๋ฉฐ ์ผ๋ถ€ ํŒ€์€ ๊ทธ๊ฒƒ์„ ์›ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ด๋Š” ์ž ์žฌ์  ์ธ Next.js ์‚ฌ์šฉ์ž์˜ ํ•˜์œ„ ๊ทธ๋ฃน์— ๋ถˆ๊ณผํ•ฉ๋‹ˆ๋‹ค. RR ๋˜๋Š” ๋‹ค๋ฅธ ๋ผ์šฐํŒ… ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์ œ๊ณตํ•˜๋Š” ์ด์  ์ค‘ ์ผ๋ถ€๋ฅผ ์›ํ•  ์ˆ˜์žˆ๋Š” ๋‹ค๋ฅธ ๊ทธ๋ฃน์ด ์žˆ์œผ๋ฉฐ ์ •์  ๊ฒฝ๋กœ๋ฅผ ๋ช…์‹œ ์ ์œผ๋กœ ์„ ์–ธํ•ด์•ผํ•˜๋Š” ํ•„์š”์„ฑ์€ ํ—ˆ์šฉ ๊ฐ€๋Šฅํ•œ ์ ˆ์ถฉ์ ์ด๊ฑฐ๋‚˜ ๋ฌธ์ œ๊ฐ€๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ์ €์˜ ๋งˆ์ง€๋ง‰ ๋ช‡ ๊ฐ€์ง€ ํ”„๋กœ์ ํŠธ๋Š” 100 %๊ฐ€ ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€ ๋’ค์— ์žˆ๊ณ  ์ •์ ์œผ๋กœ ๋ Œ๋”๋ง ํ•  ํ•„์š”๊ฐ€์—†๋Š” B2B / B2C ์•ฑ์ž…๋‹ˆ๋‹ค. Next.js๋Š” Next.js๋ฅผ ์„ ํ˜ธํ•˜๋Š” CRA์— ๋น„ํ•ด ๋ช‡ ๊ฐ€์ง€ ์žฅ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋ผ์šฐํ„ฐ์™€ ๊ฐ™์€ ๊ฒƒ๋“ค์€ ํฐ ์œ„ํ—˜ ์‹ ํ˜ธ ์˜€๊ณ  ์šฐ๋ฆฌ๋Š” CRA๋ฅผ ๊ณ„์† ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ํ”„๋กœ์ ํŠธ๋Š” raw react-router๊ฐ€์žˆ๋Š” Next.js์— ๋งค์šฐ ์ ํ•ฉํ–ˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ ๋˜ํ•œ next/router ์›ํ•˜์ง€ ์•Š๋Š” ๋ชจ๋“  ์‚ฌ๋žŒ๋“ค์ด JSX ํ˜•ํƒœ์˜ react-router๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ๋ฅผ ์›ํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด next/router ๋Œ€์•ˆ์˜ ์œ ์ผํ•œ ์œ ํ˜•์€ ์•„๋‹™๋‹ˆ๋‹ค.

๋‹ค๋ฅธ ์œ ํ˜•์˜ ๋ผ์šฐํ„ฐ๋Š” Gatsby.js ์Šคํƒ€์ผ์ž…๋‹ˆ๋‹ค. ํ”„๋กœ์ ํŠธ๊ฐ€ ์—ฌ์ „ํžˆ ํŒŒ์ผ ์‹œ์Šคํ…œ ๊ธฐ๋ฐ˜ ํŽ˜์ด์ง€ ๊ตฌ์กฐ๋ฅผ ์‚ฌ์šฉํ•˜์ง€๋งŒ ๋‚ด๋ถ€๋Š” react-router์™€ ๊ฐ™์€ ๋‹ค๋ฅธ ๋ผ์šฐํŒ… ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ ๊ตฌํ˜„๋ฉ๋‹ˆ๋‹ค (Gatsby๋Š” ๋‚ด๋ถ€์ ์œผ๋กœ @reach/router ). ์ด๋Ÿฌํ•œ ์ข…๋ฅ˜์˜ ๋ผ์šฐํ„ฐ ํ”Œ๋Ÿฌ๊ทธ์ธ์€ ๋™์ผํ•œ ์ •์  ๋ถ„์„ ์ด์ ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋Œ€์ฒด ๋ผ์šฐํ„ฐ๊ฐ€ ์ค‘์ฒฉ ๋ผ์šฐํŒ…๊ณผ ๊ด€๋ จ์ด์—†๋Š” ์ด์ ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๊ฒฝ๋กœ API์— ๋Œ€ํ•œ ์ž ์žฌ์  ์ธ ์„ ํ˜ธ ์‚ฌํ•ญ ์ˆ˜์šฉ, ์ ‘๊ทผ์„ฑ ์ฒ˜๋ฆฌ ๊ฐœ์„ , ํ•ด๋‹น ๋ผ์šฐํ„ฐ ์ฃผ๋ณ€์˜ ์ƒํƒœ๊ณ„์— ๋Œ€ํ•œ ํ†ตํ•ฉ ๊ฐœ์„ .

๋ฌผ๋ก  react-router ์ƒํƒœ๊ณ„ ๋‚ด์—์„œ๋„ JSX ์–‘์‹์ด react-router๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์œ ์ผํ•œ ๋ฐฉ๋ฒ•์€ ์•„๋‹™๋‹ˆ๋‹ค. react-router-config๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์ •์  ๋ถ„์„์„ ์ˆ˜ํ–‰ํ•˜๊ธฐ ์‰ฝ๊ณ  ์ค‘์ฒฉ ๋ผ์šฐํŒ…๋„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

react-router ์‚ฌ์šฉ์ž๋Š” ๊ทธ ์ฑ…์ž„์„ ์ตœ์ข… ์‚ฌ์šฉ์ž์—๊ฒŒ ์ „์ ์œผ๋กœ ์œ„์ž„ํ•˜๊ธฐ ๋•Œ๋ฌธ์— react-loadable์„ ์ง์ ‘ ์‚ฌ์šฉํ•˜๋Š” ๋ฐ ์ต์ˆ™ํ•˜์ง€๋งŒ Next๋Š” ์‰ฝ์ง€ ์•Š์€ ์ถ”์ƒํ™”์™€ ์ž๋™ํ™”๋ฅผ ์‹œ๋„ํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ์šฐ๋ฆฌ ์ค‘ ์ผ๋ถ€๋Š” ์ฝ”๋“œ ๋ถ„ํ•  ์ฒ˜๋ฆฌ์— ๋ฌธ์ œ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ์ค‘์ฒฉ ๋ผ์šฐํŒ…์€ ์ž๋™ ์ฝ”๋“œ ๋ถ„ํ• ๋ณด๋‹ค ํ”„๋กœ์ ํŠธ์— ๋” ์ค‘์š” ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ”„๋กœ์ ํŠธ์— ๊ฐ€์žฅ ์ ํ•ฉํ•œ ํŠธ๋ ˆ์ด๋“œ ์˜คํ”„๊ฐ€ ๋ฌด์—‡์ธ์ง€์— ๊ด€ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ ๋ถ€์ˆ˜์ ์ด์ง€๋งŒ ์‹ค์ œ๋กœ ๊ฒฝ๋กœ์— ๋Œ€ํ•ด์ด๋ฅผ ์ž๋™์œผ๋กœ ์ˆ˜ํ–‰ํ•˜๋Š” babel / webpack ํ”Œ๋Ÿฌ๊ทธ์ธ์˜ ์ž ์žฌ๋ ฅ์— ๋Œ€ํ•ด ๊ถ๊ธˆํ•ฉ๋‹ˆ๋‹ค.

๋˜ํ•œ react-loadable์€ ํšจ๊ณผ์ ์œผ๋กœ ์†Œ๋ฉธ ๋œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ž…๋‹ˆ๋‹ค (๊ฒŒ์‹œ ํ›„ 2 ๋…„, ๋ฒ„๊ทธ ๋ณด๊ณ ์„œ๋ฅผ ์ˆ˜๋ฝํ•˜์ง€ ์•Š์Œ). ๊ฐœ์ธ์ ์œผ๋กœ ์ €๋Š” react-loadable์˜ ๋‚ด๋ถ€ ํฌํฌ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ Next.js์— ์ž๋™์œผ๋กœ ๋‚ด์žฅ ๋œ ๊ฒƒ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค @loadable/components ์ฝ”๋“œ ๋ถ„ํ• ์„ ์ˆ˜๋™์œผ๋กœ ์ˆ˜ํ–‰ํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.

์ œ์•ˆ ๋œ ํ”Œ๋Ÿฌ๊ทธ ํ˜• ๋ผ์šฐํ„ฐ ์ ‘๊ทผ ๋ฐฉ์‹์€ ๋™์ผํ•œ ์œ ํ˜•์˜ ์ถœ๋ ฅ์„ ์–ป๊ธฐ ์œ„ํ•ด ํ”„๋ ˆ์ž„ ์›Œํฌ์— ๊ด‘๋ฒ”์œ„ํ•œ ๋นŒ๋“œ ์‹œ๊ฐ„ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•˜๋Š” ๋ผ์šฐํ„ฐ ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ํฌํ•จํ•ด์•ผ ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋ชจ๋“  ๋ผ์šฐํ„ฐ๋Š” ์ž์ฒด ํŒจํ„ด์„ ๊ธฐ๋ฐ˜์œผ๋กœ ์ด๋Ÿฌํ•œ ์ •๋ณด๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ์•„์•ผํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

์˜ˆ. ์ด๊ฒƒ์ด ์ผ๋ฐ˜์ ์œผ๋กœ ํ”Œ๋Ÿฌ๊ทธ์ธ ์‹œ์Šคํ…œ์ด ์ž‘๋™ํ•˜๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค. ์†”์งํžˆ ์ด๋Ÿฐ ์ข…๋ฅ˜์˜ ์ •๋ณด๊ฐ€ ํ”Œ๋Ÿฌ๊ทธ์ธ์— ์˜ํ•ด ์ œ๊ณต ๋  ์ˆ˜ ์žˆ๋‹ค๋Š” ์‚ฌ์‹ค์€ ๋ฌธ์ œ๊ฐ€ ์•„๋‹ˆ๋ผ ์žฅ์ ์ž…๋‹ˆ๋‹ค. ํ”Œ๋Ÿฌ๊ทธ์ธ์— ์ด๊ฒƒ์„ ํฌํ•จํ•œ๋‹ค๋Š” ๊ฒƒ์€ Next.js๊ฐ€์ด ์ •๋ณด๋ฅผ ์ˆ˜์ง‘ํ•˜๋Š” ๋ฐฉ์‹์ด ์ผ๋ถ€ ์œ ํ˜•์˜ ํ”„๋กœ์ ํŠธ ์š”๊ตฌ์— ์ ํ•ฉํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ ํ•ด๋‹น ํ”„๋กœ์ ํŠธ์˜ ์š”๊ตฌ์— ๋งž๋Š” ๊ฒƒ์œผ๋กœ ๋Œ€์ฒด ํ•  ์ˆ˜ ์žˆ์Œ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๊ทธ๋ ‡๊ฒŒํ•˜๊ธฐ ์œ„ํ•ด ๋ชจ๋“  Next.js๋ฅผ ํฌํฌํ•˜๊ณ  ๋‹ค์‹œ ์ž‘์„ฑํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

์ˆœ์ „ํžˆ ์ถ”์ธก์ด์ง€๋งŒ React๊ฐ€ Suspense๋ฅผ ์™„๋ฃŒํ•˜๋Š” ๋™์•ˆ ๋งŽ์€ ๊ฒƒ๋“ค์ด ๋ฆผ๋ณด์— ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ์ฒซ ๋ฒˆ์งธ ํด๋ž˜์Šค ํŒจํ„ด์ด ๋ชจ๋“  ๋ผ์šฐํ„ฐ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ํฐ ์˜ํ–ฅ์„ ๋ฏธ์น˜๊ณ  ๋น„๋™๊ธฐ /๋กœ๋“œ ๊ฐ€๋Šฅ ๋นŒ๋“œ๋ฅผ์œ„ํ•œ ๊ตฌ์ฒด์ ์ธ ๊ธฐ๋ฐ˜์„ ์ œ๊ณตํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋ฒˆ๋“ค ํŒจํ„ด.

์ด๊ฒƒ์€ ๊ทธ ์ž์ฒด๋กœ ํ”Œ๋Ÿฌ๊ทธ ํ˜• ๋ผ์šฐํ„ฐ ์‹œ์Šคํ…œ์—์„œ ์ž‘์—…ํ•˜๊ธฐ์œ„ํ•œ ๊ฝค ์ข‹์€ ์ฃผ์žฅ์ด ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ผ์šฐํŒ… ๋ฐ SSR ๋ฌผ๊ฑด ๋ชจ๋‘ Next.js์— ํ•˜๋“œ ์ฝ”๋”ฉ๋˜์–ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ง€๊ธˆ์€ ์‰ฝ๊ฒŒ Next.js. ๋‚ด์—์„œ ์‹œ์Šคํ…œ์„ ๋ผ์šฐํŒ… ๋ฏธ๋ž˜์˜ ๋ชจ๋“  ์œ ํ˜•์— ์‹คํ—˜์„ ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค Suspense๋Š” Next.js์˜ ๋ผ์šฐํŒ… ๋ฐ ๊ธฐํƒ€ ๋ผ์šฐํŒ… ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ์–ด๋–ค ์˜ํ–ฅ์„ ๋ฏธ์นฉ๋‹ˆ ๊นŒ? Next.js ์ฒญํฌ๋ฅผ ํฌํฌํ•˜๊ณ  ๋‹ค์‹œ ์ž‘์„ฑํ•˜์ง€ ์•Š๊ณ ๋Š” (์ ์–ด๋„ Next.js์˜ SSR ๋ฐ ๋ฒˆ๋“ค๋ง๊ณผ ๊ด€๋ จํ•˜์—ฌ) ์‹คํ—˜ ํ•  ์ˆ˜์žˆ๋Š” ๊ฒƒ์ด ์•„๋‹™๋‹ˆ๋‹ค.

๋ผ์šฐํ„ฐ ํ”Œ๋Ÿฌ๊ทธ์ธ์€ ์ด๋Ÿฐ ์ข…๋ฅ˜์˜ ์‹คํ—˜์„ ์ˆ˜ํ–‰ํ•˜๊ธฐ์— ์ข‹์€ ์žฅ์†Œ์ž…๋‹ˆ๋‹ค. ํ”Œ๋Ÿฌ๊ทธ์ธ API๊ฐ€ ์ถฉ๋ถ„ํžˆ ๋‚ฎ์€ ์ˆ˜์ค€์ด๋ฉด next/router ํ”Œ๋Ÿฌ๊ทธ์ธ ๋งŒ ํฌํฌํ•˜๊ณ  ํ•ด๋‹น ๋ผ์šฐํ„ฐ์˜ react @ experimental + Suspense ๊ธฐ๋ฐ˜ ๋ฒ„์ „์„ ์ž‘์„ฑํ•ด ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ด๊ฒƒ์€ ํ”Œ๋Ÿฌ๊ทธ์ธ (Next.js์˜ ๋ชจ๋“  ํฌํฌ๊ฐ€ ์•„๋‹˜)์ด๊ธฐ ๋•Œ๋ฌธ์— ์‹คํ—˜์— ์ฐธ์—ฌํ•˜๊ณ  ์ƒˆ๋กœ์šด ์„œ์ŠคํŽœ์Šค ๊ธฐ๋ฐ˜ ๋ผ์šฐํ„ฐ๋ฅผ ํ…Œ์ŠคํŠธํ•˜๊ธฐ๊ฐ€ ์‰ฝ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฐ ์ข…๋ฅ˜์˜ ์‹คํ—˜์ด ์‹ค์ œ ํ”„๋กœ์ ํŠธ์—์„œ ํ”ผ๋“œ๋ฐฑ์„ ์ˆ˜์ง‘ํ•˜๊ธฐ ์œ„ํ•ด react @ experimental ์ด ์กด์žฌํ•˜๋Š” ์ด์œ  ์ด๊ธฐ ๋•Œ๋ฌธ์— ์ด๊ฒƒ์€ ๋‚˜์ค‘๋ณด๋‹ค๋Š” ์ง€๊ธˆ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.

@dantman ๋‚˜๋Š” ๋‹น์‹ ์ด ๋งํ•œ ๊ฒƒ์— ๋™์˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์€ ๋ชจ๋‘ ํŠธ๋ ˆ์ด๋“œ ์˜คํ”„์— ๊ด€ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ฐ€์žฅ ํฐ ๋‹จ์ ์€ Next ํŒ€์ด ์‹œ๊ฐ„์„ ๋ณด๋‚ด๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ง€๊ธˆ๊นŒ์ง€ ์ € ๊ตฌ์„ฑ ๊ณ ์„ฑ๋Šฅ SSR์ด ์ฃผ์š” ์ดˆ์ ์ด์—ˆ๋˜ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๋‚˜๋Š” ์ด๊ฒƒ์ด ๋ชจ๋“  ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ฐ˜๋“œ์‹œ ๊ด€๋ จ์ด์žˆ๋Š” ๊ฒƒ์€ ์•„๋‹ˆ์ง€๋งŒ Next๊ฐ€ ์ฒ˜์Œ์— ๋ˆˆ์— ๋„๋Š” ๋ฐ ์‚ฌ์šฉ ๋œ ๊ฐ๋„๋ผ๋Š” ๊ฒƒ์„ ์ดํ•ดํ•ฉ๋‹ˆ๋‹ค (์ด๊ฒƒ์ด ์šฐ๋ฆฌ๊ฐ€ ์ง์žฅ์—์„œ ๊ทธ๋“ค์„ ์„ ํƒํ•˜๋Š” ์ด์œ ์ž…๋‹ˆ๋‹ค). ๊ทธ๋“ค์€ ์ตœ๊ทผ Gatsby์™€ Jamstack์˜ ์ธ๊ธฐ๋กœ ์ธํ•ด SSG๋ฅผ ๋” ๋งŽ์ด ํŒŒ๊ณ  ์žˆ์—ˆ์ง€๋งŒ ์—ฌ์ „ํžˆ SSR imo์— ๊ฐ€์žฅ ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค.

์†”์งํžˆ SSG๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ๋น„ ๋™์  ๊ฒฝ๋กœ๊ฐ€ ๋งŽ์€ ๊ฒฝ์šฐ์—๋งŒ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.

SSG ๋Œ€ SSR์€ ์ฒซ ํŽ˜์ด์ง€ ( "์ค‘์š” ๊ฒฝ๋กœ"JS)์— ๋Œ€ํ•ด ๊ฐ€๋Šฅํ•œ ๊ฐ€์žฅ ์ž‘์€ JS ํŽ˜์ด๋กœ๋“œ๋ฅผ ์ œ๊ณตํ•˜๋ ค๊ณ  ์‹œ๋„ํ•˜๊ฑฐ๋‚˜ ๋™์  ๊ฒฝ๋กœ๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐ ์‹ค์ œ๋กœ ์ค‘์š”ํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ์ด๊ฒƒ์ด ์˜๋ฏธํ•˜๋Š” ๋ฐ”๋ฅผ ์ž˜ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค. ์ค‘์š” ๊ฒฝ๋กœ ์ž์‚ฐ์„ ์ตœ์†Œํ™”ํ•˜๋Š” ๊ฒƒ์€ ์ผ๋ฐ˜์ ์œผ๋กœ SSR ์•ฑ์— ๋งค์šฐ ์ค‘์š”ํ•˜๋ฏ€๋กœ (๋”ฐ๋ผ์„œ ๋ชจ๋“  ๋…ธ๋ ฅ) ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์†”์งํžˆ, ๋‹น์‹ ์ด ๋งŒ๋“œ๋Š” ๋ชจ๋“  ๊ฒƒ์ด ๋กœ๊ทธ์ธ ์›” CSR ์ „์šฉ ์•ฑ์ด๋ผ๋ฉด, Next _does_๋Š” CRA์— ๋น„ํ•ด ๋งŽ์€ ๋‹จ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค (SSR์€ ๊ฒฐ์ฝ” CSR๋งŒํผ ํŽธ๋ฆฌํ•˜์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค). ์‹ค์ œ๋กœ ์„ฑ๋Šฅ ํ–ฅ์ƒ์„ ์œ„ํ•ด ๋Ÿฐํƒ€์ž„ SSR (๋กœ๊ทธ์ธ / ๊ฐœ์ธํ™”์˜ ์„œ๋ฒ„ ์ธก ์ฒ˜๋ฆฌ ํฌํ•จ)์„ ์ˆ˜ํ–‰ํ•˜๋Š” ์•ฑ์„ ํ• ์ธํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋“ค๋ฆฝ๋‹ˆ๋‹ค. ๋ชจ๋“  ๊ฒƒ์ด SSG์™€ CSR ์ด๋ถ„๋ฒ•์— ๋ถ€ํ•ฉํ•˜๋Š” ๊ฒƒ์€ ์•„๋‹™๋‹ˆ๋‹ค.

์šฐ๋ฆฌ ์ค‘ ์ผ๋ถ€๋Š” ์ฝ”๋“œ ๋ถ„ํ•  ์ฒ˜๋ฆฌ์— ๋ฌธ์ œ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

์šฐ๋ฆฌ ์ค‘ ์ผ๋ถ€๋Š” ์›นํŒฉ, react-dom / server ๋“ฑ์„ ์ฒ˜๋ฆฌ ํ•  ์ˆ˜ โ€‹โ€‹์žˆ์Šต๋‹ˆ๋‹ค. ์ง€๊ธˆ๊นŒ์ง€ Next์˜ ๋ชฉํ‘œ๋Š” CRA์ฒ˜๋Ÿผ ์ด๋Ÿฌํ•œ ๋ฐฐ์ถœ์„ ๋” ํฌ๊ท€ํ•˜๊ณ  ํฌ๊ท€ํ•˜๊ฒŒ ๋งŒ๋“œ๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋‹น์‹ ์ด ์˜ณ์Šต๋‹ˆ๋‹ค. ๊ทธ ๊ณต๊ฐ„์—๋Š” ๋งŽ์€ ์†”๋ฃจ์…˜์ด ์žˆ๊ณ  Relay์™€ ๊ฐ™์€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ์ƒˆ๋กœ์šด ๋ฐ์ดํ„ฐ ํ”Œ๋Ÿฌ์Šค ์ฝ”๋“œ ํŒจํ„ด์œผ๋กœ ์ธํ•ด ๋”์šฑ ์ด๊ตญ์ ์ด๋ฏ€๋กœ ๋ฐ˜์‘๋กœ๋“œ ๊ฐ€๋Šฅ์ด๋ผ๊ณ  ๋ง ํ–ˆ์–ด์•ผํ–ˆ์Šต๋‹ˆ๋‹ค.

๊ถ๊ทน์ ์œผ๋กœ ํ”Œ๋Ÿฌ๊ทธ ํ˜• ๋ผ์šฐํ„ฐ ์‹œ์Šคํ…œ์ด ์ข‹์„ ์ˆ˜ ์žˆ๋‹ค๋Š” ๋ฐ ๋™์˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ €๋Š” Next ํŒ€์ด ํ”„๋ ˆ์ž„ ์›Œํฌ์˜ ํ•ต์‹ฌ ์›์น™ (์˜ˆ : ๋ฒˆ๋“ค ๋ถ„ํ•  ๋…ผ๋ฆฌ)์„ ์ œ๊ฑฐํ•˜๊ณ  ํ”Œ๋Ÿฌ๊ทธ ํ˜• ์•„ํ‚คํ…์ฒ˜๋กœ ์ถ”์ถœํ•˜๋Š” ๊ฒƒ์ด ๋งŽ์€ ์ž‘์—…์ด ๋  ๊ฒƒ์ด๋ผ๊ณ  ์ง€์ ํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋‚ด ์ถ”์ธก์€ ๊ณง ๋‚ด ํ•ต์‹ฌ ์ข…์†์„ฑ์— ๋Œ€ํ•œ ํ–ฅํ›„ ๋ณ€๊ฒฝ์œผ๋กœ ์‰ฝ๊ฒŒ ๋’ค์ง‘ํž ์ˆ˜์žˆ๋Š” ๋‚ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ๊ธฐ๋ณธ ๋ณ€๊ฒฝ์„ ์„ค๊ณ„ํ•˜๊ณ  ์‹ถ์ง€ ์•Š๋‹ค๋Š” ์‚ฌ์‹ค์„ ๊ฐ•์กฐํ•˜๊ณ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ๋„ฅ์ŠคํŠธ ๋””์ž์ธ์˜ ์ผ๋ถ€ ์ธก๋ฉด์ด ์ œํ•œ์ ์ด๋ผ๋Š” ๋ฐ ํ™•์‹คํžˆ ๋™์˜ํ•˜์ง€๋งŒ, ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ ์ด๋Ÿฌํ•œ ์ œํ•œ์€ ์ง€๊ธˆ๊นŒ์ง€์˜ ๋””์ž์ธ ์ œ์•ฝ์„ ๊ณ ๋ คํ•  ๋•Œ ์˜๋ฏธ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

์†”์งํžˆ SSG๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ๋น„ ๋™์  ๊ฒฝ๋กœ๊ฐ€ ๋งŽ์€ ๊ฒฝ์šฐ์—๋งŒ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.

SSG ๋Œ€ SSR์€ ์ฒซ ํŽ˜์ด์ง€ ( "์ค‘์š” ๊ฒฝ๋กœ"JS)์— ๋Œ€ํ•ด ๊ฐ€๋Šฅํ•œ ๊ฐ€์žฅ ์ž‘์€ JS ํŽ˜์ด๋กœ๋“œ๋ฅผ ์ œ๊ณตํ•˜๋ ค๊ณ  ์‹œ๋„ํ•˜๊ฑฐ๋‚˜ ๋™์  ๊ฒฝ๋กœ๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐ ์‹ค์ œ๋กœ ์ค‘์š”ํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ์ด๊ฒƒ์ด ์˜๋ฏธํ•˜๋Š” ๋ฐ”๋ฅผ ์ž˜ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค.

์šฐ๋ฆฌ๋Š” ์•„๋งˆ๋„ ์–ด๋–ค ๊ฒฝ๋กœ๊ฐ€ ์กด์žฌํ•˜๋Š”์ง€ ์ •์ ์œผ๋กœ ๋ถ„์„ํ•˜๋Š” ๋Šฅ๋ ฅ์ด ํ•„์š”ํ•œ ๋‹ค๋ฅธ ์ด์œ ๋ฅผ ์ƒ๊ฐํ•˜๊ณ ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์šฐ๋ฆฌ ๋‘˜ ๋‹ค "์ •์  ๋ถ„์„"์„ "๋‹จ์ˆœํžˆ ์ฝ”๋“œ๋ฅผ ์ฝ๋Š” ๊ฒƒ๋งŒ์œผ๋กœ ๋นŒ๋“œ์‹œ ๊ฒฝ๋กœ ๋ชฉ๋ก (์˜ˆ : ['/about', '/', '/profile'] )์„ ์‹๋ณ„ ํ•  ์ˆ˜์žˆ๋Š” ๋Šฅ๋ ฅ"์ด๋ผ๊ณ  ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค.

์–ด๋–ค ์œ ํ˜•์˜ JS ๋ฒˆ๋“ค ์ตœ์ ํ™”์— ๋Œ€ํ•ด ๋งํ•˜๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๊นŒ? ๋ฌธ์„œ์—์„œ ์ •๋ณด๋ฅผ ์ฐพ์ง€ ๋ชป ํ–ˆ์œผ๋ฏ€๋กœ ์ •์  ๊ฒฝ๋กœ ๋ถ„์„์„ ๊ธฐ๋ฐ˜์œผ๋กœํ•˜๋Š” ์ตœ์ ํ™” ์œ ํ˜•์„ ์ •ํ™•ํžˆ ์•Œ์ง€ ๋ชปํ•ฉ๋‹ˆ๋‹ค.

์ด ์ •์  ๊ฒฝ๋กœ ๋ถ„์„์ด ์ฃผ๋กœ SSG์— ์œ ์šฉํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ์Šต๋‹ˆ๋‹ค. ์ฆ‰, ์‚ฌ์ดํŠธ๋ฅผ ๋นŒ๋“œ ํ•  ๋•Œ pages/about.js ํŒŒ์ผ์ด ์กด์žฌํ•˜๊ธฐ ๋•Œ๋ฌธ์— Next.js๋Š” /about ๊ฒฝ๋กœ๊ฐ€ ์กด์žฌํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ณ  ๋ช…์‹œ ์ ์œผ๋กœ ์–ธ๊ธ‰ ํ•œ ์ ์ด ์—†๋”๋ผ๋„์ด ๊ฒฝ๋กœ์— ๋Œ€ํ•œ html์„ ๋ฏธ๋ฆฌ ๋ Œ๋”๋งํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. ์‚ฌ์ „ ๋ Œ๋”๋ง์— ๋Œ€ํ•œ /about ๊ฒฝ๋กœ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

SSR์€ ์š”์ฒญ์ด ๋“ค์–ด์˜ฌ ๋•Œ๋งŒ ์ˆ˜ํ–‰ํ•˜๋ฏ€๋กœ ๋ฏธ๋ฆฌ ๋นŒ๋“œ ๋œ html์ด ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค (์ด ์‹œ์ ์—์„œ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜๊ณ  ๋ Œ๋”๋ง ํ•  ๊ฒฝ๋กœ๊ฐ€ ํ•˜๋‚˜ ์žˆ์Œ). ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋ Œ๋”๋ง ํ•œ ํŽ˜์ด์ง€์—๋Š” ๋ฏธ๋ฆฌ ๋ Œ๋”๋ง ๋œ HTML์ด ์ „ํ˜€ ์—†์Šต๋‹ˆ๋‹ค. SSG ํŽ˜์ด์ง€๊ฐ€ ๋™์ ์ด๋ฉด ์–ด์จŒ๋“  ๋ชจ๋“  ๊ฒฝ๋กœ๋ฅผ ์„ ์–ธํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋‚ด ์ƒ๊ฐ.

๊ทธ๋ฆฌ๊ณ  ์†”์งํžˆ, ๋‹น์‹ ์ด ๋งŒ๋“œ๋Š” ๋ชจ๋“  ๊ฒƒ์ด ๋กœ๊ทธ์ธ ์›” CSR ์ „์šฉ ์•ฑ์ด๋ผ๋ฉด, Next _does_๋Š” CRA์— ๋น„ํ•ด ๋งŽ์€ ๋‹จ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค (SSR์€ ๊ฒฐ์ฝ” CSR๋งŒํผ ํŽธ๋ฆฌํ•˜์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค).

CSR ์•ฑ๊ณผ ๊ด€๋ จํ•˜์—ฌ Next.js์—์„œ ์–ด๋–ค ๋‹จ์ ์„ ์ƒ๊ฐํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๊นŒ? ์•ž์„œ ์–ธ๊ธ‰ ํ•œ ๋ผ์šฐํ„ฐ ๋ฌธ์ œ ์™ธ์—.

๋‚ด ์ดํ•ด์— Next.js๋Š” SSR / SSG / CSR ๊ฒฝ๋กœ์˜ ์ „์ฒด ์˜์—ญ์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋กœ๊ทธ์ธ ๋ฒฝ์œผ๋กœ ๋œ CSR ์ „์šฉ ์•ฑ์„ ์ž‘์„ฑํ•˜๋Š” ๋ฐ ์—ฌ์ „ํžˆ ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค.

๊ฐœ์ธ์ ์œผ๋กœ ๋‚ด ๊ด€์ ์€ ๋•Œ๋•Œ๋กœ SSR ๋ฐ SSG๊ฐ€ ํ•„์š”ํ•œ ๋งŽ์€ CSR ์•ฑ์„ ์ž‘์„ฑํ•˜๋Š” ๋ˆ„๊ตฐ๊ฐ€๋กœ๋ถ€ํ„ฐ ๋‚ด ๋ชจ๋“  ํ”„๋กœ์ ํŠธ์— ๋Œ€ํ•ด ๊ฐ•๋ ฅํ•œ ๋‹จ์ผ ํˆดํ‚ท์„ ์›ํ•˜๊ณ  ๊ทธ๋“ค์ด ํ•„์š”ํ•œ SSR / SSG / CSR์˜ ์กฐํ•ฉ์— ์ƒ๊ด€์—†์ด ์›ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋‚ด ๊ฒฝํ—˜์ƒ CRA๋Š” CSR ์ „์šฉ ์•ฑ ๋‚ด์—์„œ๋„ Next.js์˜ CSR ํŽ˜์ด์ง€๋ฅผ ์œ ๋ฆฌํ•˜๊ฒŒ ๋งŒ๋“ค ์ˆ˜์žˆ๋Š” ๋งŽ์€ ๋‹จ์ ์„ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๊บผ๋‚ด์ง€ ์•Š๊ณ  WebPack ๊ตฌ์„ฑ ์‚ฌ์šฉ์ž ์ •์˜๋Š” ํฐ ๋ฌธ์ œ์ž…๋‹ˆ๋‹ค. i18n์„ ์•ฑ์— ์ถ”๊ฐ€ ํ•  ๋•Œ ๋‹จ์ˆœํžˆ globalize-compiler WebPack ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์—ˆ์„ ๋•Œ ์ด๋กœ ์ธํ•ด ๋งŽ์€ ๊ณ ํ†ต์„ ๊ฒช์—ˆ์Šต๋‹ˆ๋‹ค. ๋Œ€๋ถ€๋ถ„์˜ ํŽ˜์ด์ง€๊ฐ€ CSR ์ธ ๊ฒฝ์šฐ์—๋„ ํŠน์ • ํŽ˜์ด์ง€์— ๋Œ€ํ•ด SSR / SSG๋ฅผ ์˜ตํŠธ ์ธํ•˜๋Š” ๊ธฐ๋Šฅ๋„ ์žฅ์ ์ž…๋‹ˆ๋‹ค (์˜ˆ : ํŽ˜์ด์ง€์˜ 99.9 %๊ฐ€ CSR์ด๊ณ  ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€ ๋’ค์— ์žˆ์ง€๋งŒ ๋žœ๋”ฉ ํŽ˜์ด์ง€๊ฐ€ ์žˆ๊ณ  ์•ฝ๊ด€ / ์—ฐ๋ฝ์ฒ˜๊ฐ€์žˆ์„ ์ˆ˜ ์žˆ์Œ) SSG ๋˜๋Š” SSR์„ ์›ํ•˜๋Š” ํŽ˜์ด์ง€). CRA์™€ ๊ฐ™์€ ๊ฒƒ๋“ค๋กœ๋Š” ํ•ฉ๋ฆฌ์ ์œผ๋กœ ๊ทธ๋Ÿฐ ์ผ์„ ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

์šฐ๋ฆฌ ์ค‘ ์ผ๋ถ€๋Š” ์ฝ”๋“œ ๋ถ„ํ•  ์ฒ˜๋ฆฌ์— ๋ฌธ์ œ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

์šฐ๋ฆฌ ์ค‘ ์ผ๋ถ€๋Š” ์›นํŒฉ, react-dom / server ๋“ฑ์„ ์ฒ˜๋ฆฌ ํ•  ์ˆ˜ โ€‹โ€‹์žˆ์Šต๋‹ˆ๋‹ค. ์ง€๊ธˆ๊นŒ์ง€ Next์˜ ๋ชฉํ‘œ๋Š” CRA์ฒ˜๋Ÿผ ์ด๋Ÿฌํ•œ ๋ฐฐ์ถœ์„ ๋” ํฌ๊ท€ํ•˜๊ณ  ํฌ๊ท€ํ•˜๊ฒŒ ๋งŒ๋“œ๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

์†”์งํžˆ, ๊ฒฝ๋กœ ๊ธฐ๋ฐ˜ ์ฝ”๋“œ ๋ถ„ํ•  (React.lazy ๋˜๋Š” ์ง์ ‘ ๊ฐ€์ ธ ์˜ค๊ธฐ ๋Œ€์‹  ๋Œ€์ฒด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ํ†ตํ•ด ๊ฒฝ๋กœ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก ์ˆ˜์ •)์„ ์ˆ˜๋™์œผ๋กœ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ์€ ์‚ฌ์šฉ์ž ์ง€์ • WebPack ๊ตฌ์„ฑ์„ ์ˆ˜๋™์œผ๋กœ ๊ด€๋ฆฌํ•˜๊ฑฐ๋‚˜ ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ๊ณผ๋Š” ๊ฑฐ๋ฆฌ๊ฐ€ ๋ฉ€์Šต๋‹ˆ๋‹ค. react-dom/server ์ž์‹ ์˜ SSR ์ฒ˜๋ฆฌ๊ธฐ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

์ „์ฒด WebPack ๊ตฌ์„ฑ ๋˜๋Š” ์‚ฌ์šฉ์ž ์ง€์ • SSR ์„œ๋ฒ„ (์˜ˆ : Next.js์™€ ๊ฐ™์ด ๋„๋ฆฌ ์‚ฌ์šฉ๋˜๋Š” ํ”„๋ ˆ์ž„ ์›Œํฌ๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋Š” ๊ฒฝ์šฐ)๋ฅผ ์ˆ˜๋™์œผ๋กœ ์ž‘์„ฑํ•˜๊ณ  ์‹ถ์ง€๋Š” ์•Š์ง€๋งŒ, react-router๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ๊ฒฝ๋กœ ๊ธฐ๋ฐ˜ ์ฝ”๋“œ๋ฅผ ์ˆ˜๋™์œผ๋กœ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ์€ ๊ดœ์ฐฎ์Šต๋‹ˆ๋‹ค. ํŒŒํŽธ. ํŠนํžˆ ์ž๋™ ๊ฒฝ๋กœ ๊ธฐ๋ฐ˜ ์ฝ”๋“œ ๋ถ„ํ• ์„ ์„ ํƒํ•˜๋ฉด ์‚ฌ์šฉ์ค‘์ธ ๋„๋ฆฌ ์‚ฌ์šฉ๋˜๋Š” ๋ผ์šฐํ„ฐ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์žƒ์–ด ๋ฒ„๋ฆฌ๊ณ  ๋” ๊ด‘๋ฒ”์œ„ํ•˜๊ฒŒ ์‚ฌ์šฉ๋˜๋Š” ๋ผ์šฐํ„ฐ์™€๋Š” ๋งค์šฐ ๋‹ค๋ฅธ API์— ํ•„์š”ํ•œ ์—ฌ๋Ÿฌ ๊ธฐ๋Šฅ์ด์—†๋Š” ๋ผ์šฐํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ์— ๋”์šฑ ๊ทธ๋ ‡์Šต๋‹ˆ๋‹ค.

์‚ฌ์šฉ์ž ์ง€์ • ์„œ๋ฒ„๋ฅผ ๋งŒ๋“ค ํ•„์š”๊ฐ€์—†๋Š” NextJS์™€ react-router ์„ (๋ฅผ) ํ†ตํ•ฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ฐพ์„ ๋•Œ ํ•ญ์ƒ์ด ๋ฌธ์ œ์— ์ฐฉ์ˆ˜ํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์ง์ ‘ ์‹œ๋„ํ•ด๋ณด๊ธฐ๋กœ ๊ฒฐ์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.

react-router v6 (๋ฒ ํƒ€)๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์‚ฌ์šฉ์ž ์ง€์ • _app :

// _app.js || _app.tsx
import * as React from 'react'
import App from 'next/app'
import NextRouter from 'next/router'

export default class CustomApp extends App {
    render() {
        const { Component, pageProps } = this.props

        if (process.browser) {
            const { Router } = require('react-router-dom')
            const { createMemoryHistory } = require('history')
            const history = createMemoryHistory({
                initialEntries: [this.props.router.asPath],
            })

            history.listen(function ({ action, location }) {
                const url = {
                    hash: location.hash,
                    pathname: location.pathname,
                    search: location.search,
                }
                switch (action) {
                    case 'PUSH':
                        return NextRouter.push(url)
                    case 'REPLACE':
                        return NextRouter.replace(url)
                    default:
                        return void 0
                }
            })

            return (
                <Router location={history.location} navigator={history} action={history.action}>
                    <Component {...pageProps} />
                </Router>
            )
        } else {
            const { StaticRouter } = require('react-router-dom/server')
            return (
                <StaticRouter location={this.props.router.asPath}>
                    <Component {...pageProps} />
                </StaticRouter>
            )
        }
    }
}

์™œ

NextJS (์˜ˆ : /foo/[[...bar]].js )์—์„œ _optional catch all route_๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๊ฒƒ์€ ์‰ฝ์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ์ด๋Ÿฌํ•œ ์ข…๋ฅ˜์˜ ํŽ˜์ด์ง€์— ๋Œ€ํ•ด react-router ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜์žˆ๋Š” ๋ฐฉ๋ฒ•์„ ์ฐพ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ์‚ฌ๋žŒ๋“ค์€ ๋‹ค๋ฅธ ์ด์œ ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์„์ง€ ๋ชจ๋ฅด์ง€๋งŒ ๊ทธ๊ฒƒ์ด ๋‚˜์˜ ์ฃผ์š” ๊ด€์‹ฌ์‚ฌ์ด๋ฉฐ react-router ๋Š” ํŠนํžˆ ํ˜„์žฌ ๋ฒ ํƒ€ ๋ฒ„์ „ ์ธ v6์—์„œ ๋ฉ‹์ง„ API๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

์ž‘๋™ ์›๋ฆฌ

๊ทธ๊ฒƒ์€ ๋‹จ์ง€ ์‚ฌ์šฉ์ž์—๊ฒŒ ์ƒ์„ฑ MemoryRouter ๋Œ€์‹  BrowserRouter ์šฐ๋ฆฌ๊ฐ€ NextJS ๋ผ์šฐํ„ฐ ๋ฐ NextJS ๋ผ์šฐํ„ฐ๋ฅผํ•จ์œผ๋กœ์จ ๋ธŒ๋ผ์šฐ์ € ๊ธฐ๋ก๊นŒ์ง€ ์—‰๋ง๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. PUSH ๋ฐ REPLACE ์— ๋Œ€ํ•œ ๋ฉ”๋ชจ๋ฆฌ ๊ธฐ๋ก ๋ณ€๊ฒฝ์„ ์ˆ˜์‹ ํ•˜๋ฏ€๋กœ react-router ํ›„ํฌ ๋˜๋Š” Link ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํƒ์ƒ‰ ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ๋‚ด๋ถ€์ ์œผ๋กœ๋Š” NextJS ๋ผ์šฐํ„ฐ ๋ฉ”์„œ๋“œ .push ๋ฐ .replace ํ˜ธ์ถœ.

NextJS ๋ผ์šฐํ„ฐ ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ๊ฒฝ๋กœ ๋ณ€๊ฒฝ์ด ์‹ค์ œ๋กœ NextJS get*Props ๋ฉ”์„œ๋“œ๋ฅผ ํŠธ๋ฆฌ๊ฑฐํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ฆ‰, NextJS Link ์‚ฌ์šฉํ•˜๋Š” shallow ์˜ต์…˜๊ณผ ์œ ์‚ฌํ•˜๊ฒŒ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ์‚ฌ์šฉ์˜ ๋‹จ์  react-router ์˜ Link ์ „ํ˜€ ์—†๋‹ค๋Š” ๊ฒƒ์ด๋‹ค prefetch . ๊ทธ๋Ÿฌ๋‚˜ ๋Œ€์‹  NextJS Link ๋ฅผ ๊ณ„์† ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ react-router ๋Š” ์—ฌ์ „ํžˆ ๊ฒฝ๋กœ ๋ณ€๊ฒฝ์— ๋ฐ˜์‘ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฉ‹์ง„ ์ ์€ ์ด์ œ NextJS dynamic ๋ฐ react-router ๊ฒฝ๋กœ๋ฅผ ํ™œ์šฉํ•˜๊ณ  ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ž‘์—…์„ ์ˆ˜ํ–‰ ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

// /foo/[[...bar]].js
import * as React from 'react'
import { Route, Routes } from 'react-router-dom'
import dynamic from 'next/dynamic'

const Home = dynamic(() => import('src/views/Home'))
const About = dynamic(() => import('src/views/About'))
const Navigation = dynamic(() => import('src/views/Navigation'))

export default function Root() {
    return (
        <>
            <Navigation />
            <Routes>
                <Route path="/foo/" element={<Home />} />
                <Route path="/foo/about" element={<About />} />
            </Routes>
        </>
    )
}

์–ด์จŒ๋“  ์ด๊ฒƒ์ด ๋ˆ„๊ตฐ๊ฐ€์—๊ฒŒ ๋„์›€์ด๋˜๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค. ๋‚˜๋Š” ์ด๊ฒƒ์„ ํ”„๋กœ๋•์…˜์—์„œ ์‚ฌ์šฉํ•˜์ง€ ์•Š์•˜๊ณ ์ด ์ฝ”๋“œ๋Š” ๋‚ด๊ฐ€ ๊ฐ€์ง€๊ณ ์žˆ๋Š” ์ง€์—ญ ๋†€์ดํ„ฐ์—์„œ ์˜จ ๊ฒƒ์ด๋ฏ€๋กœ ์•„๋งˆ๋„ ๊ฐœ์„  ํ•  ์ˆ˜์žˆ๋Š” ๊ฒƒ์ด์žˆ์„ ๊ฒƒ์ด์ง€๋งŒ ์‹œ์ž‘์ผ ๋ฟ์ด๋‹ค.

Next.js 9.5 ์ด์ƒ์—์„œ React Router ์‚ฌ์šฉ

๋‹น์‹ ์ดํ•ด์•ผ ํ•  Next.js 9.5 ์ด์ƒ ์˜ฌ๋ฐ”๋ฅธ ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ์ด ํ•จ๊ป˜ ๋‹ค์‹œ ์“ฐ๊ธฐ . _ ์‚ฌ์šฉ์ž ์ •์˜ ์„œ๋ฒ„๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ๋งˆ์‹ญ์‹œ์˜ค _! ์ด ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•œ ์ž์„ธํ•œ ์ž์Šต์„œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค : https://colinhacks.com/essays/building-a-spa-with-nextjs

๊ธฐ๋ณธ ์•„์ด๋””์–ด :

  1. ์‚ฌ์šฉ์ž ์ง€์ • ์•ฑ ๋งŒ๋“ค๊ธฐ ( /pages/_app.tsx )

  2. ๋Œ์•„ null ์˜ ๊ฒฝ์šฐ typeof window === "undefined" . ์ด๋Š” SSR ๋‹จ๊ณ„์—์„œ react-router๊ฐ€ ์˜ค๋ฅ˜๋ฅผ ๋ฐœ์ƒ์‹œํ‚ค๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค!

// pages/_app.tsx

import { AppProps } from 'next/app';

function App({ Component, pageProps }: AppProps) {
  return (
    <div suppressHydrationWarning>
      {typeof window === 'undefined' ? null : <Component {...pageProps} />}
    </div>
  );
}

export default App;

suppressHydrationWarning ์†์„ฑ์€ ์„œ๋ฒ„์—์„œ ๋ Œ๋”๋ง ํ•œ ์ฝ˜ํ…์ธ ๊ฐ€ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋ Œ๋”๋ง ํ•œ ์ฝ˜ํ…์ธ ์™€ ์ผ์น˜ํ•˜์ง€ ์•Š์„ ๋•Œ React๊ฐ€ ๋˜์ง€๋Š” ๊ฒฝ๊ณ ๋ฅผ ๋ฐฉ์ง€ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

  1. ํ™ˆํŽ˜์ด์ง€์— ๋ชจ๋“  ๊ฒฝ๋กœ๋ฅผ ๋‹ค์‹œ ์ž‘์„ฑ
// next.config.js

module.exports = {
  async rewrites() {
    return [
      // Rewrite everything else to use `pages/index`
      {
        source: '/:path*',
        destination: '/',
      },
    ];
  },
};

๊ทธ๋Ÿฌ๋ฉด ํ‰์†Œ์ฒ˜๋Ÿผ React Router๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค! ๋งํฌ ๋œ ํŠœํ† ๋ฆฌ์–ผ์—๋Š” ๋” ๋งŽ์€ ์ปจํ…์ŠคํŠธ / ์„ค๋ช…์ด ์žˆ์ง€๋งŒ ์‹œ์ž‘ํ•˜๋Š” ๋ฐ ๋„์›€์ด๋ฉ๋‹ˆ๋‹ค. https://vriad.com/essays/building-a-spa-with-nextjs

@colinhacks ๋ฉ‹์ง„ ์†”๋ฃจ์…˜์ด ์ž‘๋™ํ•˜๋Š”์ง€ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ƒ๊ฐํ•ด์•ผ ํ•  ์ ์€ ์•ฑ์„ app.js ๋˜๋Š” routes.js์™€ ๊ฐ™์€ ์ž์ฒด ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ ๋‹ค์‹œ ์“ฐ๊ธฐ

// next.config.js

module.exports = {
  async rewrites() {
    return [
      {
        source: '/app/:path*',
        destination: '/app',
      },
    ];
  },
};

์ƒ๊ฐํ•ด ๋ณผ๋งŒํ•œ ๊ฒƒ์ด ๋ฐ”๋กœ ๊ท€ํ•˜์˜ ์†”๋ฃจ์…˜์ด ์ œ๊ฐ€ ์ฐพ์€ ๊ฒƒ ์ค‘ ์ตœ๊ณ ์ž…๋‹ˆ๋‹ค.

์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
0 / 5 - 0 ๋“ฑ๊ธ‰