icon안동민 개발노트

레이아웃 컴포넌트 생성 및 중첩


 Next.js의 레이아웃 시스템은 애플리케이션의 구조를 효율적으로 관리하고 일관된 UI를 유지하는 데 중요한 역할을 합니다.

 이 절에서는 레이아웃 컴포넌트의 심화 내용과 중첩 레이아웃 구현 방법에 대해 알아보겠습니다.

layout.js 파일의 역할

 layout.js 파일은 여러 페이지에서 공유되는 UI 요소를 정의합니다.

 주요 특징은 다음과 같습니다.

  1. 자동으로 자식 레이아웃이나 페이지를 감싸줍니다.
  2. 라우트 간 이동 시 상태를 유지합니다.
  3. 서버 컴포넌트로 동작하여 초기 로드 성능을 최적화합니다.

 기본 구조

app/layout.js
export default function Layout({ children }) {
  return (
    <div>
      {/* 공통 UI 요소 */}
      <main>{children}</main>
    </div>
  )
}

루트 레이아웃과 중첩 레이아웃의 관계

  1. 루트 레이아웃 : app/layout.js에 정의되며, 모든 페이지에 적용됩니다.
  2. 중첩 레이아웃 : 특정 라우트나 라우트 그룹에 대해 추가적인 레이아웃을 정의합니다.

 중첩 레이아웃 예시

app/dashboard/layout.js
export default function DashboardLayout({ children }) {
  return (
    <div>
      <nav>{/* 대시보드 네비게이션 */}</nav>
      <main>{children}</main>
    </div>
  )
}

 이 레이아웃은 /dashboard 경로 아래의 모든 페이지에 적용되며, 루트 레이아웃 내부에 중첩됩니다.

레이아웃 간 데이터 흐름

 레이아웃 간 데이터 공유는 주로 컨텍스트나 상태 관리 라이브러리를 통해 이루어집니다.

 하지만 레이아웃 자체는 서버 컴포넌트이므로 클라이언트 상태를 직접 다루지 않습니다.

 데이터 흐름 예시

app/layout.js
import { ThemeProvider } from './ThemeContext'
 
export default function RootLayout({ children }) {
  return (
    <html>
      <body>
        <ThemeProvider>{children}</ThemeProvider>
      </body>
    </html>
  )
}
app/dashboard/layout.js
import { useTheme } from '../ThemeContext'
 
export default function DashboardLayout({ children }) {
  const theme = useTheme()
  return (
    <div className={theme}>
      <nav>{/* 대시보드 네비게이션 */}</nav>
      <main>{children}</main>
    </div>
  )
}

 이 예시에서 ThemeProvider는 루트 레이아웃에서 정의되고, 중첩된 대시보드 레이아웃에서 사용됩니다.

4장 중첩 라우트 구현과의 연관성

 4장에서 다룬 중첩 라우트 구현은 5장의 중첩 레이아웃과 밀접하게 연관됩니다.

 중첩 라우트 구조는 자연스럽게 중첩 레이아웃 구조로 이어집니다.

 예를 들어, /dashboard/settings라는 중첩 라우트가 있다면, 이에 대응하는 중첩 레이아웃을 app/dashboard/layout.js에 정의할 수 있습니다.

레이아웃의 고급 기능

  1. 템플릿 : template.js를 사용하여 각 네비게이션마다 리렌더링되는 UI를 정의할 수 있습니다.
  2. 로딩 UI : loading.js를 사용하여 레이아웃 내에서 로딩 상태를 처리할 수 있습니다.
  3. 에러 처리 : error.js를 사용하여 레이아웃 내에서 발생하는 에러를 우아하게 처리할 수 있습니다.

실습 : 다단계 중첩 레이아웃 구현

 다음 요구사항을 만족하는 다단계 중첩 레이아웃을 구현해보세요.

  1. 루트 레이아웃 : 전체 애플리케이션에 적용되는 헤더와 푸터 포함
  2. 대시보드 레이아웃 : 대시보드 페이지에 적용되는 사이드바 포함
  3. 설정 레이아웃 : 설정 페이지에 적용되는 탭 네비게이션 포함

 구현 단계

  1. app/layout.js 파일에 루트 레이아웃 생성
  2. app/dashboard/layout.js 파일에 대시보드 레이아웃 생성
  3. app/dashboard/settings/layout.js 파일에 설정 레이아웃 생성
  4. 각 레이아웃에 해당하는 UI 요소 구현
  5. 페이지 컴포넌트 생성하여 레이아웃 테스트

 예시 코드

app/layout.js
// app/layout.js
export default function RootLayout({ children }) {
  return (
    <html>
      <body>
        <header>{/* 전역 헤더 */}</header>
        <main>{children}</main>
        <footer>{/* 전역 푸터 */}</footer>
      </body>
    </html>
  )
}
app/dashboard/layout.js
export default function DashboardLayout({ children }) {
  return (
    <div className="dashboard-layout">
      <aside>{/* 대시보드 사이드바 */}</aside>
      <div className="dashboard-content">{children}</div>
    </div>
  )
}
app/dashboard/settings/layout.js
export default function SettingsLayout({ children }) {
  return (
    <div className="settings-layout">
      <nav>{/* 설정 탭 네비게이션 */}</nav>
      <div className="settings-content">{children}</div>
    </div>
  )
}
app/dashboard/settings/page.js
export default function SettingsPage() {
  return <h1>Settings Page</h1>
}

 이 실습을 통해 다단계 중첩 레이아웃을 구현하고, 각 레벨의 레이아웃이 어떻게 조합되어 전체 페이지 구조를 형성하는지 이해할 수 있습니다.

 이는 복잡한 애플리케이션 구조를 효율적으로 관리하는 데 필요한 핵심 스킬을 개발하는 데 도움이 될 것입니다.