๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

NextJS

[NextJS] NextJs์˜ ๋ผ์šฐํŒ…

React๋งŒ ์‚ฌ์šฉํ•˜๋‹ค๊ฐ€ ์ตœ๊ทผ๋ถ€ํ„ฐ NextJS๋ฅผ ๊ณต๋ถ€ํ•˜๊ณ  ์žˆ๋Š”๋ฐ ๋„ˆ๋ฌด ์‹ ๊ธฐํ•˜๋‹ค.. ๊ธฐ์กด์˜ React๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ๋Š” react-router-dom์„ ์‚ฌ์šฉํ•œ ๋ผ์šฐํŒ…์„ ์ „๋‹ดํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋งŒ๋“ค์–ด์คฌ์—ˆ๋Š”๋ฐ NextJS๋Š” ๊ทธ๋Ÿด ํ•„์š”๊ฐ€ ์—†๋‹ค! 

 

๋„ฅ์ŠคํŠธ(Next.js) ์—์„œ๋Š” pages ํด๋” ์•ˆ์— page ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ƒ์„ฑํ•˜๋ฉด ์ž๋™์œผ๋กœ ๊ฒฝ๋กœ๊ฐ€ ์„ค์ •๋œ๋‹ค!!

NextJS ํ”„๋กœ์ ํŠธ์˜ ํด๋”๊ตฌ์กฐ๋ฅผ ์‚ดํŽด๋ณด๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ตฌ์„ฑ๋˜์–ด ์žˆ๋‹ค.

/.next
/node_modules
/pages
/public
/styles
.getignore
package-look.json
package.json
README.md

 

 

์—ฌ๊ธฐ์„œ pages๋ผ๋Š” ํด๋” ์•„๋ž˜์— ํŒŒ์ผ ๋˜๋Š” ํด๋”๋ฅผ ์ƒ์„ฑํ•ด์„œ ๋ผ์šฐํŒ…์„ ํ•  ์ˆ˜ ์žˆ๋‹ค. pages ํด๋”๋‚ด์—๋Š” index.js๋ผ๋Š” ํŒŒ์ผ์ด ์กด์žฌํ• ํ…๋ฐ ์ด ํŒŒ์ผ์ด "/" ๋ฃจํŠธ์ธ ๋ฉ”์ธํŽ˜์ด์ง€๋กœ ๋ผ์šฐํŒ…๋œ๋‹ค.

 

๐Ÿ“˜ ์ •์  ๋ผ์šฐํŒ…

"/" ๋ฃจํŠธ๊ฐ€ ์•„๋‹Œ "/about"์ด๋ผ๋Š” ๋ฃจํŠธ๋กœ ๋ผ์šฐํŒ…์„ ํ•˜๊ณ  ์‹ถ์„๋•Œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ•  ์ˆ˜ ์žˆ๋‹ค. 

/pages
  ใ„ด-- index.js
  ใ„ด-- about.js

pages ํด๋” ๋‚ด์— about์ด๋ผ๋Š” ํŒŒ์ผ์„ ์ƒ์„ฑํ•œ๋‹ค. ์ด๋•Œ ํŒŒ์ผ์˜ ์ด๋ฆ„์ด ๋ฃจํŠธ๊ฐ€ ๋œ๋‹ค.

 

// about.js

function AboutPage() {
  return (
    <div>
      <h1>the About Page</h1>
    </div>
  );
}

export default AboutPage;

 

 

 

 

ํŒŒ์ผ์„ ์ƒ์„ฑํ•˜๊ณ  ํŒŒ์ผ์˜ ๋‚ด์šฉ์„ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ตฌ์„ฑํ•œ๋‹ค๋ฉด "/about"์œผ๋กœ ์ ‘๊ทผํ–ˆ์„ ๋•Œ h1 ํƒœ๊ทธ๋กœ the About Page๋ผ๋Š” ๋ฌธ๊ตฌ๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

 

์ด๋ ‡๊ฒŒ ๋ฐ”๋กœ ํŒŒ์ผ์„ ์ƒ์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ๊ณ  ํด๋”๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•๋„ ์กด์žฌํ•œ๋‹ค. ํด๋”๋ฅผ ์ƒ์„ฑํ•ด๋‚˜๊ฐ€๋ฉด์„œ ํด๋”๋ช…์ด ๋ฃจํŠธ๊ฐ€ ๋˜๊ณ  ํด๋” ๋‚ด๋ถ€์˜ index.js ํŒŒ์ผ์ด ์›ํ•˜๋Š” ์ฃผ์†Œ๋กœ ์ ‘๊ทผํ–ˆ์„ ๋•Œ ๋ณด์—ฌ์ง€๋Š” Page Component๊ฐ€ ๋œ๋‹ค.

/pages
  ใ„ด-- index.js
  ใ„ด-- /about
  	ใ„ด--index.js

 

 

