๐ŸคNext.js ์—์„œ ๋ผ์šฐํŒ… ํ•˜๊ธฐ

๐ŸŽฎ๋ผ์šฐํŒ…์˜ ๋น„๋ฐ€, pages ํด๋”

๋”ฐ๋ผ ํ•ด๋ณด๋ฉด์„œ ์™€ ๋Œ€๋ฐ• ์‹ ๊ธฐํ•จ์„ ๋Š๊ผˆ๋‹ค.

์„ธ์ƒ์—โ€ฆ ๋„ˆ๋ฌด ๊ฐ„ํŽธํ•˜์ž–์•„? ๐Ÿ˜ญ๐Ÿ˜ญ๐Ÿ˜ญ

๋„ฅ์ŠคํŠธ์—์„œ ๋ผ์šฐํŒ… ์„ค์ •์€ pages ํด๋”์— ํŒŒ์ผ์„ ๋งŒ๋“ค๋ฉด (๊ธฐ๋ณธ root ๊ฒฝ๋กœ๋Š” index.js) ํŒŒ์ผ์˜ ๊ฒฝ๋กœ์— ๋”ฐ๋ผ ๊ฒฝ๋กœ๊ฐ€ ์„ค์ •์ด ๋œ๋‹ค.

๐ŸŽฎ1. ์ •์  ํŽ˜์ด์ง€ ๋ผ์šฐํŒ… ํ•˜๊ธฐ

pages ํด๋” ๋‚ด index.js (ํ˜น์€ jsx) ํŒŒ์ผ์„ ๋งŒ๋“ค๊ณ  ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ–ˆ๋‹ค.

import Link from 'next/link';

const App = () => {
  return (
    <div>
      <h2>Link to 'tomato' Page</h2>
      <Link href="/tomato">
        <a>Move to '/tomato'</a>
      </Link>
    </div>
  );
};

export default App;

yarn dev ๋ฅผ ํ†ตํ•ด, Move to โ€˜/tomatoโ€™ ๋ผ๋Š” ๋ฌธ๊ตฌ๊ฐ€ localhost:3000 ์˜ ๋ฃจํŠธ ํŽ˜์ด์ง€์— ๋ณด์—ฌ์ง„๋‹ค.

์ด ๋ฌธ๊ตฌ๋ฅผ ๋ˆ„๋ฅด๋ฉด ํŽ˜์ด์ง€๊ฐ€ ์ด๋™์€ ๋˜๋Š”๋ฐ 404 ํŽ˜์ด์ง€๊ฐ€ ๋œฌ๋‹ค.

/tomato ์˜ ๊ฒฝ๋กœ๋กœ ์ด๋™ํ–ˆ์„ ๋•Œ ํ•ด๋‹น ๊ฒฝ๋กœ๋ฅผ ๊ฐ€์ง€๋Š” ํŽ˜์ด์ง€๋ฅผ ๋งŒ๋“ค์ง€ ์•Š์•„์„œ์ด๋‹ค.

๊ทธ๋ž˜์„œ pages ํด๋” ๋‚ด tomato.jsx ํŒŒ์ผ์„ ์ƒ์„ฑํ–ˆ๋‹ค.

import Link from 'next/link';

const tomato = () => {
  return (
    <div>
      <h2>Link to 'Main' Page</h2>
      <Link href="/">
        <a>Move to '/'</a>
      </Link>
    </div>
  );
};

export default tomato;

์ด ํŽ˜์ด์ง€ ์—์„œ๋Š” ๋‹ค์‹œ ๋งํฌ๋ฅผ ํ†ตํ•ด ๋ฉ”์ธ ๋ฃจํŠธ ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•˜๊ฒŒ ๋œ๋‹ค.

import Link from 'next/link';

๋„ฅ์ŠคํŠธ์—์„œ ์ฃผ์†Œ ์ด๋™์„ ํ•  ๋•Œ๋Š” ์ฃผ๋กœ Link ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

Link ์ปดํฌ๋„ŒํŠธ๋Š” DOM ์„ ๊ฐ€์ง€์ง„ ์•Š์ง€๋งŒ ์ž์‹ ์š”์†Œ์ธ < a > ํƒœ๊ทธ๋ฅผ ํด๋ฆญํ•˜๊ฒŒ ๋˜๋ฉด ํด๋ผ์ด์–ธํŠธ ์ธก ๋‚ด๋น„๊ฒŒ์ด์…˜์„ ์‹คํ–‰ํ•˜์—ฌ,

