Next.js 13 - 1. Routing - 1.3. Pages and Layouts

Chaewon Kang·2023년 4월 21일
0

Pages and Layouts (페이지와 레이아웃)

Next.js 13의 앱 라우터는 페이지, 공유 레이아웃, 템플릿을 쉽게 생성할 수 있는 파일 컨벤션들을 제공합니다. 이 페이지에서는 이러한 특별한 파일들을 Next.js 애플리케이션에서 어떻게 사용할 수 있는지 알아볼 겁니다.

Pages (페이지)

하나의 페이지는 하나의 루트에 단일한 UI를 나타냅니다. page.js파일에 컴포넌트를 익스포트함으로써 페이지들을 정의할 수 있습니다. 루트를 정의하기 위해 중첩된 폴더들을 사용하고, 루트에 공개적으로 접근 가능하도록 하기 위해 page.js파일을 사용합니다.

app 디렉토리 내에 page.js를 추가해서 첫번 째 페이지를 생성해 보세요.

// app/page.js

export default function Page() {
	return <h1>Hello, Next.js!</h1>;
}

알아두면 좋은 것:

  • 하나의 페이지는 항상 루트 서브 트리의 잎사귀입니다.
  • .js, .jsx, 또는 .tsx 파일 확장자 또한 페이지에 사용될 수 있습니다.
  • 하나의 page.js는 루트 세그먼트를 공개적으로 접근 가능하도록 하기 위해 필요합니다.
  • 페이지들은 기본적으로 서버 컴포넌트이지만, 클라이언트 컴포넌트로 만들 수도 있습니다.
  • 페이지는 데이터를 페칭할 수 있습니다. 데이터 가져오기 페이지를 참조하세요.

Layouts (레이아웃)

레이아웃은 여러 페이지들이 공유하는 UI 입니다. 네비게이션에서, 레이아웃은 상태를 보존하고, 인터랙티브한 상태를 유지하며, 리렌더링 하지 않습니다. 레이아웃 또한 중첩할 수 있습니다.

layout.js 파일에 리액트 컴포넌트를 default로 익스포트해서 레이아웃을 정의할 수 있습니다. 해당 컴포넌트는 반드시 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>
    );
}

알아두면 좋은 것:

  • 가장 상단의 레이아웃을 루트 레이아웃이라고 부릅니다. 이 필수적인 레이아웃은 애플리케이션 전반에 걸쳐 모든 페이지가 공유하게 됩니다. 루트 레이아웃은 htmlbody태그를 꼭 포함해야 합니다.
  • 어떤 루트 세그먼트들은 선택적으로 각각의 레이아웃을 정의할 수 있습니다. 이렇게 정의된 레이아웃들은 세그먼트 안의 모든 페이지가 공유하게 됩니다.
  • 한 루트 안의 레이아웃들은 기본적으로 중첩됩니다. 각각의 부모 레이아웃은 리액트의 children prop을 이용하여 아래에 있는 자식 레이아웃들을 감싸게 됩니다.
  • 공유된 레이아웃들의 내외부에서 특정한 루트 세그먼트를 도입하기 위해 루트 그룹을 사용할 수 있습니다.
  • 레이아웃들은 기본적으로 서버 컴포넌트이지만 클라이언트 컴포넌트로 사용할 수도 있습니다.
  • 레이아웃은 데이터를 가져올 수 있습니다. 데이터 가져오기 페이지를 참조하세요.
  • 부모 레이아웃과 자식들 사이에 데이터를 전달하는 것은 불가능합니다. 그러나, 한 루트에서 같은 데이터를 여러 번 가져올 수 있습니다. 리액트는 퍼포먼스에 영향을 주지 않으면서 자동으로 중복된 리퀘스트들을 제거할 겁니다.
  • .js, .jsx, 또는 .tsx 파일 확장자 또한 레이아웃에 사용될 수 있습니다.
  • layout.jspage.js파일은 같은 폴더 안에 정의될 수 있습니다. 레이아웃은 페이지를 감싸게 될 겁니다.

Root Layout (Required) (루트 레이아웃)

루트 레이아웃은 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> 태그를 반드시 정의해야 합니다.
  • <head> HTML 요소들을 관리하기 위해 빌트인 SEO 서포트를 사용할 수 있습니다. 예를 들어 <title> 요소와 같이요.
  • 여러 개의 루트 레이아웃을 만들기 위해 루트 그룹을 사용할 수 있습니다. 여기서 예시를 참조하세요.
  • 루트 레이아웃은 기본적으로 서버 컴포넌트이며, 클라이언트 컴포넌트가 될 수 없습니다.

