
NextJS가 새롭게 도입한 App router 방식은 폴더와 파일로 라우팅을 구성한다.
💡 NextJS의 Routing Conventions
- 모든 라우팅은 app 폴더 안에 있어야 한다.
- 라우팅이 매치되는 파일 이름은 무조건 page여야 한다. (page.js 또는 page.tsx)
- 이에 해당하지 않는 파일은 라우팅에 영향을 주지 않는다.
- 폴더 이름이 브라우저에서 보이는 URL의 path가 된다.
NextJS에서는 app 폴더 바로 밑의 page.tsx 파일이 ‘/’ 주소에 해당한다.
create-next-app으로 NextJS 템플릿 설치 후 app 폴더 안의 파일을 모두 지운 후 page.tsx 파일을 만든다.
‘src/app/page.tsx’
export default function Home() {
return <h1>Home</h1>;
}
실행시키면 브라우저 화면에 Home이라는 글자만 뜨고, layout.tsx 파일이 자동으로 생성된다.
export const metadata = {
title: 'NextJS',
description: 'Generated by NextJS',
}
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en">
<body>{children}</body>
</html>
)
}
app 폴더 바로 밑에 있는 layout.tsx 파일 안에 있는 것을 RootLayout이라 하며,
html 기본 구조를 제공해준다.
app/about/page.tsx ==> '/about' 라우팅에 대응
app/profile/page.tsx ==> '/profile' 라우팅에 대응
각 폴더 이름이 URL의 path가 된다.
만약 없는 이름의 url에 접근할 경우, 404 에러가 뜨며 NextJS에서 기본적으로 제공해주는 404 페이지 화면이 뜬다.
중첩 라우팅이란, 라우팅 주소 밑에 또 다른 주소가 연이어 나오는 것이다.
📁profile
├── 📄page.tsx
├── 📁profile1
│ └── 📄page.tsx
└── 📁profile2
└── 📄page.tsx
폴더 구조를 위와 같이 작성하면,
‘profile/profile1’ 또는 ‘profile/profile2’ 주소로 접근이 가능하다.
중첩 라우팅이 많아지거나, DB에서 id 값을 불러오는 등 특정 값으로 고정되지 않을 때,
라우팅을 동적으로 관리할 수 있는 다이나믹 라우팅이 필요하다.
📁profile
├── 📄page.tsx
└── 📁[profileId]
└── 📄page.tsx
폴더명을 square 괄호로 감싸주면 NextJS에서 다이나믹 라우팅으로 간주된다.
다이나믹 라우팅의 컴포넌트는
params와 searchParams 두 개의 값을 갖는 props 객체를 가지게 된다.
params는 다이나믹 라우팅의 파라미터 → square 괄호 안에 넘겼던 값이 이 params 객체의 항목 이름이 된다.searchParams는 URL 쿼리 문자열localhost:3000/profile/1?name=yon
{ params: { profileId: '1' }, searchParams: { name: 'yon' } }
보통 props 객체를 디스트럭처링 해서 사용한다.
이 때 주의할 점은, URL 관련된 것의 데이터 타입은 무조건 string!
type Props = {
params: { profileId: string };
searchParams: { name?: string };
};
export default function ProfileDetail({ params, searchParams }: Props) {
return (
<>
<h2>Profile{params.profileId} Detail Page</h2>
<h3>{searchParams.name && `Name: ` + searchParams.name}</h3>
</>
);
}
[...folderName] 형식으로 폴더명을 설정하면 여러 개의 route segment에 대응할 수 있다.
📁product
├── 📄page.tsx
└── 📁[...detail]
└── 📄page.tsx
http://localhost:3000/product/1
http://localhost:3000/product/1/2
product 폴더에 page.tsx를 따로 필요하지 않다면 이중 sqaure 괄호를 사용할 수 있다.
📁product
└── 📁[[...detail]]
└── 📄page.tsx
http://localhost:3000/product
이렇게 작성하지 않고, product 폴더의 page.tsx를 삭제한다면 http://localhost:3000/product URL에 접근할 수 없다. (404 에러)
NextJS는 404 에러 페이지를 기본으로 제공하는데, 이를 커스텀 할 수 있다.
파일 이름은 무조건 not-found.tsx
app 폴더 밑에 두면 모든 404 에러 페이지에 적용할 수 있고,
특정 폴더 밑에 두면 그 라우팅에만 적용할 수 있다.
또한 NextJS는 notFound 함수를 제공한다.
이를 사용하면 조건에 따라 강제로 404 페이지를 적용할 수 있다.
📁product
└── 📁[[...detail]]
└── 📄page.tsx
└── 📄not-found.tsx
import { notFound } from "next/navigation";
type Props = { params: { detail: string[] } };
export default function Detail({ params }: Props) {
if (params?.detail?.length > 3) {
notFound();
}
return (
<>
<h1>Product List</h1>
<h2>{JSON.stringify(params.detail, null, 2)}</h2>
</>
);
}
http://localhost:3000/product/1/2/3/4
app 밑에 폴더가 많아질수록 각각의 폴더가 찾기 어려워진다.
예를 들어, 인증 관련 라우팅인 register 폴더와 login 폴더가 있다.
이를 auth 폴더에 넣어 묶어서 관리하고 싶지만, 이렇게 되면 라우팅 주소에 auth가 포함되어야 한다.
localhost:3000/auth/register
localhost:3000/auth/login
auth 폴더명을 (auth)로 변경하면 이를 해결할 수 있다.
괄호를 추가하면 NextJS는 해당 폴더를 주소로 인식하지 않고, 단순히 그룹화하는 방식으로만 작동한다.