ํŽ˜์ด์ง€ ์ „์ฒด๋ฅผ ์ƒˆ๋กœ ๋ถˆ๋Ÿฌ์˜ค์ง€ ์•Š๊ณ  ์ฃผ์†Œ ์ด๋™์„ ํ•  ์ˆ˜ ์žˆ๋‹ค.

/tomato ํŽ˜์ด์ง€์—์„œ ๋’ค๋กœ๊ฐ€๊ธฐ๋ฅผ ์‹คํ–‰ํ•˜๋ฉด ์ƒˆ๋กœ์šด ์ปดํŒŒ์ผ ์‹œ๊ฐ„์„ ๊ฐ€์ง€์ง€ ์•Š๊ณ  ์ด์ „์— ๋ Œ๋”๋ง๋œ ํŽ˜์ด์ง€ ๋ฅผ ๋ณด์—ฌ์ฃผ๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

ํ•˜์ง€๋งŒ Link ์ปดํฌ๋„ŒํŠธ๋ฅผ ์“ฐ์ง€ ์•Š๊ณ , ์•„๋ž˜ ์ฝ”๋“œ์ฒ˜๋Ÿผ a ํƒœ๊ทธ ๋งŒ์„ ์ด์šฉํ•ด ์ฃผ์†Œ ์ด๋™์„ ํ•˜๊ฒŒ ๋˜๋ฉด

const App = () => {
  return (
    <div>
      <h2>Link to 'tomato' Page</h2>
      <a href="/tomato">
        <p>Move to '/tomato'</p>
      </a>
    </div>
  );
};

ํŽ˜์ด์ง€ ์ „์ฒด๋ฅผ ์ƒˆ๋กœ ๋ฐ›์•„์˜ค๊ฒŒ ๋˜์–ด ์†๋„๊ฐ€ ๋Š๋ ค์ง€๊ณ  ๊นœ๋ฐ•์ž„ ํ˜„์ƒ์ด ๋ฐœ์ƒํ•˜๋ฉฐ ๋’ค๋กœ๊ฐ€๊ธฐ๋ฅผ ํ•ด๋„ ํŽ˜์ด์ง€๋ฅผ ์ƒˆ๋กœ ๋ฐ›์•„์˜ค๊ฒŒ ๋œ๋‹ค.

๋˜ํ•œ Link ์ปดํฌ๋„ŒํŠธ ์•ˆ์— a ํƒœ๊ทธ๊ฐ€ ์•„๋‹Œ p ํƒœ๊ทธ ๋“ฑ์„ ๋„ฃ์–ด๋„ ๋ผ์šฐํŒ… ๊ธฐ๋Šฅ์„ ์ˆ˜ํ–‰ํ•˜์ง€๋งŒ ์›น ์ ‘๊ทผ์„ฑ๊ณผ SEO (๊ฒ€์ƒ‰์—”์ง„ ์ตœ์ ํ™”) ์— ์ข‹์ง€ ์•Š๋‹ค๋Š” ์ !

๋งˆ์ง€๋ง‰์œผ๋กœ Link ์ปดํฌ๋„ŒํŠธ ์•ˆ์— ๋ฆฌ์•กํŠธ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋„ฃ์–ด ๋ผ์šฐํŒ…์„ ์‹œ๋„ํ•˜๋Š” ๊ฒฝ์šฐ์ด๋‹ค.

import Link from 'next/link';

const App = () => {
  return (
    <div>
      <h2>Link to 'potato' Page</h2>
      <Link href="/tomato">
        <Child/>
      </Link>
    </div>
  );
};

const Child = () => {
  return <p>Move to '/tomato'</p>;
};

export default App;

๋ Œ๋”๋ง๋œ ํ™”๋ฉด์€ ํ™•์ธ ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ๋ฆฌ์•กํŠธ ์ปดํฌ๋„ŒํŠธ๋ฅผ ํด๋ฆญํ–ˆ์„ ๋•Œ ๋ผ์šฐํŒ…์ด ๋˜์ง€ ์•Š๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

๋ฆฌ์•กํŠธ ์ปดํฌ๋„ŒํŠธ์— ๋ผ์šฐํŒ… ๊ธฐ๋Šฅ์„ ์ฃผ๊ณ  ์‹ถ๋‹ค๋ฉด

<Link href="/tomato">
  <a><Child/></a>
</Link>