์ด๋Ÿฐ ๊ตฌ์กฐ๋กœ ํŒŒ์ผ์„ ๊ตฌ์„ฑํ•œ๋‹ค๋ฉด ๋™์ผํ•œ ๊ฒฐ๊ณผ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค. 

 

๋งŒ์•ฝ ๋ผ์šฐํŒ…์„ ํ•˜๊ธฐ ์œ„ํ•œ url์ด "/about/jongbin/address" ์ด๋ ‡๊ฒŒ ๋œ๋‹ค๋ฉด ํด๋”๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋Š˜๋ ค๋‚˜๊ฐˆ ์ˆ˜ ์žˆ๋‹ค.

 

๐Ÿ“— ๋™์  ๋ผ์šฐํŒ…

๋™์ ๋ผ์šฐํŒ…๋„ ๊ฐ€๋Šฅํ•˜๋‹ค. react์—์„œ ๋™์ ๋ผ์šฐํŒ…์„ ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋ผ์šฐํŒ… ์ปดํฌ๋„ŒํŠธ์—์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์‹์œผ๋กœ ๋งŒ๋“ค์–ด์คฌ์—ˆ๋‹ค.

<Routes>
  <Route path="About/:id" element={<About />} />
  ...
</Routes>

 

ํ•˜์ง€๋งŒ NextJs์—์„œ๋Š” []๋กœ ๊ฐ์‹ธ์ฃผ๋ฉด ๋œ๋‹ค. ๋”ฐ๋ผ์„œ ์œ„์™€ ๊ฐ™์€ ๋ผ์šฐํŒ…์„ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” about ํด๋” ์•„๋ž˜ [id].js๋ผ๋Š” ํŒŒ์ผ๋งŒ ๋งŒ๋“ค์–ด์ฃผ๋ฉด ๋œ๋‹ค! ์ฃผ์˜ํ•ด์•ผ ํ•˜๋Š” ์ ์€ ํ•œ ํด๋” ์•„๋ž˜ []๋ฅผ ๋‘๋ฒˆ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค.

/pages
  ใ„ด-- index.js
  ใ„ด-- /about
  	ใ„ด--index.js
	ใ„ด--[id].js

 

์ด๋•Œ [id].js๋ผ๋Š” ํŒŒ์ผ์—์„œ๋Š” ์ž…๋ ฅ๋œ ์ฟผ๋ฆฌ ๊ฐ’์„ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

 

import { useRouter } from 'next/router';

function AboutIDPage() {
  const router = useRouter();
  console.log(router.query);

  return (
    <div>
      <h1>the ID Page</h1>
    </div>
  );
}

export default AboutIDPage;

 

 

next์˜ router์—์„œ useRouter๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋˜๋Š”๋ฐ ์ด๋•Œ query๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ๋ธŒ๋ผ์šฐ์ €์—์„œ "/about/jongbin"์œผ๋กœ ์ ‘๊ทผํ•˜์—ฌ ๊ฐœ๋ฐœ์ž๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ฝ˜์†”๊ฐ’์„ ํ™•์ธํ•ด ๋ณด๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ถœ๋ ฅ๋œ๋‹ค.

 

์งฑ์ด๋‹ค...!

์ด๋ฅผ ์ด์šฉํ•ด์„œ API์š”์ฒญ์„ ๋ณด๋‚ด์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜จ๋‹ค๋˜์ง€ ํ•  ์ˆ˜ ์žˆ๋‹ค! ์ถ”๊ฐ€์ ์œผ๋กœ ๋™์ ๋ผ์šฐํŒ…์„ ์ค‘๋ณตํ•ด์„œ ํ•  ์ˆ˜ ์žˆ๋‹ค. ํด๋” ๋ช…์„ []์„ ์‚ฌ์šฉํ•ด์„œ ๋„ฃ์–ด์คŒ์œผ๋กœ์„œ ๋™์ ๋ผ์šฐํŒ…๋„ ๊ฐ€๋Šฅํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ด๋ฅผ ์ด์šฉํ•œ๋‹ค. ์ด๋•Œ ์‚ฌ์šฉ๋˜๋Š” []์•ˆ์— ๋“ค์–ด๊ฐ€๋Š” ๊ฐ’์€ ์ค‘๋ณต๋˜์„œ๋Š” ์•ˆ๋œ๋‹ค! 

 

๋˜ํ•œ ๋ฃจํŠธ๊ฐ€ ๋งŽ์ด ๊ธธ์–ด์ง€๊ณ  ์ผ์ • ๋ฃจํŠธ๊นŒ์ง€๋Š” ์ •ํ•ด์ ธ ์žˆ์„ ๋•Œ ๋“ฑ ์ด๋Ÿฐ ๋ฐฉ์‹๋„ ๊ฐ€๋Šฅํ•˜๋‹ค.