Nesting Layouts (중첩 레이아웃)

하나의 폴더 안에 정의된 레이아웃은 (예를 들면 app/dashboard/layout.js) 특정한 루트 세그먼트 (예를 들면 acme.com/dashboard) 에 적용되며, 이 세그먼트가 활성된 상태일 때 렌더됩니다. 기본적으로, 파일 위계 안의 레이아웃들은 중첩되어 있으며, 이는 children prop 을 통해 자식 레이아웃들을 감싼다는 의미입니다.

// app/dashboard/layout.tsx

export default function DashboardLayout({
	children,
}: {
	children: React.ReactNode,
}) {
	return <section>{children}</section>;
}

만약 위 예시의 두 레이아웃을 합치려고 한다면, 루트 레이아웃 (app/layout.js) 가 app/dashboard/* 안의 루트 세그먼트를 감싸는 dashboard 레이아웃 (app/dashboard/layout.js)를 감쌀 겁니다.

두 개의 레이아웃은 아래와 같이 중첩됩니다:

공유 레이아웃 안팎으로 특정 루트 세그먼트를 도입하기 위해서는 루트 그룹을 사용할 수 있습니다.

Templates (템플릿)

템플릿은 각각의 자식 레이아웃이나 페이지를 감싼다는 점에서 레이아웃과 비슷합니다. 루트를 가로질러 보존되고 상태를 유지하는 레이아웃과 다르게, 템플릿은 네비게이션 상의 각각의 자식을 위해 새로운 인스턴스를 생성합니다. 이는 유저가 하나의 템플릿을 공유하는 루트 사이사이를 탐방할 때, 컴포넌트의 새로운 인스턴스들이 마운트되고, DOM 요소들이 재생성되고, 상태가 보존되지 않으며, 이펙트들이 다시 조율된다는 의미입니다.

이러한 특정 행동들을 필요로 할 때가 있을 겁니다. 그리고 템플릿은 레이아웃보다 더 좋은 옵션이 될 수 있습니다. 예를 들어:

  • 애니메이션 라이브러리나 CSS를 이용한 애니메이션을 시작하거나 끝내는 경우
  • useEffect에 의존하는 기능들 (예를 들어 페이지 뷰를 기록) 또는 useState (페이지 기반의 피드백 양식)
  • 기본적인 프레임워크의 행동 양식을 바꿔야 하는 경우. 이를테면, 레이아웃 안의 서스펜스 바운더리는 레이아웃이 로드되는 맨 처음에 폴백만을 보여주고, 페이지를 스위칭할 때는 보여주지 않습니다. 템플릿은 모든 네비게이션에서 폴백이 보여집니다.

추천: 템플릿을 사용해야 할 특별한 이유가 없는 경우 레이아웃을 사용하는 것을 추천해요.

템플릿은 template.js 파일 안에 디폴트 리액트 컴포넌트를 익스포트 해서 정의할 수 있습니다. 이 컴포넌트는 children prop을 받게 되며, 이는 중첩 세그먼트가 됩니다.

// app/template.tsx

export default function Template({ children }: {
	children: React.ReactNode
)} {
	return <div>{children}</div>
}

레이아웃이나 템플릿과 함께 루트 세그먼트의 렌더된 결과물은 아래와 같을 겁니다:

// Output

<Layout>
	{/* 템플릿은 고유한 키를 갖는다는 점을 기억하세요 */}
    <Template key={routeParam}>{children}</Template>
</Layout>

Modifying <head> (<head 태그 수정하기)

app 디렉토리 안에서, 빌트인 SEO 서포트를 통해 <title>이나 <meta> 와 같은 <head> HTML 요소들을 수정할 수 있습니다.

메타데이터들은 layout.jspage.js 파일 안에서 metadata 객체를 익스포트하거나, generateMetadata 함수를 통해 정의될 수 있습니다.

// app/page.tsx

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

export default function Page() {
	return '...'
}

알아두면 좋은 것: 수동으로 <title>이나 <meta> 와 같은 <head> 태그를 루트 레이아웃에 적용하면 안 됩니다. 대신에, 반드시 자동으로 향상된 피필요 조건들을 핸들링하는 메타데이터 API를 사용해야 합니다. (예를 들어 스트리밍이나 <head> 태그 중복을 제거하는 등)

profile
문학적 상상력과 기술적 가능성

0개의 댓글