a ํƒœ๊ทธ๋กœ ๊ฐ์‹ธ ์ฃผ์–ด์•ผ ํ•œ๋‹ค.

๐ŸŽฎ2. ๋™์  ํŽ˜์ด์ง€ ๋ผ์šฐํŒ… ํ•˜๊ธฐ

routing1

์ด์ „์— ์ •ํ•ด์ง€์ง€ ์•Š์€ ์ฃผ์†Œ๋กœ ๋ผ์šฐํŒ…์„ ํ•œ๋‹ค.

์œ„์˜ ์ด๋ฏธ์ง€ ์ฒ˜๋Ÿผ โ€˜pagesโ€™ ํด๋”์— โ€˜vegetablesโ€™ ํด๋”๋ฅผ ๋งŒ๋“ค๊ณ  ๊ทธ ์•ˆ์—

[name].jsx

๋ผ๋Š” ํŒŒ์ผ์„ ๋งŒ๋“ค์—ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ํŒŒ์ผ ์•ˆ์—๋Š” ์ ๋‹นํ•œ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋‹ค์‹œ ์ž‘์„ฑํ•ด ์ฃผ๊ณ ,

// [name].jsx

import Link from 'next/link';

const name = () => {
  return (
    <div>
      <h2>Hello!!</h2>
      <Link href="/">Move to '/'</Link>
    </div>
  );
};

export default name;

์ด์ฒ˜๋Ÿผ ํŒŒ์ผ ์ด๋ฆ„์„ ๋Œ€๊ด„ํ˜ธ๋กœ ๊ฐ์‹ธ์„œ ๋งŒ๋“ค๊ฒŒ ๋˜๋ฉด ํŽ˜์ด์ง€๊ฐ€ ์ •์  ํŽ˜์ด์ง€๊ฐ€ ์•„๋‹Œ ๋™์  ํŽ˜์ด์ง€์ž„์„ ์˜๋ฏธํ•˜๊ฒŒ ๋œ๋‹ค.

[ name ].jsx ๋Š” ๋™์  ํŽ˜์ด์ง€์ธ ๊ฒƒ์ด๋‹ค. ์—ฌ๊ธฐ์„œ name ์€ ์ž„์˜์˜ ๊ฐ’์ด ๋œ๋‹ค.

pages/index.jsx ์ฝ”๋“œ๋ฅผ ๋ฐ”๊ฟ” ๋ณด์•˜๋‹ค.

// pages/index.jsx

import Link from 'next/link';

const App = () => {
  return (
    <div>
      <h2>Link to 'potato' Page</h2>
      <Link href="/vegetable/potato">
        <a>Move to '/vegetable/potato'</a>
      </Link>
    </div>
  );
};

export default App;

root

๋ฃจํŠธ โ€™/โ€™ ํŽ˜์ด์ง€์˜ ๋ชจ์Šต์„ ํ™•์ธํ•˜๊ณ  โ€˜/vegetable/potatoโ€™ ๋กœ ๋„˜์–ด๊ฐ€๋Š” ๋งํฌ๋ฅผ ํด๋ฆญํ•˜๋ฉด, ๋งŒ๋“ค์–ด ๋‘์—ˆ๋˜ [ name ].jsx ํŽ˜์ด์ง€๊ฐ€

์•„๋ž˜์™€ ๊ฐ™์ด ๋‚˜์˜จ๋‹ค.

routing2

ํŒŒ์ผ ์ด๋ฆ„์—์„œ ๋Œ€๊ด„ํ˜ธ ์•ˆ์— ์žˆ๋Š” ๊ฐ’์€ ๋ผ์šฐํ„ฐ ๊ฐ์ฒด (router) ์˜ query ์†์„ฑ์œผ๋กœ ๋“ค์–ด๊ฐ€๊ฒŒ ๋œ๋‹ค.

์ •๋ง ๊ทธ๋Ÿฐ์ง€ ํ™•์ธํ•ด ๋ณด๊ธฐ ์œ„ํ•ด โ€˜next/routerโ€™ ์˜ useRouter ํ›…์Šค ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

useRouter ๋Š” ๋ผ์šฐํŠธ ๊ฐ์ฒด๋ฅผ ๋ฆฌํ„ดํ•ด ๋ณด์—ฌ์ค„ ํ…Œ๋‹ˆ ๊ทธ๊ฑธ ์ฝ˜์†”๋กœ๊ทธ๋ฅผ ์ฐ์–ด๋ณด๋ฉด ๋  ๊ฒƒ์ด๋‹ค.

