Next.js 13부터 도입된 App Router는 기존 Page Router와 유사하면서도, 서버 컴포넌트 기반으로 더 유연한 구조를 제공한다.
이번 글에서는 App Router의 기본 라우팅 방식과 Query String, URL 파라미터 사용 방법을 정리해본다.
Next.js의 기존 Page Router에서는 pages 폴더 아래 파일 이름이 곧 URL 경로가 되었다.
예시:
pages/index.tsx → /
pages/search.tsx → /search
하지만 App Router에서는 app 디렉토리 기반으로 라우팅을 설정하며, 페이지 파일 이름은 반드시 page.tsx로 고정된다.
예를 들어 /search 페이지를 만들고 싶다면 다음과 같이 구성한다.
app/
└─ search/
└─ page.tsx
즉, 폴더명이 URL 경로가 되고, 그 안의 page.tsx가 실제 페이지 컴포넌트 역할을 한다.
src/app/search/page.tsx
// src/app/search/page.tsx
export default function Page() {
return <div>Search 페이지</div>
}
이제 localhost:3000/search로 접속하면 해당 페이지가 렌더링된다.
App Router에서는 Query String과 URL 파라미터 모두 페이지 컴포넌트의 props로 전달된다.
searchParamsparams// src/app/search/page.tsx
export default async function Page({
searchParams,
}: {
searchParams: Promise<{ q: string }>
}) {
const { q } = await searchParams
return <div>Search 페이지 : {q}</div>
}
localhost:3000/search?q=사과로 접속하면 다음과 같이 출력된다.
Search 페이지 : 사과
searchParams는 Promise 형태로 전달await으로 값을 꺼내 사용async 함수 사용 가능이번에는 /book/[id] 형태의 동적 경로를 만들어본다.
src/app/book/[id]/page.tsx
export default function Page() {
return <div>book/[id] 페이지입니다.</div>
}
localhost:3000/book/1로 접속하면 해당 페이지가 렌더링된다.
이때 1은 URL 파라미터로 인식된다.
동적 경로에서 전달된 값을 사용하려면 params를 활용한다.
// src/app/book/[id]/page.tsx
export default async function Page({
params,
}: {
params: Promise<{ id: string }>
}) {
const { id } = await params
return <div>book/[id] 페이지 : {id}</div>
}
localhost:3000/book/100book/[id] 페이지 : 100/book/100 요청app/book 폴더 탐색[id] 폴더가 URL 파라미터와 매칭page.tsx 렌더링params.id 값이 100으로 전달App Router의 페이지는 기본적으로 Server Component이다.
따라서:
async 키워드 사용 가능이 구조 덕분에 데이터 패칭 로직이 훨씬 직관적으로 작성된다.
| 구분 | App Router 방식 |
|---|---|
| 라우팅 기준 | app 폴더 구조 |
| 페이지 파일명 | page.tsx 고정 |
| Query String | searchParams |
| URL 파라미터 | params |
| 기본 컴포넌트 | Server Component |
| 비동기 처리 | async/await 직접 사용 가능 |
app 디렉토리 기반 자동 라우팅을 사용한다.page.tsx이다.searchParams로,params로 전달된다.