icon안동민 개발노트

템플릿 컴포넌트 활용


 Next.js의 템플릿 컴포넌트는 레이아웃과 유사하지만 독특한 특성을 가진 강력한 기능입니다.

 이 절에서는 템플릿 컴포넌트의 개념, 레이아웃과의 차이점, 그리고 적절한 사용 사례에 대해 알아보겠습니다.

템플릿 컴포넌트의 개념

 템플릿 컴포넌트는 template.js 파일로 정의되며, 라우트 세그먼트의 UI를 감싸는 역할을 합니다.

 레이아웃과 유사하게 작동하지만, 몇 가지 중요한 차이점이 있습니다.

레이아웃과 템플릿의 차이점

  1. 상태 유지 : 레이아웃은 라우트 간 이동 시 상태를 유지하지만, 템플릿은 매 네비게이션마다 새 인스턴스를 생성합니다.
  2. 리렌더링 : 템플릿은 라우트 변경 시마다 리렌더링되므로, 애니메이션 효과 등을 적용하기에 적합합니다.
  3. 중첩 : 템플릿은 레이아웃 내부에 중첩되며, 페이지나 하위 세그먼트를 감싸게 됩니다.

template.js 파일의 특징과 사용 방법

 템플릿 컴포넌트의 기본 구조는 다음과 같습니다.

app/template.js
export default function Template({ children }) {
  return (
    <div>
      {/* 템플릿 특정 UI 요소 */}
      {children}
    </div>
  )
}

 템플릿 사용 예시

app/dashboard/template.js
'use client'
 
import { useState, useEffect } from 'react'
import LoadingSpinner from './LoadingSpinner'
 
export default function DashboardTemplate({ children }) {
  const [isLoading, setIsLoading] = useState(true)
 
  useEffect(() => {
    // 데이터 로딩 시뮬레이션
    const timer = setTimeout(() => setIsLoading(false), 1000)
    return () => clearTimeout(timer)
  }, [])
 
  return (
    <div className="dashboard-template">
      {isLoading ? <LoadingSpinner /> : children}
    </div>
  )
}

 이 예시에서 템플릿은 대시보드 페이지에 로딩 상태를 추가합니다.

 매 네비게이션마다 새로운 로딩 상태가 시작됩니다.

레이아웃 대신 템플릿을 사용해야 하는 경우

  1. 페이지 전환 효과 : 라우트 변경 시 특정 애니메이션이나 전환 효과가 필요한 경우
  2. 동적 초기화 : 매 페이지 로드마다 특정 상태나 효과를 재설정해야 하는 경우
  3. 성능 최적화 : 특정 컴포넌트나 로직이 매 라우트 변경 시 재실행되어야 하는 경우

8장 상태 관리 및 폼 처리와의 연결

 템플릿 컴포넌트는 8장에서 다루는 상태 관리 및 폼 처리와 밀접하게 연관됩니다.

 템플릿은 매 라우트 변경 시 새로운 인스턴스를 생성하므로, 폼의 초기 상태를 설정하거나 특정 상태를 리셋하는 데 유용할 수 있습니다.

 또한, 클라이언트 사이드 상태 관리 라이브러리와 함께 사용하여 라우트별로 독립적인 상태를 관리할 수 있습니다.

실습 : 인증 상태에 따른 템플릿 컴포넌트

 다음 요구사항을 만족하는 템플릿 컴포넌트를 구현해보세요.

  1. 사용자의 인증 상태를 확인합니다.
  2. 인증된 사용자에게는 대시보드 내용을 보여줍니다.
  3. 인증되지 않은 사용자에게는 로그인 폼을 보여줍니다.
  4. 매 라우트 변경 시 인증 상태를 다시 확인합니다.

 구현 예시

app/dashboard/template.js
'use client'
 
import { useState, useEffect } from 'react'
import { useRouter } from 'next/navigation'
 
export default function DashboardTemplate({ children }) {
  const [isAuthenticated, setIsAuthenticated] = useState(false)
  const router = useRouter()
 
  useEffect(() => {
    // 인증 상태 확인 (실제 구현에서는 API 호출 등을 사용)
    const checkAuth = async () => {
      // 예시: localStorage를 사용한 간단한 인증 체크
      const token = localStorage.getItem('authToken')
      setIsAuthenticated(!!token)
    }
 
    checkAuth()
  }, [])
 
  if (!isAuthenticated) {
    return (
      <div className="login-form">
        <h2>Please log in to access the dashboard</h2>
        {/* 로그인 폼 컴포넌트 */}
        <button onClick={() => {
          // 로그인 로직 (예시)
          localStorage.setItem('authToken', 'dummy-token')
          setIsAuthenticated(true)
        }}>
          Log In
        </button>
      </div>
    )
  }
 
  return (
    <div className="dashboard-template">
      <h1>Welcome to the Dashboard</h1>
      {children}
    </div>
  )
}

 이 실습을 통해 템플릿 컴포넌트를 사용하여 동적인 인증 로직을 구현하고, 라우트 변경 시마다 인증 상태를 확인하는 방법을 경험할 수 있습니다.

 이는 실제 애플리케이션에서 보안과 사용자 경험을 향상시키는 데 유용한 패턴입니다.