์˜คํ˜ธ, ๋ฆฌ์•กํŠธ์™€ ๋น„์Šทํ•˜๊ตฐ?!๐Ÿคฃ๐Ÿคฃ๐Ÿคฃ๐Ÿคฃ๐Ÿคฃ

// [name].jsx
import Link from 'next/link';
import { useRouter } from 'next/router';

const name = () => {
  const router = useRouter();
  console.log(router);
  return (
    <div>
      <h2>Hello!!</h2>
      <Link href="/">Move to '/'</Link>
    </div>
  );
};

export default name;

๋ธŒ๋ผ์šฐ์ €์˜ ๊ฐœ๋ฐœ์ž ๋„๊ตฌ ์ฝ˜์†” ์ฐฝ์—์„œ ๋ผ์šฐํ„ฐ ๊ฐ์ฒด๋ฅผ ํ™•์ธํ•ด ๋ณด์•˜๋‹ค.

router query

{pathname: "/vegetable/[name]", route: "/vegetable/[name]",
query: {โ€ฆ}, asPath: "/vegetable/potato", components: {โ€ฆ}, โ€ฆ}
asPath: "/vegetable/potato"
back: ฦ’ ()
basePath: ""
beforePopState: ฦ’ ()
components: {/: {โ€ฆ}, /_app: {โ€ฆ}, /vegetable/[name]: {โ€ฆ}}
defaultLocale: undefined
events: {on: ฦ’, off: ฦ’, emit: ฦ’}
isFallback: false
isLocaleDomain: false
isPreview: false
isReady: true
locale: undefined
locales: undefined
pathname: "/vegetable/[name]"
prefetch: ฦ’ ()
push: ฦ’ ()
query: {name: "potato"}
reload: ฦ’ ()
replace: ฦ’ ()
route: "/vegetable/[name]"
__proto__: Object

๋ผ์šฐํ„ฐ ๊ฐ์ฒด์˜ ์†์„ฑ ์ค‘ query ์†์„ฑ ์•ˆ์— {name: โ€œpotatoโ€} ๊ฐ’์ด ๋“ค์–ด ์žˆ๋Š” ๊ฒƒ์„ ํ™•์ธ ํ•  ์ˆ˜ ์žˆ๋‹ค.

์ด๋ฅผ ํ†ตํ•ด pages ํด๋”์— ํŒŒ์ผ ์ด๋ฆ„์„ ๋Œ€๊ด„ํ˜ธ๋กœ [ name ] ์œผ๋กœ ์ž‘์„ฑํ•˜๋ฉด ์ฃผ์†Œ๋กœ ์ „๋‹ฌํ•œ (href) ๊ฐ’์ด query ์†์„ฑ ์•ˆ์—

name ์†์„ฑ์˜ ๊ฐ’์œผ๋กœ ๋“ค์–ด๊ฐ„ ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

ํŒŒ์ผ์˜ ์ด๋ฆ„์ด [ item ] ์ด๋ผ๋ฉด query ์†์„ฑ ์•ˆ์— {item: โ€œpotatoโ€} ๋ผ๋Š” ๊ฐ’์ด ๋  ๊ฒƒ์ด๋‹ค.

๐ŸŽฎ3. ๋ผ์šฐํ„ฐ ๊ฐ์ฒด๋ฅผ ์ด์šฉํ•˜์—ฌ ๋ผ์šฐํŒ… ํ•˜๊ธฐ

ํ•ญ์ƒ Link ์ปดํฌ๋„ŒํŠธ๋กœ ์ฃผ์†Œ ์ด๋™์„ ํ•˜์ง€๋Š” ์•Š๋Š”๋‹ค.

๋ฒ„ํŠผ์„ ํ†ตํ•œ onClick ์ด๋ฒคํŠธ ํ•จ์ˆ˜ ๋‚ด์—์„œ ๋ผ์šฐํŠธ ์ด๋™์„ ํ•˜๊ฒŒ ๋˜๋Š” ๊ฒฝ์šฐ๋„ ๋นˆ๋ฒˆํ•˜๋‹ค.

๋ฐ”๋กœ ์œ„ ๋ผ์šฐํ„ฐ ๊ฐ์ฒด์˜ ํ‚ค์™€ ๊ฐ’์„ ๋ณด๋ฉด ๋‹ค์–‘ํ•œ ํ•จ์ˆ˜๋“ค์ด ์žˆ๋Š”๋ฐ ์ด ์ค‘์— ์ฃผ์†Œ ์ด๋™์„ ์œ„ํ•œ ํ•จ์ˆ˜๊ฐ€ ์žˆ๋‹ค.

