IT/nextjs 기초 내 공부

쉬운 NextJs 04: Layout 컴포넌트 완벽 가이드 - 제약사항과 해결방법

higold 2024. 11. 12. 08:45
반응형

Next.js Layout 컴포넌트 완벽 가이드: 제약사항과 해결방법

목차

  1. Layout 컴포넌트 기본 개념
  2. Layout 컴포넌트의 제약사항
  3. 실제 구현 방법과 해결책

1. Layout 컴포넌트 기본 개념

1.1 Layout이란?

Layout 컴포넌트는 여러 라우트(route)에서 UI를 공유할 수 있게 해주는 컴포넌트입니다.

// app/layout.tsx (Root Layout)
export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en">
      <body>
        <nav>공통 네비게이션</nav>
        {children}
      </body>
    </html>
  )
}

1.2 중첩 Layout

Layout은 중첩해서 사용할 수 있습니다:

// app/dashboard/layout.tsx
export default function DashboardLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <div>
      <aside>대시보드 사이드바</aside>
      {children}
    </div>
  )
}

2. Layout 컴포넌트의 제약사항

2.1 접근 불가능한 정보들

Layout 컴포넌트에서는 다음 정보들에 접근할 수 없습니다:

  1. 라우트 세그먼트
  2. 검색 파라미터(Search Params)
  3. 현재 경로(pathname)

2.2 제약사항의 이유: Partial Rendering

이러한 제약사항이 있는 이유는 Next.js의 Partial Rendering 때문입니다:

  1. 클라이언트 사이드 네비게이션 시 Layout은 리렌더링되지 않음
  2. 성능 최적화를 위해 필요한 부분만 렌더링
  3. 오래된(stale) 데이터 사용 방지

3. 실제 구현 방법과 해결책

3.1 잘못된 구현 방식

// ❌ 잘못된 구현 - Layout에서 직접 pathname 접근
export default function Layout({ children }) {
  const pathname = usePathname() // 작동하지 않음!

  return (
    <div>
      <nav>
        <Link className={pathname === '/' ? 'active' : ''} href="/">
          Home
        </Link>
      </nav>
      {children}
    </div>
  )
}

3.2 올바른 구현 방식

// ✅ 올바른 구현 - 클라이언트 컴포넌트로 분리

// components/Navigation.tsx
'use client'

import { usePathname } from 'next/navigation'
import Link from 'next/link'

export function Navigation() {
  const pathname = usePathname()

  return (
    <nav>
      <Link 
        className={pathname === '/' ? 'active' : ''} 
        href="/"
      >
        Home
      </Link>
      <Link 
        className={pathname === '/dashboard' ? 'active' : ''} 
        href="/dashboard"
      >
        Dashboard
      </Link>
    </nav>
  )
}

// app/layout.tsx
import { Navigation } from './components/Navigation'

export default function Layout({ children }) {
  return (
    <div>
      <Navigation />
      {children}
    </div>
  )
}

3.3 URL 검색 파라미터 처리

// ✅ 올바른 구현 - 페이지 컴포넌트에서 검색 파라미터 처리
// app/dashboard/page.tsx
export default function DashboardPage({
  searchParams,
}: {
  searchParams: { [key: string]: string | string[] | undefined }
}) {
  // 여기서는 searchParams 사용 가능
  const query = searchParams.q ?? ''

  return (
    <div>
      <h1>검색어: {query}</h1>
    </div>
  )
}

실제 사용 예시와 팁

URL 상태 관리

'use client'

import { usePathname, useSearchParams } from 'next/navigation'

export function BreadcrumbNavigation() {
  const pathname = usePathname()
  const searchParams = useSearchParams()

  // 현재 경로를 '/' 기준으로 분할하여 배열로 만듦
  const segments = pathname.split('/').filter(Boolean)

  return (
    <nav aria-label="breadcrumb">
      <ol>
        <li>
          <Link href="/">Home</Link>
        </li>
        {segments.map((segment, index) => {
          const path = `/${segments.slice(0, index + 1).join('/')}`
          return (
            <li key={path}>
              <Link href={path}>{segment}</Link>
            </li>
          )
        })}
      </ol>
    </nav>
  )
}

참고문헌

  1. Next.js 공식 문서. "Layouts", https://nextjs.org/docs/app/building-your-application/routing/pages-and-layouts
  2. Next.js 공식 문서. "Partial Rendering", https://nextjs.org/docs/app/building-your-application/rendering/partial-rendering
  3. MDN Web Docs. "URL API", https://developer.mozilla.org/en-US/docs/Web/API/URL
  4. Vercel Blog. "Understanding Layouts in Next.js", https://vercel.com/blog/understanding-layouts-in-nextjs
반응형