Next.js App Router에서 레이아웃 사용하기
Next.js의 App Router에서는 레이아웃이 파일 시스템 라우팅의 일부가 되었다.
예전처럼 모든 페이지에서 직접 <DefaultLayout>을 감싸는 방식도 가능하지만, 새 프로젝트라면 app/layout.tsx를 먼저 이해하는 편이 좋다.
기본 구조
App Router에서는 app 디렉토리 아래에 라우트 세그먼트를 만들고, 각 세그먼트에 특별한 파일을 배치한다.
page.tsx: 해당 경로에서 보여줄 페이지layout.tsx: 해당 경로와 하위 경로를 감싸는 레이아웃loading.tsx: 로딩 UIerror.tsx: 에러 UInot-found.tsx: 404 UI
가장 기본이 되는 파일은 루트 레이아웃이다.
// app/layout.tsx
import type { Metadata } from 'next'
import './globals.css'
export const metadata: Metadata = {
title: 'My App',
description: 'Next.js App Router example',
}
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="ko">
<body>{children}</body>
</html>
)
}루트 레이아웃은 반드시 html과 body 태그를 포함해야 한다.
여기에 전역 CSS, 공통 폰트, 전역 provider, 기본 메타데이터처럼 앱 전체에 필요한 설정을 모아둘 수 있다.
페이지 만들기
page.tsx는 특정 URL에서 실제로 렌더링되는 UI다.
// app/page.tsx
export default function HomePage() {
return <main>홈 화면입니다.</main>
}app/page.tsx는 / 경로가 되고, app/posts/page.tsx는 /posts 경로가 된다.
// app/posts/page.tsx
export default function PostsPage() {
return <main>포스트 목록입니다.</main>
}중첩 레이아웃 만들기
특정 경로 아래에서만 다른 공통 UI가 필요하다면 해당 세그먼트에 layout.tsx를 추가한다.
// app/posts/layout.tsx
export default function PostsLayout({ children }: { children: React.ReactNode }) {
return (
<section>
<aside>포스트 카테고리</aside>
<div>{children}</div>
</section>
)
}이 레이아웃은 /posts와 /posts/[slug] 같은 하위 경로에 적용된다.
루트 레이아웃이 앱 전체를 감싸고, posts 레이아웃이 그 안에서 포스트 영역만 다시 감싸는 구조가 된다.
Pages Router 방식과 다른 점
예전 Pages Router에서는 페이지 컴포넌트 안에서 직접 레이아웃 컴포넌트를 import해 감싸는 경우가 많았다.
import DefaultLayout from '@/components/layout/DefaultLayout'
export default function HomePage() {
return (
<DefaultLayout>
<main>홈 화면입니다.</main>
</DefaultLayout>
)
}App Router에서는 이 반복을 파일 구조로 옮길 수 있다.
공통 UI는 layout.tsx에 두고, 페이지는 해당 경로의 본문에 집중하는 식이다.
언제 layout에 넣고 언제 component로 둘까요?
여러 페이지에 항상 적용되는 구조라면 layout.tsx에 둔다.
- 상단 내비게이션
- 푸터
- 공통 사이드바
- 인증 provider
- 테마 provider
반대로 특정 화면 내부에서만 쓰는 UI라면 일반 컴포넌트로 분리하는 편이 낫다.
- 카드 목록
- 검색 필터
- 상세 페이지의 추천 영역
- 특정 폼의 입력 그룹
라우팅 계층과 생명주기를 공유해야 하는 공통 구조는 layout, 재사용 가능한 화면 조각은 component로 나누면 이해하기 쉽다.
참고 자료