โ€œpushโ€ ๊ฐ€ ๋Œ€ํ‘œ์ ์ด๋‹ค.

Link ๋Œ€์‹  ๋ฒ„ํŠผ์„ ๋ˆ„๋ฆ„์œผ๋กœ ์ธํ•œ ์ •์  ํŽ˜์ด์ง€ ์ด๋™๊ณผ input ํƒœ๊ทธ ๋‚ด ์ž…๋ ฅํ•œ name state ๋ฅผ ๊ฐ€์ง€๊ณ  ํ•ด๋‹น ํ…์ŠคํŠธ ์ฃผ์†Œ๋กœ ์ด๋™ํ•˜๋Š”

๋™์  ์ฃผ์†Œ ์ด๋™์„ ํ•˜๊ฒŒ ํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ–ˆ๋‹ค.

// index.jsx

import { useState } from 'react';
import { useRouter } from 'next/router';

const App = () => {
  const [name, setName] = useState('');
  const router = useRouter();
  return (
    <div>
      <button type="button" onClick={() => router.push('/tomato')}>
        tomato๋กœ ๊ฐ€๊ธฐ
      </button>
      <p>์ด๋ฆ„</p>
      <input
        value={name}
        onChange={(e) => setName(e.target.value)}
        style={{ marginRight: '12px' }}
      />
      <button type="button" onClick={() => router.push(`/vegetable/${name}`)}>
        {name}์œผ๋กœ ๊ฐ€๊ธฐ
      </button>
    </div>
  );
};

export default App;

์•„๋ž˜ ํŒŒ์ผ์˜ ์ฝ”๋“œ๋„ ๋™์ ์œผ๋กœ ๋ฐ”๋€Œ๋Š” query ๋ฅผ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด ๋ณ€๊ฒฝํ•ด ๋ณด์•˜๋‹ค.

// pages/vegetable/[name].jsx

import Link from 'next/link';
import { useRouter } from 'next/router';

const name = () => {
  const { query } = useRouter();
  console.log(query);
  return (
    <div>
      <h2>Hello!! {query.name}</h2>
      <Link href="/">Move to '/'</Link>
    </div>
  );
};

export default name;

๋ผ์šฐํŒ… ๊ฐ์ฒด๋ฅผ ์ด์šฉํ•œ ์ฃผ์†Œ ์ด๋™ (๋™์  ๋ผ์šฐํŒ…) ์ด ์ž˜ ๋˜๋Š” ๊ฒƒ์„ ํ™•์ธ ํ•  ์ˆ˜ ์žˆ๋‹ค.

๐ŸŽฎ4. ์ •๋ฆฌ

โ€˜pagesโ€™ ํด๋”๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ •์  ํŽ˜์ด์ง€์™€ ๋™์  ํŽ˜์ด์ง€์˜ ๋ผ์šฐํŒ…์„ ์„ค์ •ํ•˜์˜€๊ณ , Link ์ปดํฌ๋„ŒํŠธ์™€ ๋ผ์šฐํ„ฐ ๊ฐ์ฒด๋ฅผ ์ด์šฉํ•˜์—ฌ ์ฃผ์†Œ ์ด๋™์„ ํ•ด ๋ณผ ์ˆ˜ ์žˆ์—ˆ๋‹ค.

๋„ฅ์ŠคํŠธ์—์„œ ์ œ๊ณตํ•˜๋Š” ๋ผ์šฐํŒ… ๊ด€๋ จ ๊ธฐ๋Šฅ๋“ค์ด ํŽธ๋ฆฌํ•˜๋‹ค ๋ผ๋Š” ๊ฒƒ์„ ์ƒˆ์‚ผ ๋Š๊ผˆ๋‹ค.


Written by@[DotoriMook]
ํ”„๋ก ํŠธ์—”๋“œ ์ฃผ๋‹ˆ์–ด ๊ฐœ๋ฐœ์ž ๋„ํ† ๋ฆฌ๋ฌต์˜ ๊ธฐ์ˆ ๊ฐœ๋ฐœ ๋ธ”๋กœ๊ทธ ์ž…๋‹ˆ๋‹ค.

GitHubMediumTwitterFacebook