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์ ์ข์์ ์ผ๋ก ๋ผ์ฐํ ์ด ์ฝ๋ค.๋ผ๊ณ ๋ค์์๋๋ฐ ๊ฐ์ธ์ ์ธ ์๊ฐ์ผ๋ก๋ ํด๋-ํ์ผ ๊ตฌ์กฐ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ๊ธฐ ๋๋ฌธ์ ์ง๊ด์ ์ผ๋ก ์ฌ์ฉํ ์ ์๋ค๊ณ ๋๊ผ๋ค!