계속해서 동적 라우팅에 대해서 이야기 해보도록 하겠다. 가령 게시판을 만든다고 가정했을 때, 특정 게시글 페이지로 이동하게 되면 그 때 URL은 어떻게 구성되어야 할까?
posts 페이지의 4번 게시글로 이동하는 URL이라고 가정한다면 아마 이런식으로 작성하게 될 것이다. posts 페이지는 pages 폴더에 posts 라는 파일을 만들면 자동으로 라우팅을 구성해준다는 것을 우리는 앞서 알아보았다. 그렇다면 저기 게시글의 아이디에 따라 변하게 되는 /4 부분은 어떤 식으로 구축해야 하는가?
pages
ㄴ posts
ㄴ 1.js
ㄴ 2.js
ㄴ 3.js
ㄴ 4.js
... 모르긴 몰라도 이건 아니다.
Next.js는 비단 정적 페이지로의 라우팅만 편하게 해주는 것이 아니다. 위처럼 동적으로 이동해야 하는 라우팅의 경우에도 간단하게 구성해줄 수 있다.
앞서 작성했던 프로젝트에서 test.js를 지우고 components/nav에 /posts로 통하는 새로운 링크를 작성해주도록 하자.
// components/nav.js
import Link from "next/link";
const links = [
{ href: "https://github.com/zeit/next.js", label: "GitHub" },
{ href: "https://nextjs.org/docs", label: "Docs" }
];
export default function Nav() {
return (
<nav>
<ul className="flex justify-between items-center p-8">
<div>
<Link href="/">
<a className="text-blue-500 no-underline mr-10">Home</a>
</Link>
<Link href="/posts">
<a className="text-blue-500 no-underline mr-10">Posts</a>
</Link>
</div>
<ul className="flex justify-between items-center space-x-4">
{links.map(({ href, label }) => (
<li key={`${href}${label}`}>
<a href={href} className="btn-blue no-underline">
{label}
</a>
</li>
))}
</ul>
</ul>
</nav>
);
}
그 다음에는 posts 폴더를 pages 폴더 아래 만들어주고 4개의 게시글로 통하는 링크를 만들어준다.
동적 라우팅으로 보내주는 링크를 만들어주는 방법은 매우 간단하다. 키를 대괄호로 감싼 파일을 만들어주면 된다. 아래 디렉토리 구조를 보자.
posts 폴더 아래 [pid].js라는 파일을 만들어주는 것만으로도 pid에 대응하는 모든 라우팅을 저 하나의 파일로 이동시켜 줄 수 있다.
또한 pages/index.js 가 / 링크로 라우팅되는 것 처럼 posts 폴더의 index.js는 /posts 링크로 라우팅된다.
이제 posts/index.js와 [pid].js를 짜보도록 하자.
// pages/posts/index.js
import Nav from "../../components/nav";
import Link from "next/link";
export default function Posts() {
return (
<div>
<Nav />
<div className="m-10">
// as 요소는 동적 라우팅에서 실제 라우팅 될 링크가 들어가게 된다.
<Link href="/posts/[pid]" as={`/posts/1`}>
<p className="cursor-pointer">PID 1</p>
</Link>
<Link href="/posts/[pid]" as={`/posts/2`}>
<p className="cursor-pointer">PID 2</p>
</Link>
<Link href="/posts/[pid]" as={`/posts/3`}>
<p className="cursor-pointer">PID 3</p>
</Link>
<Link href="/posts/[pid]" as={`/posts/4`}>
<p className="cursor-pointer">PID 4</p>
</Link>
</div>
</div>
);
}
// pages/posts/[pid].js
import { useRouter } from "next/router";
export default function Post() {
const router = useRouter();
const { pid } = router.query;
return (
<div className="m-10">
<h1>Post ID : {pid}</h1>
</div>
);
}
자, 이제 실행을 시키고 posts 페이지로 이동해 본 뒤, 각 링크들을 눌러서 적절하게 라우팅 되는지 확인해보도록 하자.
다음으로 이야기할 것은 API 라우팅이다. Next.js는 통상적으로 백엔드에서 만드는 API를 쉽게 구성하여 API 테스트를 손쉽게 진행할 수 있다.
pages 폴더 아래에 api 폴더를 만든 후, posts API를 구성하고 하드코딩되어 있는 posts 페이지를 재구성하도록 하겠다.
이번에도 디렉토리 구조를 먼저 보도록 하자.
api 폴더 아래 posts.js 파일을 만들어 줌으로써 /api/posts 링크로 해당 API를 호출하도록 만들 수 있다.
// api/posts.js
const posts = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }];
export default function handler(req, res) {
res.status(200).json(posts);
}
매우 간단하게 API를 구성했다. 자, 이제 API 하드코딩되어 있는 posts/index.js 파일을 재구성해보도록 하자.
그 전에 API를 호출하기 위한 axios 라이브러리를 설치하자.
npm install axios
axios와 함께 사용할 수 있는 swr은 Next.js를 만든 vercel에서 만든 Data Fetching Hook Library이다.
관련 포스팅이 있으니 관심 있으신 분들은 한 번 살펴보시기 바란다.
https://velog.io/@silver2473/axios-%EC%99%B8%EA%B8%B8%EC%9D%B8%EC%83%9D-swr%EC%9D%84-%EB%A7%8C%EB%82%98%EB%8B%A4
// pages/posts/index.js
import React, { useState, useEffect } from "react";
import Nav from "../../components/nav";
import Link from "next/link";
import axios from "axios";
export default function Posts() {
const [posts, setPosts] = useState([]);
const getPosts = async () => {
try {
const { data } = await axios.get("/api/posts");
setPosts(data);
} catch (error) {
console.log(error);
}
};
const printPosts = () => {
return posts.map(post => {
return (
<Link href="/posts/[pid]" as={`/posts/${post.id}`}>
<p className="cursor-pointer">PID {post.id}</p>
</Link>
);
});
};
useEffect(() => {
getPosts();
}, []);
return (
<div>
<Nav />
<div className="m-10">{printPosts()}</div>
</div>
);
}
이전과 같이 동작하는 것을 볼 수 있을 것이다.
이처럼 Next.js는 정적, 동적, API에 이르기까지 여러 다양한 라우팅을 제공함으로써 프론트 엔드 개발을 손쉽게 할 수 있도록 지원해준다.
좀 더 심화하여 API 라우팅에도 동적 라우팅의 대괄호 기법을 적용하여 GET /posts/1 과 같은 API 호출도 구성할 수 있는데, 아래 링크를 통해 살펴보시기 바란다.
https://github.com/vercel/next.js/tree/canary/examples/dynamic-routing
여담이지만 vercel팀의 가장 큰 장점은 각 라이브러리에 대한 예제코드를 풍성하게 제공한다는 점이다. (react-spring 팀이랑 비교된다...)
따라서 예제를 통해 해당 라이브러리를 처음 접하는 개발자들도 손쉽게 활용할 수 있으므로 여러분들도 Next.js를 통해 새로운 프레임워크의 세계로 입문하시기 바라는 바이다.
👍