NextJS 디렉토링 네이밍 정리
안녕하세요, 프론트엔드 개발자 여러분! 오늘은 Next.js를 사용하면서 꼭 알아야 할 디렉토리 네이밍 규칙에 대해 알아보려고 합니다. 처음 Next.js를 접할 때 주니어 개발자들이 가장 많이 어려워하는 내용은 앱 라우터에서 제공하는 다양한 디렉토리 규칙들입니다.
디렉토리명으로 라우팅이나 처리 방식을 제어한다는 개념이 코드로 로직을 작성하는 개발자 입장에서는 혼란스러울 수 있는데요
오늘은 이러한 디렉토리 네이밍 규칙들을 보다 쉽게 정리하고 알아보는 시간을 가지겠습니다.
1. 언더스코어(_) - 비공개 디렉토리
_로 시작하는 디렉토리는 라우팅 시스템에서 제외됩니다. 이런 디렉토리는 컴포넌트, 유틸리티 함수, 스타일 등 애플리케이션 내부에서만 사용되는 파일들을 정리할 때 유용합니다.
app/
├─ _components/ <- 라우팅에서 제외됨
│ ├─ Button.tsx
│ └─ Navbar.tsx
├─ _utils/ <- 라우팅에서 제외됨
│ └─ formatter.ts
├─ page.tsx <- 홈페이지 (/)
실제 프로젝트에서는 이렇게 활용할 수 있어요:
// app/page.tsx
import { Button } from './_components/Button';
export default function HomePage() {
return (
<main>
<h1>안녕하세요!</h1>
<Button>시작하기</Button>
</main>
);
}
팀 프로젝트를 할 때 공통 컴포넌트나 유틸 함수들을 정리하는 데 정말 유용하더라고요. 꼭 /app 바로 아래가 아니라 하위 경로에서도 사용할 수 있습니다.
2. 괄호(()) - 라우트 그룹
괄호로 감싼 디렉토리는 라우트 그룹을 만들어 줍니다. 이는 실제 URL 경로에는 포함되지 않으면서 코드를 논리적으로 구성할 수 있게 해줍니다.
app/
├─ (marketing)/ <- URL에 영향 없음
│ ├─ about/
│ │ └─ page.tsx <- /about으로 접근 가능
│ ├─ blog/
│ │ └─ page.tsx <- /blog로 접근 가능
├─ (shop)/ <- URL에 영향 없음
│ ├─ products/
│ │ └─ page.tsx <- /products로 접근 가능
이렇게 하면 코드를 논리적인 섹션으로 나눌 수 있어요. 예를 들어, 마케팅 관련 페이지와 쇼핑 관련 페이지를 구분하면서도 URL 구조는 단순하게 유지할 수 있죠.
특히 큰 프로젝트에서 코드베이스를 정리할 때 유용해요. 팀원들 간에 담당 영역을 디렉토리로 분리할 수도 있고요.
3. 대괄호([]) - 동적 라우트
대괄호로 감싼 디렉토리는 동적 경로를 만듭니다. 제품 상세 페이지나 블로그 포스트 같이 ID나 슬러그에 따라 다른 콘텐츠를 보여줄 때 사용해요.
app/
├─ products/
│ ├─ [id]/
│ │ └─ page.tsx <- /products/1, /products/2 등으로 접근
├─ blog/
│ ├─ [slug]/
│ │ └─ page.tsx <- /blog/hello-world, /blog/next-js-guide 등
실제 코드에서는 이렇게 활용할 수 있어요:
// app/products/[id]/page.tsx
export default function ProductPage({ params }: { params: { id: string } }) {
return (
<div>
<h1>제품 상세 페이지</h1>
<p>제품 ID: {params.id}</p>
</div>
);
}
이커머스 사이트를 만들 때 정말 많이 사용했던 패턴이에요. 동적 라우팅 없이는 제품마다 페이지를 따로 만들어야 했을 텐데, 이 기능 덕분에 하나의 템플릿으로 수많은 제품 페이지를 처리할 수 있죠.
4. 세 개의 점(...) - 캐치올 라우트
대괄호 안에 세 개의 점과 변수명을 넣으면 캐치올 라우트를 만들 수 있습니다. 이는 여러 경로 세그먼트를 하나의 매개변수로 캡처해요.
app/
├─ docs/
│ ├─ [...slug]/
│ │ └─ page.tsx <- /docs/intro, /docs/advanced/routing 등
코드로 구현하면:
// app/docs/[...slug]/page.tsx
export default function DocsPage({ params }: { params: { slug: string[] } }) {
return (
<div>
<h1>문서 페이지</h1>
<p>경로: {params.slug.join('/')}</p>
</div>
);
}
이 방식은 문서 사이트나 위키 같은 프로젝트에서 유용해요. 폴더 구조가 깊어져도 하나의 컴포넌트로 처리할 수 있으니까요. /docs/getting-started/installation/docker와 같은 복잡한 경로도 간단히 처리할 수 있죠.
5. @기호 - 병렬 라우트
@로 시작하는 디렉토리는 병렬 라우트를 만듭니다. 이를 통해 하나의 URL에서 여러 페이지를 동시에 렌더링할 수 있어요.
app/
├─ dashboard/
│ ├─ page.tsx <- 기본 대시보드 내용
│ ├─ @analytics/ <- 대시보드 내 분석 정보
│ │ └─ page.tsx
│ ├─ @notifications/ <- 대시보드 내 알림
│ │ └─ page.tsx
실제 구현은 이렇게 할 수 있어요:
// app/dashboard/layout.tsx
export default function DashboardLayout({
children,
analytics,
notifications
}: {
children: React.ReactNode;
analytics: React.ReactNode;
notifications: React.ReactNode;
}) {
return (
<div>
<div className="main">{children}</div>
<div className="sidebar">
{analytics}
{notifications}
</div>
</div>
);
}
이 기능은 대시보드나 복잡한 레이아웃을 가진 페이지에서 정말 강력해요. 각 섹션의 로딩 상태나 에러 처리를 독립적으로 관리할 수 있거든요. 처음에는 좀 복잡하게 느껴질 수 있지만, 사용해보면 정말 편리합니다.
6. 괄호와 점((.)) - 인터셉팅 라우트
괄호 안에 점으로 시작하는 디렉토리는 인터셉팅 라우트를 만듭니다. 이는 현재 경로의 컨텍스트 내에서 다른 경로를 가로채서 보여줄 때 사용해요.
app/
├─ feed/
│ └─ page.tsx <- /feed 페이지
├─ photo/
│ ├─ [id]/
│ │ └─ page.tsx <- /photo/123 페이지
│ ├─ (..)feed/ <- /feed에서 모달로 표시
│ │ └─ page.tsx
이 기능은 모달이나 슬라이드오버와 같은 UI 패턴을 구현할 때 아주 유용해요. 예를 들어, 인스타그램처럼 피드를 보다가 사진을 클릭하면 모달로 상세 페이지가 표시되는 기능을 구현할 수 있죠.
팀 프로젝트에서 처음 이 기능을 도입했을 때 모두가 놀랐던 기억이 나네요. 복잡한 상태 관리 없이도 깔끔하게 모달 라우팅을 구현할 수 있으니까요.
7. app vs pages - 디렉토리 구조
Next.js 13부터는 app 디렉토리가 도입되었어요. 기존의 pages 디렉토리와는 어떤 차이가 있을까요?
프로젝트 루트/
├─ app/ <- App Router (새로운 방식)
│ ├─ layout.tsx <- 루트 레이아웃
│ ├─ page.tsx <- 홈페이지
├─ pages/ <- Pages Router (기존 방식)
│ ├─ _app.tsx <- 전역 레이아웃
│ ├─ index.tsx <- 홈페이지
app 디렉토리는 React 서버 컴포넌트를 지원하고, 더 직관적인 파일 기반 라우팅을 제공해요. 하지만 두 방식은 함께 사용할 수도 있습니다. 기존 프로젝트를 점진적으로 마이그레이션할 때 유용하죠.
처음에는 어려워 보일 수 있지만, app 디렉토리의 새로운 파일 컨벤션을 익히면 더 효율적인 개발이 가능해요. layout.tsx, loading.tsx, error.tsx 같은 특수 파일들을 활용하면 더 좋은 사용자 경험을 제공할 수 있거든요.
마무리
Next.js의 디렉토리 네이밍 규칙은 처음에는 낯설 수 있지만, 이해하고 나면 정말 강력한 도구가 됩니다. 이런 규칙들 덕분에 복잡한 라우팅 로직을 파일 시스템으로 표현할 수 있어 코드가 더 직관적이고 관리하기 쉬워지죠.
지금까지 설명한 내용을 실제 프로젝트에 적용해보면서 Next.js의 강력함을 직접 경험해보세요. 처음에는 헷갈릴 수 있지만, 조금만 실습해보면 금방 익숙해질 거예요!
궁금한 점이 있으시면 댓글로 남겨주세요. 감사합니다! 😊