Routing
์ ๋ธ๋ผ์ฐ์ ๊ฒฝ๋ก์ ๋ฐ๋ผ ๋ค๋ฅธ ํ๋ฉด(ํ์ด์ง)์ ๋ณด์ฌ์ฃผ๋ ๊ฒ์ ๋งํ๋ค.React
์์๋ routing์ ๊ตฌํํ๊ธฐ ์ํด ์ฃผ๋ก react-router-dom
๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ค.Next
์์๋ ๋ณ๋์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ํ์ํ์ง ์๋ค.NextJS ๊ณต์๋ฌธ์ ๐
ํ์ผ ์์คํ ์ ๊ธฐ๋ฐ์ผ๋ก ์ ์ ๋ผ์ฐํ ๊ณผ ๋์ ๋ผ์ฐํ ์ ์ ๊ณตํ๋ค.
NextJS
ํ๋ก์ ํธ๋ฅผ ๋ง๋ค๋ฉด pages
๋ผ๋ ํด๋๊ฐ ๋ง๋ค์ด์ง๋ค. pages
ํด๋ ์์ ์๋ ํ์ผ๋ช
์ ๋ฐ๋ผ route
๊ฐ ๊ฒฐ์ ๋๋ค. => ๐ automatic routingexport default
ํด์ผ ํ๋ค.pages/about.js
ํ์ผ ์์ฑ -> localhost:3000/about
pages/index.js
-> localhost:3000/index
(x) localhost:3000
(o)Link
์ปดํฌ๋ํธ์ href
์์ฑ์ ๋ฃ๊ณ , ๋๋จธ์ง ํ๊ทธ ์์ฑ๋ค(ex. className
)์ anchor
ํ๊ทธ์ ๋ฃ๋๋ค.
const router = useRouter();
Routing
์ ๋ณด๋ฅผ ๋ด์ ๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ค.router.push(url, as, options)
: next/link๋ก ์ถฉ๋ถํ์ง ์์ ๊ฒฝ์ฐ์ ์ฌ์ฉํ๋ค.url
: UrlObject | String, ํ์ํ URLas
: UrlObject | String, ๋ธ๋ผ์ฐ์ URL ํ์์ค์ ํ์๋ ๊ฒฝ๋ก๐ป Link and useRouter Example
import Link from "next/link";
import { useRouter } from "next/router";
import styled from "styled-components";
const Anchor = styled.a<{ router: string; pathName: string }>`
color: ${(props) => (props.pathName === props.router ? "red" : "black")};
cursor: pointer;
`;
const NavBar = () => {
const router = useRouter();
return (
<nav>
<Link href="/">
<Anchor pathName="/" router={router.pathname}>
Home
</Anchor>
</Link>
<Link href="/about">
<Anchor pathName="/about" router={router.pathname}>
About
</Anchor>
</Link>
</nav>
);
};
export default NavBar;
ex) pages/movies/[id].tsx -> http://localhost:3000/movies/:id
const router = useRouter();
const { id } = router.query;
๐ฅ Dynamic Routes Example
// components/Movie.tsx
import Link from "next/link";
import { useRouter } from "next/router";
import { IMovieProps } from "../lib/api/movies";
import styled from "styled-components";
// ... styled components ์๋ต
const Movie = ({ movie }: { movie: IMovieProps }) => {
const router = useRouter();
const onClick = (id: number, title: string) => {
router.push(
{
pathname: `/movies/${id}`,
query: {
title,
},
},
`/movies/${id}` // URL masking
);
};
return (
<StyledMovie onClick={() => onClick(movie.id, movie.original_title)}>
<Image src={`https://image.tmdb.org/t/p/w500/${movie.poster_path}`} />
<h4>{movie.original_title}</h4>
</StyledMovie>
);
};
export default Movie;
// pages/movies/[id].tsx
import { useRouter } from "next/router";
import CustomHead from "../../components/CustomHead";
const Detail = () => {
const router = useRouter();
const { id, title } = router.query;
return (
<main>
<CustomHead title={title as string} />
<h1>{id}</h1>
</main>
);
};
export default Detail;
๋๊ดํธ ์์ ์ธ ๊ฐ์ ์ ์ ์ถ๊ฐํ์ฌ ๋ชจ๋ ๊ฒฝ๋ก๋ฅผ ํฌ์ฐฉํ๋๋ก dynamic routes๋ฅผ ํ์ฅํ ์ ์๋ค.
ex) pages/movies/[...params].tsx
-> http://locahost:3000/movies/1
-> http://locahost:3000/movies/asdf/2
-> http://localhost:3000/movies/3/adf3/23a ๋ชจ๋ ์ผ์น
๐ Catch-All-URL Example
// components/Movie.tsx
import Link from "next/link";
import { useRouter } from "next/router";
import { IMovieProps } from "../lib/api/movies";
import styled from "styled-components";
// ... styled components ์๋ต
const Movie = ({ movie }: { movie: IMovieProps }) => {
const router = useRouter();
const onClick = (id: number, title: string) => {
router.push(`/movies/${title}/${id}`);
};
return (
<StyledMovie onClick={() => onClick(movie.id, movie.original_title)}>
<Image src={`https://image.tmdb.org/t/p/w500/${movie.poster_path}`} />
<h4>{movie.original_title}</h4>
</StyledMovie>
);
};
export default Movie;
// pages/movies/[...params].tsx
import { useRouter } from "next/router";
import CustomHead from "../../components/CustomHead";
type MovieDetailParams = [string, string] | [];
const Detail = () => {
const router = useRouter();
const [title, id] = router.query.params as MovieDetailParams; // ๋ฐฐ์ด ๋น๊ตฌ์กฐํ ํ ๋น
return (
<main>
<CustomHead title={title as string} />
<h1>{title}</h1>
</main>
);
};
export default Detail;
pages
ํด๋์ 404.tsx
ํ์ผ์ ๋ง๋ค์ด 404 page๋ฅผ ์ปค์คํ
ํ ์ ์๋ค.