March 20, 2021
๋ฐ๋ผ ํด๋ณด๋ฉด์ ์ ๋๋ฐ ์ ๊ธฐํจ์ ๋๊ผ๋ค.
์ธ์์โฆ ๋๋ฌด ๊ฐํธํ์์? ๐ญ๐ญ๐ญ
๋ฅ์คํธ์์ ๋ผ์ฐํ ์ค์ ์ pages ํด๋์ ํ์ผ์ ๋ง๋ค๋ฉด (๊ธฐ๋ณธ root ๊ฒฝ๋ก๋ index.js) ํ์ผ์ ๊ฒฝ๋ก์ ๋ฐ๋ผ ๊ฒฝ๋ก๊ฐ ์ค์ ์ด ๋๋ค.
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 ํ๊ทธ๋ก ๊ฐ์ธ ์ฃผ์ด์ผ ํ๋ค.
์ด์ ์ ์ ํด์ง์ง ์์ ์ฃผ์๋ก ๋ผ์ฐํ ์ ํ๋ค.
์์ ์ด๋ฏธ์ง ์ฒ๋ผ โ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;
๋ฃจํธ โ/โ ํ์ด์ง์ ๋ชจ์ต์ ํ์ธํ๊ณ โ/vegetable/potatoโ ๋ก ๋์ด๊ฐ๋ ๋งํฌ๋ฅผ ํด๋ฆญํ๋ฉด, ๋ง๋ค์ด ๋์๋ [ name ].jsx ํ์ด์ง๊ฐ
์๋์ ๊ฐ์ด ๋์จ๋ค.
ํ์ผ ์ด๋ฆ์์ ๋๊ดํธ ์์ ์๋ ๊ฐ์ ๋ผ์ฐํฐ ๊ฐ์ฒด (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;
๋ธ๋ผ์ฐ์ ์ ๊ฐ๋ฐ์ ๋๊ตฌ ์ฝ์ ์ฐฝ์์ ๋ผ์ฐํฐ ๊ฐ์ฒด๋ฅผ ํ์ธํด ๋ณด์๋ค.
{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โ} ๋ผ๋ ๊ฐ์ด ๋ ๊ฒ์ด๋ค.
ํญ์ 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;
๋ผ์ฐํ ๊ฐ์ฒด๋ฅผ ์ด์ฉํ ์ฃผ์ ์ด๋ (๋์ ๋ผ์ฐํ ) ์ด ์ ๋๋ ๊ฒ์ ํ์ธ ํ ์ ์๋ค.
โpagesโ ํด๋๋ฅผ ์ฌ์ฉํด์ ์ ์ ํ์ด์ง์ ๋์ ํ์ด์ง์ ๋ผ์ฐํ ์ ์ค์ ํ์๊ณ , Link ์ปดํฌ๋ํธ์ ๋ผ์ฐํฐ ๊ฐ์ฒด๋ฅผ ์ด์ฉํ์ฌ ์ฃผ์ ์ด๋์ ํด ๋ณผ ์ ์์๋ค.
๋ฅ์คํธ์์ ์ ๊ณตํ๋ ๋ผ์ฐํ ๊ด๋ จ ๊ธฐ๋ฅ๋ค์ด ํธ๋ฆฌํ๋ค ๋ผ๋ ๊ฒ์ ์์ผ ๋๊ผ๋ค.