
폴더 하위 경로에 page.tsx 를 생성했을 뿐인데 페이지가 만들어지고 라우팅까지 처리되었다.
이는 Next.js의 파일 구조 기반 라우팅에 의해 가능한 것이다.
기존 리액트 프로젝트에서는 페이지 라우팅을 위해 react-router를 사용하여 번거로운 작업을 수행했었다면, 넥스트는 기본적으로 파일 구조 기반의 페이지 라우팅을 지원한다.
그렇기에 app 하위 경로의 page.tsx 만 추가해도 자동적으로 페이지 라우팅이 수행되는 것이다. app 하위 경로에서는 폴더 생성 후 page.tsx 생성을 통해 모든 페이지 라우팅을 자동으로 수행할 수 있다.
예시)
app/home/page.tsx : "url/home"app/home/detail/page.tsx : "url/home/detail"💡 유효하지 않은 경로 접속 시, 404 페이지 렌더링을 위한 컴포넌트는
app/not-found.tsx파일에 작성하면 된다.
프로젝트 생성 후, npm run dev 수행 시 자동적으로 layout.tsx 파일이 만들어졌을 것이다. 해당 파일이 존재하지 않으면 warning이 발생한다.
layout.tsx 는 무슨 파일일까?
layout.tsx 내부에 생성된 component는 하위 페이지들의 default component가 된다.
Next.js가 렌더링되고, 현재 URL 확인 후 layout.tsx 의 component를 기본적으로 렌더링한다. 이후에 하위 페이지 component를 렌더링 한다.
💡
layout.tsx는 무조건 Server Component여야 한다.
아래와 같이 폴더 구조를 예시로 들어보자.
📂 app
ㄴ 📂 list
ㄴ page.tsx
ㄴ layout.tsx
ㄴ page.tsx
/ 경로 접속 시, app/page.tsx 내부의 component가 렌더링될 것이다. 또한, default component인 app/layout.tsx 내부의 component도 렌더링될 것이다.
/list 경로 접속 시에는 어떨까? 당연히 app/list/page.tsx 내부의 component가 렌더링될 것이다.
또한 default component인 app/layout.tsx 내부의 component까지 렌더링 된다. 이는 Next.js가 제공하는 Layout System 때문이다. 이 기능을 사용하여 항상 존재해야 하는 Navagation Bar, Menu Bar 등의 Component를 쉽게 제작할 수 있다.
layout.tsx 파일은 app 바로 하위 경로에만 존재할 수 있는 것이 아니다. 특정 페이지를 위한 다른 레이아웃을 만들 수도 있다.
여러 레이아웃이 존재하면 어떻게 될까?
📂 app
ㄴ 📂 list
ㄴ layout.tsx
ㄴ page.tsx
ㄴ layout.tsx
ㄴ page.tsx
레이아웃이 여러개 존재한다면, 상쇄되는 것이 아니라 중첩된다. 상위 경로의 레이아웃과 현재 경로의 레이아웃이 함께 렌더링된다.
중첩되는 레이아웃의 특성상, 상위 레이아웃이 나타나지 않는 것을 원할 수도 있다. 이는 Route Groups 기능을 통해 해결할 수 있다.
💡 Root Layout에서만
html,body태그 사용이 가능하다.
Route Groups는 라우팅을 논리적으로 그룹화하는 것을 말한다.
Route Groups를 통해 라우팅을 그룹화하는 방법은 다음과 같다.

위처럼 괄호를 감싸 만든 폴더는 URL에 포함되지 않는다. 이렇게 논리적으로 라우팅 그룹을 만들 수 있으므로 레이아웃을 선택적으로 포함할 수 있고, 가독성 면에서의 장점도 존재한다.
특정 데이터의 상세 정보를 확인할 수 있는 페이지 등, 동적으로 경로를 생성해야 하는 경우가 있다.
Next.js로 동적 경로를 생성하는 방법은 다음과 같다.

해당 경로 폴더의 하위에 [id] 폴더를 생성하면 된다. 대괄호 안의 변수명은 자유롭게 작성하면 된다. 해당 변수명은 react-router 의 :id 와 동일한 역할을 한다.
이제 컴포넌트 내부에서는 동적 라우팅을 통해 생성된 변수의 값을 가져와 사용하면 된다. 변수의 값은 params 에 담겨있다.
export default function MovieDetail({
params: { id }
}: {
params: { id: string }
}) {
return <div>MovieDetail {id}</div>;
}