Defining Routes
Routes를 정의하고 구조를 잡는 방법에 대해서 알아본다.
Creating Routes
Next.js는 폴더가 routes를 정의하는 파일 시스템 기반의 router를 사용한다.
각각의 폴더는 URL segment에 매핑되는 route segment를 나타낸다. 중첩된 route를 만들려면 폴더를 중첩시키면 된다.
page.js라는 특수한 파일은 route의 진입접을 위해 사용된다.
위의 예에서 /dashboard/analytics URL 경로는 page.js 파일이 없기 때문에 공개적으로 접근이 불가능하다. 이 폴더는 컴포넌트, 스타일, 이미지나 기타 배치 파일을 저장하는데 사용될 수 있다.
Creating UI
각각의 route segment에서 UI를 만들기 위해 특별한 파일 컨벤션이 사용된다. 가장 자주사용되는 것에는 pages와 layouts가 있다.
pages는 route에 고유한 UI를 표시하고, layouts은 여러 route에서 공유되는 UI를 보여준다.
예를 들어 첫 페이지를 만들 때 page.js 파일을 app 디렉토리에 넣고 React 컴포넌트를 export한다.
// app/page.tsx
export default function Page() {
return <h1>Hello, Next.js!</h1>
}
Pages and Layouts
Next.js의 App Router는 새로운 파일 컨벤션으로 페이지를 만들고 레이아웃이나 템플릿을 공유하는것을 편하게 해준다. 이 페이지에서는 Next.js의 여러 특별한 파일들을 어떻게 사용하는지 알려준다.
Pages
page는 route에서 유일한 UI이다. page.js에서 컴포넌트를 export 함으로써 page를 정의할 수 있다. 중첩된 폴더로 route를 정의하고 page.js 파일로 route의 진입점을 만든다.
app 디렉토리에 page.js 파일을 만들어서 첫 번째 페이지를 만든다.
// app/page.tsx
// `app/page.tsx` is the UI for the `/` URL
export default function Page() {
return <h1>Hello, Home page!</h1>
}
// app/dashboard/page.tsx
// `app/dashboard/page.tsx` is the UI for the `/dashboard` URL
export default function Page() {
return <h1>Hello, Dashboard Page!</h1>
}
* - 페이지는 언제나 root subtree의 leaf이다.
- 페이지 파일에 .js, .jsx, .tsx 확장자를 쓸 수 있다.
- root segment에는 page.js 파일이 필요하다.
- 페이지는 기본적으로 서버 컴포넌트이지만 필요하다면 클라이언트 컴포넌트로 만들 수 있다.
- 페이지는 데이터를 fetch할 수 있다. Data Fetching 섹션 참조.
Layouts
layout은 여러 페이지에서 공유되는 UI이다. 탐색을 할 때 layout은 상태를 유지하고 여전히 상호작용가능하고 리렌더링 되지 않는다. layout역시 중첩될 수 있다.
기본적으로 layout.js에 React 컴포넌트를 export 함으로써 layout을 정의할 수 있다. 컴포넌트는 렌더링 중에 하위 레이아웃(존재하는 경우) 또는 하위 페이지로 채워질 children prop을 받아들인다.
// app/dashboard/layout.tsx
export default function DashboardLayout({
children, // will be a page or nested layout
}: {
children: React.ReactNode
}) {
return (
<section>
{/* Include shared UI here e.g. a header or sidebar */}
<nav></nav>
{children}
</section>
)
}
*알아두면 좋은것
- 가장 상위의 레이아웃을 Root Layout이라고 부른다. 필수 레이아웃인 root layout은 하나의 애플리케이션의 모든 페이지에 공유된다. Root layout은 html, body 태그를 필수적으로 포함한다.
- route segment는 자신 고유의 layout을 (optionally)정의할 수 있다. 이러한 layout은 해당 segment 전체 페이지에 공유될 수 있다.
- route안의 layout은 기본적으로 중첩되어있다. 부모 layout은 React children prop을 사용하여 자식 layout을 감싼다.
- 공유된 layout의 안밖으로 특별한 route segment 선택하기 위해 Route Groups를 사용할 수 있다. (맞나?)
- layout은 데이터를 fetch 할 수 있다. Data Fetching 섹션 참조
- 부모 layout에서 자식으로 데이터를 넘겨줄 수 없다. 하지만 route에서 한 번 이상 같은 데이터를 받아올 수 있고 React는 성능에 영향을 주지 않고 요청의 중복을 자동으로 제거한다.
- layout은 현재 route segment에 접근할 수 없다. route segment에 접근하기 위해 클라이언트 컴포넌트 내에서 useSelectedLayoutSegment나 useSelectedLayoutSegments를 사용할 수 있다.
- layout에서 .js, .jsx, .tsx 확장자를 사용할 수 있다.
- layout.js와 page.js 파일은 같은 폴더에서 정의할 수 있다. layout이 page를 감싼다.
Root Layout (Required)
root layout은 app 디렉토리 최상단에 정의되고 모든 route에 적용한다. 이 레이아웃을 사용하면 서버에서 반환되는 초기 HTML을 수정할 수 있다.
* 알아두면 좋을 것
- app 디렉토리는 root layout을 필수로 포함해야 한다.
- Next.js는 자동으로 html, body태그를 생성하지 않기 때문에 root layout은 html, body태그를 필수로 포함해야 한다.
- HTML 요소를 관리하기 위해 built-in SEO support를 사용할 수 있다. (예를들면 title 요소)
- 여러 root layout을 만들기 위해 route groups를 사용할 수 있다.
- root layout은 기본적으로 서버 컴포넌트이고 클라이언트 컴포넌트로 사용할 수 없다.
- root layout은 pages router에서의 _app.js파일과 _document.js 파일을 대체한다.
Nesting Layouts
특정 폴더에 정의된(예 app/dashboard/layout.js) layout은 특정 route segment에 적용되고(예 acme.com/dashboard) 해당 segment가 활성화될 때 렌더링된다. 기본적으로 파일 계층의 레이아웃은 중첩된다. 즉, children prop으로 자식 레이아웃을 감싼다.
// app/dashboard/layout.tsx
export default function DashboardLayout({
children,
}: {
children: React.ReactNode
}) {
return <section>{children}</section>
}
위의 두 레이아웃을 결합하는 경우 root layout(app/layout.js)은 dashboard layout(app/dashboard/layout.js)을 감싸고 이것은 route segment를 app/dashboard/* 내부로 감싼다.
다음과 같이 중첩된다.
공유된 layout의 안밖으로 특별한 route segment 선택하기 위해 Route Groups를 사용할 수 있다. (맞나?)
Templates
탬플릿은 자식 레이아웃이나 페이지를 감싼다는 측면에서 layout과 비슷하다. 여러 routes에 걸쳐 유지되고 상태를 유지하는 레이아웃과는 다르게 탬플릿은 탐색중인 자식에 대해 새 인스턴스를 만든다. 즉, 사용자가 탬플릿을 공유하는 route간 이동을 할 때 컴포넌트의 새로운 인스턴스가 mount되고, DOM 요소가 다시 생성되고 상태는 유지되지 않으며 효과가 다시 동기화된다.
이러한 특수한 동작이 필요한 경우가 있을 수 있고, 그 때는 레이아웃보다 탬플릿이 더 적합하다. 예를 들면
- CSS나 애니메이션 라이브러리를 사용한 애니메이션을 시작/종료 할 때
- useEffect(예 : logging page views) 및 useState(예 : a per-page feedback form)에 의존하는 기능
- 프레임워크 기본동작을 바꾸기 위해서. 예를 들면 레이아웃 내부의 suspense boundary는 레이아웃이 처음 로드될 때만 fallback을 표시하고 페이지 이동을 할 때는 표시하지 않는다. 탬플릿을 사용하는 경우 각 탐색에 fallback을 표시한다.
* 탬플릿을 사용할 이유가 있는게 아니라면 레이아웃을 사용하는 것을 추천한다.
template.js 파일에서 React 컴포넌트를 export 함으로써 탬플릿을 정의할 수 있다. 이 컴포넌트는 중첩될 segments를 children prop으로 받아들인다.
// app/template.tsx
export default function Template({ children }: { children: React.ReactNode }) {
return <div>{children}</div>
}
레이아웃과 탬플릿을 포함한 route segment는 다음과 같이 렌더된다.
<Layout>
{/* Note that the template is given a unique key. */}
<Template key={routeParam}>{children}</Template>
</Layout>
Modifying <head>
app 디렉토리에서 built-in SEO support를 사용하여 title, meta 태그 등<head> HTML 요소를 수정할 수 있다.
layout.js 파일이나 page.js 파일에서 metadata 객체나 generateMetadata 함수를 export 함으로써 metadata를 정의 할 수 있다.
// app/page.tsx
import { Metadata } from 'next'
export const metadata: Metadata = {
title: 'Next.js',
}
export default function Page() {
return '...'
}
* 알면 좋은것
root layout에 <title> 및 <meta> 같은 <head> 태그를 수동으로 추가하면 안된다. 대신 streaming 및 <head> 요소 중복 제거와 같은 고급 요구사항을 자동으로 처리하는 Metadata API를 사용해야 한다. Metadata API에 대한 자세한 사항은 API reference 참고.
Reference
- https://nextjs.org/docs/app/building-your-application/routing/defining-routes
Routing: Defining Routes | Next.js
We recommend reading the Routing Fundamentals page before continuing. This page will guide you through how to define and organize routes in your Next.js application. Each folder represents a route segment that maps to a URL segment. To create a nested rout
nextjs.org
- https://nextjs.org/docs/app/building-your-application/routing/pages-and-layouts
Routing: Pages and Layouts | Next.js
Using App Router Features available in /app
nextjs.org
'개인공부' 카테고리의 다른 글
Next.js Docs (6) Dynamic Routes (0) | 2023.06.20 |
---|---|
Next.js Docs (5) Route Groups (0) | 2023.06.16 |
Next.js Docs (4) Linking and Navigating (0) | 2023.06.13 |
Next.js Docs (2) Routing Fundamentals (0) | 2023.06.07 |
Next.js Docs (1) React Essentials (0) | 2023.06.02 |
댓글