[Next 13] Routing - 페이지와 레이아웃

Jeongho·2023년 9월 3일
0

Next 13의 App Router는 page, layout, template를 쉽게 생성할 수 있는 새로운 파일 규칙이 도입되었습니다.

Page

  • 페이지는 경로의 고유한 UI입니다. 파일에서 컴포넌트를 export해 페이지를 정의할 수 있습니다.
  • 중첩된 폴더를 사용하여 경로와 page.js 파일을 정의하여 해당 경로에 공개적으로 접근할 수 있도록 합니다.
// `app/page.tsx` is the UI for the `/` URL
export default function Page() {
  return <h1>Hello, Home page!</h1>
}

// `app/dashboard/page.tsx` is the UI for the `/dashboard` URL
export default function Page() {
  return <h1>Hello, Dashboard Page!</h1>
}
  • page.js 파일은 항상 리프(경로의 최하단) 하위 트리입니다.
  • 기본적으로 서버 컴포넌트 이지만 클라이언트 컴포넌트로 사용할 수도 있습니다.
  • page.js는 데이터를 가져올 수 있습니다.

Layout

  • 레이아웃은 여러 페이지에서 공유되는 UI입니다. 탐색 시 레이아웃은 상태를 유지하고 대화형을 유지하며 다시 렌더링되지 않습니다. (레이아웃은 중첩될 수 있습니다)
  • layout.js은 children을 받아 렌더링합니다.
// 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>
  )
}
  • 최상위 레이아웃을 루트 레이아웃이라 합니다. 이 필수 레이아웃은 애플리케이션의 모든 페이지에서 공유되며, html 및 body 태그가 포함되어야 합니다. (React와 달리 index.html에 App 컴포넌트를 렌더링하는 방식이 아닙니다!)
  • 모든 경로 세그먼트는 선택적으로 자체 레이아웃을 정의할 수 있습니다.
  • 경로의 레이아웃은 기본적으로 중첩 됩니다. 각 상위 레이아웃은 React children prop을 사용하여 그 아래의 하위 레이아웃을 래핑합니다.
  • 경로 그룹을 사용하여 공유 레이아웃 안팎에서 특정 경로 세그먼트를 선택할 수 있습니다.
  • 레이아웃은 기본적으로 서버 컴포넌트이지만 클라이언트 컴포넌트로 설정할 수 있습니다.
  • 레이아웃은 데이터를 가져올 수 있습니다.
  • 상위 레이아웃과 해당 하위 레이아웃 간에 데이터 전달하는 것은 불가능합니다.
    • 하지만 경로에서 동일한 데이터를 두 번 이상 가져올 수 있으며 React는 성능에 영향을 주지 않고 자동으로 요청의 중복을 제거합니다.
  • 레이아웃은 현재 경로 세그먼트에 접근할 수 없습니다. 배관 세그먼트()에 액세스하려면 클라이언트 구성 요소에서 useSelectedLayoutSegment 또는 useSelectedLayoutSegments를 사용할 수 있습니다.

루트 레이아웃

  • 루트 레이아웃은 디렉터리의 최상위 수준에서 정의되며 app 모든 경로에 적용됩니다. 이 레이아웃을 사용하면 서버에서 반환된 초기 HTML을 수정할 수 있습니다.
// app/layout.tsx
export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en">
      <body>{children}</body>
    </html>
  )
}
  • app 디렉터리에는 루트 레이아웃이 포함되어야 합니다.
  • Next.js는 루트 레이아웃을 자동으로 생성하지 않으므로 루트 레이아웃을 정의하고 html, body 태그를 정의해야 합니다.
  • 내장된 SEO 지원을 사용하여 title HTML 요소를 관리할 수 있습니다.
  • 경로 그룹을 사용하여 여러 루트 레이아웃을 생성할 수 있습니다.
  • 루트 레이아웃은 기본적으로 서버 컴포넌트이며 클라이언트 컴포넌트로 설정할 수 없습니다.

중첩 레이아웃

  • app/dashboard/layout.js 내부에 정의된 레이아웃은 특정 경로 세그먼트(/dashboard/)에 적용되고 해당 세그먼트가 활성화되면 렌더링됩니다.
  • 기본적으로 파일 계층 구조의 레이아웃은 중첩됩니다. childrend prop을 통해 하위 레이아웃을 래핑합니다.
// app/dashboard/layout.tsx
export default function DashboardLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return <section>{children}</section>
}
  • 루트 레이아웃에만 html과 body가 포함될 수 있습니다. (당연하죠?)
  • 경로 그룹을 사용하여 공유 레이아웃 안팎에서 특정 경로 세그먼트를 선택할 수 있습니다.

Template

  • 템플릿은 각 하위 레이아웃이나 페이지를 래핑한다는 점에서 레이아웃과 유사합니다.
  • 경로 전반에 걸쳐 지속되고 상태를 유지하는 레이아웃과 달리 템플릿은 탐색 시 각 하위 항목에 대해 새 인스턴스를 만듭니다.
  • 이는 사용자가 템플릿을 공유하는 경로 사이를 탐색할 때 컴포넌트의 새 인스턴스가 마운트되고 DOM 요소가 다시 생성되며 상태가 유지되지 않고 Effect가 다시 동기화된다다는 것을 의미합니다.
  • 이러한 특정 동작이 필요한 경우가 있을 수 있으며 이때 템플릿은 레이아웃보다 더 적합한 옵션입니다.
    • useEffect 및 useState에 의존하는 기능
    • 기본 프레임워크 동작을 변경합니다. 예를 들어 레이아웃 내부의 정지 경계는 레이아웃이 처음 로드될 때만 대체를 표시하고 페이지를 전환할 때는 표시하지 않습니다. 템플릿의 경우 각 탐색에 대체가 표시됩니다.
  • 템플릿은 template.js 파일을 생성해 만들 수 있고 children을 받아야 합니다.
// app/template.tsx
export default function Template({ children }: { children: React.ReactNode }) {
  return <div>{children}</div>
}
  • Template는 Layout과 children 사이에 렌더링 됩니다.
<Layout>
  {/* Note that the template is given a unique key. */}
  <Template key={routeParam}>{children}</Template>
</Layout>

Modifying head

  • 앱 디렉토리에서는 내장된 SEO 지원을 사용하여 title, meta와 같은 head HTML 요소를 수정할 수 있습니다.
  • 메타데이터는 layout.js 또는 page.js 파일의 메타데이터 객체 또는 generateMetadata 함수를 내보내 정의할 수 있습니다.
import { Metadata } from 'next'
 
export const metadata: Metadata = {
  title: 'Next.js',
}
 
export default function Page() {
  return '...'
}

Reference

profile
주도적으로 문제를 정의하고 코드를 통해 해결합니다.

0개의 댓글