본문 바로가기

개발/Next.js

[Next.js] Layout, Metadata

Layouts

레이아웃은 화면의 틀을 의미하며 사이트의 느낌과 디자인을 전체적으로 통일시켜 줍니다. layout.js 또는 layou.tsx 이름의 파일을 사용합니다. 레이아웃은 chlidren prop을 통해 내부에 컴포넌트를 받아서 사용합니다. 기본적으로 Next는 app 폴더에 하나의 layout을 제공해 주고, 하나의 layout 파일은 항상 존재해야 합니다.

// 기본으로 제공되는 layout.tsx
export const metadata = {
  title: 'Next.js',
  description: 'Generated by Next.js',
}

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en">
      <body>
        {/* 해당 부분에 공통적으로 적용시키고 싶은 레이아웃 생성 */}
        {children}
      </body>
    </html>
  )
}

Nested Layouts

전체적인 레이아웃은 app 폴더에 만들어진 layout.tsx가 담당한다면, 각 화면별로 원하는 레이아웃을 적용하려면 각 폴더에 layout.tsx 파일을 생성하면 됩니다.

 

의문. 그룹화시킨 폴더 내에 layout 파일을 만들면 해당 그룹 안에 있는 화면에 전부 적용이 되는가?
네, 전부 적용됩니다. 그룹화 폴더뿐만 아니라 dynamic 라우트 폴더에서도 적용이 됩니다.

 

Multiple Root Layouts

기본적인 레이아웃을 바꾸고 싶다면 그룹화를 사용하는 방법이 있습니다. 프로젝트를 원하는 레이아웃에 따라 그룹을 나누어서 사용하는 방법입니다.

 

적용하고 싶은 레이아웃이 두 가지라고 가정하겠습니다. 그렇다면 app 폴더 밑에 두 그룹을 만들어서 사용하면 됩니다. 아래 이미지와 같이 말입니다.

예시 사진

그런 다음 각 폴더에 layout.tsx를 생성하면 각각 화면에 원하는 레이아웃을 적용할 수 있습니다.

 

그런데 이때 몇 가지 조건이 필요합니다. (제가 파악한 것만 적혀있습니다. 추가적인 조건이 존재할 수 있습니다)

  • app 폴더 밑에는 기본적으로 하나의 page와 layout이 존재해야 합니다. 그렇기에 시작 페이지를 담당할 page를 두 폴더 중 하나의 폴더를 선택해 생성해주어야 합니다. layout 파일은 두 폴더에 모두 존재해야 합니다.
  • 두 개의 레이아웃 파일은 일반 layout 파일이 아닌 Root layout 파일이기 때문에 html과 body 태그를 포함해야 합니다.
  • 만약 not-found 파일이 존재한다면 해당 파일도 폴더를 선택해 생성해야 합니다.

최종 예시

Routing metadata

기본으로 생성된 레이아웃 파일을 보면 metadata라는 object가 export 되고 있는 것을 볼 수 있습니다.

export const metadata = {
  title: 'Next.js',
  description: 'Generated by Next.js',
}

 

해당 데이터는 각 페이지에 대해서 정의하면서 검색 엔진에게 정보를 제공하는 역할을 합니다. 또한 head 태그에 적용되는 meta 태그 및 title 태그의 역할도 포함하고 있습니다.

 

layout과 page에서 metadata를 다루는 두 가지 방법이 있습니다. 단, 두 가지 방법 중 한 가지를 선택해서 사용해야 합니다.

 

1. 정적 metadata객체 export

2. 동적 generateMetadata 함수 export

import { Metadata } from "next";

type Props = {
    params: Promise<{productId: string}>;
}

export const generateMetadata = async ({params}: Props): Promise<Metadata> => {
    const {productId} = (await params);
    return {
        title: `Product ${productId}`,
    }
}

export default async function ProductDetail({params}: Props) {
    const productId = (await params).productId;
    return <h1>Details about product {productId}</h1>
}

 

메타데이터 규칙

  • 서버 컴포넌트에서만 사용할 수 있습니다. 따라서 해당 규칙에 따라서 UI는 클라이언트 컴포넌트를 사용해 따로 분리하고, page에서 불러서 사용하는 것이 바르게 사용하는 방법입니다.
  • layout의 메타데이터는 포함되는 페이지의 정보를 page의 메타데이터는 해당하는 특정 페이지의 정보를 가집니다.
  • 루트에서 시작하는 탑 다운 순서
  • 여러 메타데이터는 merge 되며 page의 메타데이터는 layout 메타데이터에 overriding 됩니다.

title metadata

메타데이터 중 title은 더 세세하게 조절할 수 있습니다. title에 문자열이 아닌 객체를 통해 컨트롤할 수 있습니다. 타입스크립트를 사용하는 경우 Metadata 타입을 import 해서 사용해야 합니다.

import { Metadata } from "next";

export const metadata = {
  title: {
    default: "",
    template: "",
    absolute: "",
  }
};

 

세 가지 옵션이 제공됩니다.

  • default: 기본적으로 해당 메타데이터를 사용하는 페이지의 title 값입니다.
  • template: %s를 통해 특정 페이지의 title 값을 가져와 적용합니다.
  • absolute: template를 무시하고 absolute의 값을 해당 페이지의 title로 변경합니다.

 

참고

https://nextjs-ko.org/docs/app/api-reference/functions/generate-metadata#generatemetadata-function

https://nextjs-ko.org/docs/app/building-your-application/routing/layouts-and-templates

https://www.youtube.com/watch?v=b4ba60j_4o8&list=PLC3y8-rFHvwhIEc4I4YsRz5C7GOBnxSJY

'개발 > Next.js' 카테고리의 다른 글

[Next.js] Navigation part.2  (0) 2025.06.13
[Next.js] Navigation  (0) 2025.06.12
[Next.js] 폴더 구조 활용(private, group)  (0) 2025.06.02
[Next.js] catch-all segments, custom not found page  (0) 2025.05.30
[Next.js] Dynamic routes  (0) 2025.05.28