/pages
  ใ„ด-- index.js
  ใ„ด-- /about
  	ใ„ด--index.js
	ใ„ด--[...slug].js

 

 

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ ์ „๊ฐœ๊ตฌ๋ฌธ(...)์„ ์‚ฌ์šฉํ•˜๋ฉด "/about/jongbin/address"๋ผ๊ณ  url์„ ์ž…๋ ฅํ•ด๋„ [...slug].js๋กœ ์ ‘๊ทผํ•˜๊ฒŒ ๋˜๊ณ , useRouter๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๊ฐ’์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. ํ™•์ธํ•ด๋ณด๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ฐฐ์—ด๋กœ ๊ฐ’์ด ๋“ค์–ด๊ฐ€์žˆ๋‹ค.

 

 

๐Ÿ“•๋ผ์šฐํ„ฐ ๊ฐ์ฒด๋ฅผ ์ด์šฉํ•œ ๋ผ์šฐํŒ…

input์„ ์ž‘์„ฑํ•˜๊ณ  form์„ ์ œ์ถœํ•œ๋‹ค๋˜์ง€ ๋“ฑ์˜ ์ž‘์—…์„ ํ• ๋•Œ ํŽ˜์ด์ง€๊ฐ€ ๋‹ค์‹œ reload๋˜์–ด ๋’ค๋กœ๊ฐ€๊ธฐ๊ฐ€ ์•ˆ๋œ๋‹ค๋˜๊ฐ€์˜ ๋ฌธ์ œ์ ์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ ๋ผ์šฐํ„ฐ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•ด์„œ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค.

import { useRouter } from 'next/router';

function About() {
  const router = useRouter();
  console.log(router.query);

  function IDHandler() {
    // API ํ˜ธ์ถœ ๋“ฑ์˜ ์ž‘์—…?!

    // 1. ๊ฒฝ๋กœ๋กœ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Œ
     router.push('/clients/max/projectA');
    
    // 2. ๊ฐ์ฒด๋ฅผ ๋„ฃ์–ด์ค„ ์ˆ˜ ์žˆ์Œ
    router.push({
        pathname: '/about/[id]',
        query: { id: 'jongbin'},
    });
  }

  return (
    <div>
      <h1>the About Page</h1>
      <button onClick={IDHandler}>Load ID</button>
    </div>
  );
}

useRouter๋ฅผ ์‚ฌ์šฉํ•ด์„œ push๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค. ์ด๋•Œ ๋‘๊ฐ€์ง€ ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ path๊ฐ’ ๋ฌธ์ž์—ด๋กœ ๋„ฃ์–ด์ฃผ๋Š” ๋ฐฉ๋ฒ•๊ณผ ๊ฐ์ฒด๋กœ ๋„ฃ์–ด์ฃผ๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค. ๊ฐ์ฒด๋กœ ๋„ฃ์–ด์ค„ ๋•Œ์—๋Š” path์™€ ๋“ค์–ด๊ฐˆ query๊ฐ’์„ key-value๋กœ ๋„ฃ์–ด์ค€๋‹ค.

 

๐Ÿ“™ 404ํŽ˜์ด์ง€

์›ํ•˜์ง€ ์•Š๋Š” ์ฃผ์†Œ๋กœ ์ ‘๊ทผ์„ ํ–ˆ์„ ๋•Œ ๋ง‰์•„์ฃผ๋Š” ๋ฐฉ๋ฒ•์ด ํ•„์š”ํ• ํ…๋ฐ pages ํด๋” ๋ฐ”๋กœ ์•„๋ž˜์— 404.js๋กœ ํŒŒ์ผ์„ ๋งŒ๋“ค์–ด ์ฃผ๋ฉด ๋œ๋‹ค.

 

/pages
  ใ„ด-- index.js
  ใ„ด-- /about
  	ใ„ด--index.js
  	ใ„ด--[id].js
  ใ„ด--404.js

404.js ํŒŒ์ผ์˜ ๋‚ด์šฉ์€ ์›ํ•˜๋Š”๋Œ€๋กœ ๊ตฌ์„ฑํ•˜๋ฉด ๋œ๋‹ค.

 

 

์œ„ ๋ฐฉ๋ฒ•๋“ค์„ ์‚ฌ์šฉํ•ด์„œ ๋ผ์šฐํŒ…์„ ํ•˜๋ฉด ๋œ๋‹ค. NextJS์˜ ์ข‹์€์ ์œผ๋กœ ๋ผ์šฐํŒ…์ด ์‰ฝ๋‹ค.๋ผ๊ณ  ๋“ค์—ˆ์—ˆ๋Š”๋ฐ ๊ฐœ์ธ์ ์ธ ์ƒ๊ฐ์œผ๋กœ๋„ ํด๋”-ํŒŒ์ผ ๊ตฌ์กฐ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ง๊ด€์ ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ๋Š๊ผˆ๋‹ค!