본문 바로가기
스터디

[Next.js] Pages and Layouts(페이지와 레이아웃)

by rious275 2023. 8. 12.

Pages(페이지)

페이지는 각 라우트의 고유 UI이며, React와 같이 컴포넌트를 구성하여 내보내서 사용할 수 있다. 아래 이미지와 같이 앱 루트에 page.ts를 생성하여 /에 엑세스 할 수 있으며, 중첩된 폴더를 구성해 내부에 page.ts를 생성하면 해당 라우트에 엑세스 할 수 있다.

page 파일은 .js, .jsx 또는 .tsx 확장자를 사용할 수 있다.

ex_screenshot

Layouts(레이아웃)

layout.js 파일은 여러 페이지에 사용될 수 있는 공용 UI를 생성하며, 이 파일은 상태를 보존하며 리렌더링되지 않는다. 최초 앱 루트에 생성할 수 있지만, 라우트와 마찬가지로 하위에 중첩해서 사용할 수 있다.

중첩된 레이아웃의 경우, 하위로 갈수록 우선순위가 높아진다.

ex_screenshot

const DashboardLayout = ({ children }: PropTypes) => {
  return (
    <section>
      {/* 헤더 또는 사이드바와 같은 공용 UI가 포함된다. */}
      <nav></nav>

      {children}
    </section>
  );
};

export default DashboardLayout;

최상위에 있는 layout.ts을 루트 레이아웃이라 부른다. 앱 내의 모든 페이지에서 공용으로 적용되며, 루트 레이아웃에는 <html>, <body> 태그가 포함되어야 한다.

layout.ts 파일과 page.js 파일은 같은 폴더에 정의할 수 있으며, 레이아웃이 페이지를 감싸는 형태가 된다.

Root Layout(필수적으로 생성)

루트 레이아웃은 앱 루트의 최상위 레벨에 정의되며 모든 라우트에 적용된다. 이 파일을 활용해 서버에서 반환된 초기 HTML을 수정할 수 있다.

const RootLayout = ({ children }: PropTypes) => {
  return (
    <html lang="en">
      <body>{children}</body>
    </html>
  );
};

export default RootLayout;
알아두면 좋은 점

루트 레이아웃은 기본적으로 서버 컴포넌트이며, 클라이언트 컴포넌트로 설정할 수 없다.

Nesting Layouts(중첩 레이아웃)

각 라우트 내에 정의된 레이아웃은 해당 라우트 세그먼트에만 적용되며 해당 세그먼트가 활성화될 때 렌더링된다.

주의사항으로, <html><body> 태그는 루트 레이아웃에만 포함할 수 있다.

ex_screenshot

const DashboardLayout = ({ children }: PropTypes) => {
  return <section>{children}</section>;
};

export default DashboardLayout;

기본적으로 중첩된 레이아웃은 아래 이미지처럼 하위 레이아웃을 감싸는 형태가 된다.

ex_screenshot

Templates(템플릿)

template.ts는 각 하위 레이아웃 또는 페이지를 래핑한다는 점에서 레이아웃과 유사하다. 라우트 전체에 적용되고 상태를 유지하는 레이아웃과는 달리, 템플릿은 각 하위 레이아웃에 대해 새 인스턴스를 생성한다.

즉, 사용자가 템플릿을 공유하는 라우트 사이를 탐색할 때 컴포넌트의 새 인스턴스가 마운트되고, DOM 요소가 재생성되며, 상태는 보존되지 않으며, 이팩트가 다시 동기화된다.

템플릿 사용이 적합한 경우
  1. CSS 또는 애니메이션 라이브러리를 사용하여 애니메이션을 시작/종료할 경우
  2. useEffectuseState에 의존하는 기능(예: 페이지 조회 수 로깅)
  3. 기본 프레임워크 동작을 변경할 경우: 예를 들어, 레이아웃 내부의 서스펜스 바운더리는 레이아웃을 처음 로드할 때만 폴백을 표시하고 페이지를 전환할 때는 표시하지 않는다. 템플릿의 경우 각 탐색에 폴백이 표시된다.

위의 경우 템플릿이 적합하지만, Next.js에서는 템플릿을 사용해야 할 특별한 이유가 없는 한 레이아웃을 사용을 권장한다.

레이아웃과 템플릿이 함께 존재할 경우, 아래와 같은 형태가 된다.

<Layout>
  {/* 템플릿에는 고유 키가 부여된다. */}
  <Template key={routeParam}>{children}</Template>
</Layout>

head 태그 수정하기

앱 루트에서 내장 SEO 지원을 사용하여 titlemeta 등의 <head> HTML 요소를 수정할 수 있다.

메타데이터는 layout.js 또는 page.js 파일에서 Metadata 객체 또는 generateMetadata 함수를 내보내 정의할 수 있다.

import { Metadata } from 'next';

export const metadata: Metadata = {
  title: 'Next.js',
};

const Page = () => {
  return '...';
};

export default Page;
알아두면 좋은 점

루트 레이아웃에 <title><meta>와 같은 <head> 태그를 수동으로 추가하면 안된다. 위의 예시처럼 내장된 Metadata API를 사용해야 한다.