Next.js App Router(3) - 폴더 구조와 파일 역할
이번 편에서는 Next.js App Router의 page 파일 이외에 새롭게 추가된 파일들의 역할을 알아보고 효율적인 폴더 구조를 구성하는 방법에 대하여 알아보겠습니다.
1편에서 App Router에서 추가된 주요 파일들에 소개했는데요.
다시 간단하게 작성해 보자면 다음과 같습니다.
- page.tsx: 각 경로의 메인 컴포넌트입니다. 서버 컴포넌트가 기본이며, 클라이언트 컴포넌트로 사용하려면 상단에 'use client'를 추가합니다.
- layout.tsx: 특정 경로 그룹에서 공통으로 사용되는 레이아웃을 정의합니다. 페이지 전환 시에도 상태가 유지됩니다.
- template.tsx: 페이지 전환마다 새 인스턴스로 생성됩니다. 상태를 초기화하고 싶을 때 사용됩니다.
- loading.tsx / error.tsx: 로딩 상태 및 에러 UI를 선언적으로 구성합니다.
1. 중첩 레이아웃과 상태 보존 전략
Next.js를 사용하던 개발자라면 App Router에서 누가 뭐라고 해도 가장 눈에 띄는 요소 중 하나는 layout.tsx일 것입니다.
레이아웃은 페이지 이동 간에도 유지되며, 로그인 레이아웃, 기본 레이아웃과 같이 다른 레이아웃을 만들기 위해 분기 처리를 하는 등의 처리 없이 간단하게 레이아웃 처리를 할 수 있도록 도와줍니다.
Layout vs Template
레이아웃과 템플릿은 언뜻 비슷해 보일 수 있으나 다음과 같은 확실한 차이가 있습니다.
- Layout : 레이아웃(layout.tsx)은 페이지 이동 간에도 유지되므로, 사이드바나 탭 메뉴 같은 UI 상태 유지에 적합합니다.
- Template : 반면 템플릿(template.tsx)은 페이지 이동 시마다 초기화되어야 하는 상태(검색 결과, 입력 폼 등)에 적합합니다.
2. 폴더 및 컴포넌트 모듈화 전략
중첩 레이아웃을 구성하는데 가장 중요한 요소는 Route Group입니다.
그리고 App Router의 효율적인 폴더 구조를 짜는데 아주 중요한 역할을 합니다.
App Router에서는 괄호를 사용하여 URL에 노출되지 않고 폴더 구조상으로만 그룹화할 수 있습니다.
그렇기 때문에 기능, 레이아웃, 권한별로 라우트 그룹을 설정하면 깔끔한 구조를 구성할 수 있습니다.
// 구조 예시
app/
├── (main)
│ ├── layout.tsx
│ └── dashboard/
│ ├── page.tsx
│ └── components/
├── (external)
│ └── login/
│ └── page.tsx
├── blog/
│ ├── layout.tsx
│ ├── page.tsx
│ └── [slug]/
│ ├── page.tsx
│ └── loading.tsx
├── layout.tsx
└── error.tsx
주로 많이 추천하는 방식은 다음과 같습니다.
- 기능별 폴더로 모듈화
- 컴포넌트를 사용하는 페이지에 함께 배치(colocation)
- 공통 컴포넌트는 별도의 디렉터리에 배치(components 디렉터리 등)
이 방법이 꼭 정답은 아니며 저의 경우 Next.js의 App Router 구조에 아예 영향을 주지 않는 방식을 선호하여 app, src 폴더를 별도로 두는 방식을 사용하고 있습니다.
// 필자 예시
app/
├── (main)
│ ├── layout.tsx
│ └── dashboard/
│ ├── page.tsx
├── (external)
│ └── login/
│ └── page.tsx
├── blog/
│ ├── layout.tsx
│ ├── page.tsx
│ └── [slug]/
│ ├── page.tsx
│ └── loading.tsx
├── layout.tsx
└── error.tsx
src/
├── api/
├── components/
├── config/
├── provider/
...
└── utils/
이처럼 정답은 없지만 기본적으로 기능, 레이아웃, 권한별로 라우트 그룹을 설정한다는 생각을 항상 가지고 폴더 구조를 설정한다면 유지보수와 확장성 높은 폴더 구조를 사용할 수 있을 것입니다.