Next.js 라우팅의 기본 개념
Next.js는 파일 기반 라우팅 시스템을 사용합니다. 이는 pages
디렉토리 내의 파일 구조에 따라 라우트가 자동으로 생성되는 것을 의미합니다. 각 파일은 하나의 라우트를 나타내며, 파일 이름이 URL 경로가 됩니다.
기본 페이지 라우팅
pages/index.js
: 기본 루트 경로(/
)pages/about.js
: /about
경로pages/contact.js
: /contact
경로예를 들어, pages/about.js
파일을 생성하면 /about
경로에서 이 페이지를 접근할 수 있습니다.
동적 라우팅
동적 라우팅은 파일 이름에 대괄호([]
)를 사용하여 설정할 수 있습니다. 이는 URL의 일부가 동적으로 변할 수 있음을 나타냅니다.
pages/posts/[id].js
: /posts/1
, /posts/2
등 다양한 id
값을 가진 경로를 처리합니다.[id].js
파일에서는 useRouter
훅을 사용하여 동적 경로 파라미터를 추출할 수 있습니다.
import { useRouter } from 'next/router';
const Post = () => {
const router = useRouter();
const { id } = router.query;
return <p>Post: {id}</p>;
};
export default Post;
중첩 라우팅
Next.js에서는 디렉토리를 중첩하여 하위 경로를 만들 수 있습니다. 예를 들어, pages/blog
디렉토리에 index.js
와 [slug].js
파일이 있으면 다음과 같은 경로를 처리할 수 있습니다.
pages/blog/index.js
: /blog
pages/blog/[slug].js
: /blog/first-post
, /blog/second-post
등API 라우팅
Next.js는 pages/api
디렉토리 내에서 API 라우팅을 지원합니다. 여기서 각 파일은 API 엔드포인트를 나타내며, 서버리스 함수로 실행됩니다.
pages/api/hello.js
: /api/hello
export default function handler(req, res) {
res.status(200).json({ text: 'Hello' });
}
커스텀 서버
Next.js는 기본적으로 Node.js 서버를 사용하지만, Express 같은 커스텀 서버를 사용할 수도 있습니다. 이를 통해 더 정교한 라우팅 로직을 구현할 수 있습니다.
const express = require('express');
const next = require('next');
const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });
const handle = app.getRequestHandler();
app.prepare().then(() => {
const server = express();
server.get('/p/:id', (req, res) => {
const actualPage = '/post';
const queryParams = { id: req.params.id };
app.render(req, res, actualPage, queryParams);
});
server.all('*', (req, res) => {
return handle(req, res);
});
server.listen(3000, (err) => {
if (err) throw err;
console.log('> Ready on http://localhost:3000');
});
});
라우팅 최적화
Next.js에서는 정적 생성과 서버사이드 렌더링을 결합하여 성능을 최적화할 수 있습니다. 정적 페이지는 빌드 타임에 생성되며, 동적 페이지는 서버사이드 렌더링을 통해 실시간으로 생성됩니다.
getStaticProps
: 빌드 타임에 정적 페이지를 생성getServerSideProps
: 요청 시 서버사이드 렌더링을 통해 페이지를 생성예시
// pages/posts/[id].js
import { useRouter } from 'next/router';
export async function getStaticProps({ params }) {
const res = await fetch(`https://.../posts/${params.id}`);
const post = await res.json();
return {
props: {
post,
},
};
}
export async function getStaticPaths() {
const res = await fetch('https://.../posts');
const posts = await res.json();
const paths = posts.map((post) => ({
params: { id: post.id.toString() },
}));
return { paths, fallback: false };
}
const Post = ({ post }) => {
return (
<div>
<h1>{post.title}</h1>
<p>{post.body}</p>
</div>
);
};
export default Post;