# Next.js App Router의 라우트 그룹(Route Groups) 구현 분석 ## 개요 Next.js의 App Router에서는 괄호로 묶인 디렉토리(`(with-base-layout)`, `(without-base-layout)`)를 라우트 그룹으로 처리하여 URL 경로에 영향을 주지 않으면서 서로 다른 레이아웃을 적용할 수 있게 합니다. 이 문서에서는 프로젝트에서 라우트 그룹이 어떻게 구현되고 사용되는지 분석합니다. ## 라우트 그룹 구조 분석 ### 1. 디렉토리 구조 프로젝트에서는 두 가지 주요 라우트 그룹이 사용되고 있습니다: ``` /apps/cs/app/ ├── (with-base-layout)/ │ ├── banner/ │ ├── bbs/ │ ├── code/ │ ├── contents/ │ ├── dashboard/ │ ├── ... │ ├── layout.tsx │ └── loading.tsx ├── (without-base-layout)/ │ ├── user-survey-article/ │ └── user-survey-result/ └── layout.tsx ``` ### 2. 라우트 그룹별 레이아웃 구현 #### 루트 레이아웃 (`/apps/cs/app/layout.tsx`) ```tsx import type { Metadata } from "next"; import { App } from "@/app"; export const metadata: Metadata = { title: "유역하수도 통합 정보플랫폼", }; export default App; ``` #### App 컴포넌트 (`/apps/cs/src/app/index.tsx`) ```tsx import "./styles/base.css"; import "./styles/components.css"; import "@fontsource-variable/noto-sans-kr"; import { AppProvider } from "./providers"; import { cookies } from "next/headers"; const App = async ({ children }: Readonly<{ children: React.ReactNode }>) => { const theme = (await cookies()).get("site-theme-key"); return ( {children} ); }; export { App }; ``` #### (with-base-layout) 레이아웃 (`/apps/cs/app/(with-base-layout)/layout.tsx`) ```tsx "use client"; import { usePathname, useRouter } from "next/navigation"; import { useQueryClient } from "@tanstack/react-query"; import { BaseLayout } from "@common/components"; import type { MenuItem } from "@/entities/menu"; import { useMenuStore } from "@/shared/lib"; import { PageLayout } from "@/shared/ui/page-layout"; export default function WithBaseLayout({ children, }: { children: React.ReactNode; }) { const router = useRouter(); const pathname = usePathname(); const queryClient = useQueryClient(); const setCurrentMenuInfo = useMenuStore((state) => state.setCurrentMenuInfo); const handleMenuClick = (item: MenuItem) => { setCurrentMenuInfo(item); router.push(item.urlPath); }; return ( {children} ); } ``` #### PageLayout 컴포넌트 (`/apps/cs/src/shared/ui/page-layout.tsx`) ```tsx import { PageTitle } from "@common/components"; import { useMenuStore } from "../lib/use-menu-store"; function PageLayout({ children }: { children: React.ReactNode }) { const currentMenuInfo = useMenuStore((state) => state.currentMenuInfo); const menuPaths = currentMenuInfo?.menuPath ?.split(">") .map((path) => path.trim()); return (
{children}
); } ``` ## 라우트 그룹의 작동 원리 ### 1. URL 경로에 영향을 주지 않는 그룹화 Next.js App Router에서 괄호로 묶인 디렉토리는 URL 경로에 포함되지 않습니다. 예를 들어: - `/bbs/register` 경로는 `(with-base-layout)/bbs/register` 디렉토리에 매핑됩니다. - `/user-survey-article/1` 경로는 `(without-base-layout)/user-survey-article/[srvySn]` 디렉토리에 매핑됩니다. ### 2. 레이아웃 분리 및 재사용 라우트 그룹을 사용하면 서로 다른 레이아웃을 가진 페이지들을 효율적으로 구성할 수 있습니다: - `(with-base-layout)` 그룹: 메뉴, 헤더, 사이드바 등을 포함하는 `BaseLayout`과 `PageLayout`을 사용합니다. - `(without-base-layout)` 그룹: 기본 레이아웃 없이 페이지 컴포넌트만 렌더링합니다. ### 3. 중첩 라우트 그룹 프로젝트에서는 중첩된 라우트 그룹도 사용되고 있습니다: ``` (with-base-layout)/bbs/(post)/bbsnormal/ ``` 여기서 `(post)`는 게시물 관련 페이지들을 그룹화하는 중첩된 라우트 그룹입니다. ## 라우트 그룹 사용 사례 ### 1. 관리자 인터페이스 (`with-base-layout`) 관리자 인터페이스는 일관된 레이아웃과 네비게이션이 필요합니다: ```tsx // (with-base-layout)/layout.tsx return ( {children} ); ``` 이 레이아웃은 다음과 같은 기능을 제공합니다: - 메뉴 시스템을 통한 페이지 간 이동 - 현재 페이지 경로 표시 - 일관된 페이지 타이틀 및 구조 ### 2. 독립적인 페이지 (`without-base-layout`) 설문 기사나 결과 페이지와 같은 독립적인 페이지는 기본 레이아웃 없이 콘텐츠에 집중합니다: ```tsx // (without-base-layout)/user-survey-article/[srvySn]/page.tsx export default async function UserSurveyArticlePage({ params, }: { params: Promise<{ srvySn: string }>; }) { const { srvySn } = await params; return ; } ``` 이러한 페이지는: - 외부 링크나 팝업으로 열리는 경우가 많음 - 독립적인 기능을 제공(예: 설문 제출 후 창 닫기) - 메인 애플리케이션 UI와 분리된 경험 제공 ## 두 라우트 그룹의 주요 차이점 ### (with-base-layout) - `BaseLayout` 컴포넌트를 포함하는 레이아웃을 사용합니다. - 이 레이아웃은 메뉴, 헤더, 사이드바 등 기본 UI 요소를 포함합니다. - `PageLayout` 컴포넌트로 감싸져 있어 일관된 페이지 구조를 제공합니다. - 주로 관리자 페이지나 로그인 후 사용하는 내부 페이지에 사용됩니다. - 다양한 관리 기능을 포함하는 여러 하위 디렉토리가 있습니다. ### (without-base-layout) - 기본 레이아웃 없이 페이지 컴포넌트만 렌더링합니다. - 메뉴, 헤더, 사이드바 등의 UI 요소가 없는 독립적인 페이지입니다. - 주로 외부 사용자용 페이지나 팝업, 임베드 페이지에 사용됩니다. - 현재 두 가지 특수 목적 페이지만 포함하고 있습니다. ## 기술적 이점 1. **코드 구성 개선**: 관련 페이지와 레이아웃을 논리적으로 그룹화할 수 있습니다. 2. **레이아웃 재사용**: 공통 레이아웃을 여러 페이지에서 재사용할 수 있습니다. 3. **URL 구조 단순화**: 그룹 이름이 URL에 포함되지 않아 깔끔한 URL 구조를 유지할 수 있습니다. 4. **유지보수성 향상**: 관련 기능을 함께 그룹화하여 코드 탐색과 유지보수가 용이합니다. ## 결론 Next.js App Router의 라우트 그룹 기능은 프로젝트에서 다양한 레이아웃 요구사항을 효율적으로 관리하는 데 중요한 역할을 합니다. `(with-base-layout)`과 `(without-base-layout)` 그룹을 통해 관리자 인터페이스와 독립적인 페이지를 명확하게 분리하면서도 코드 재사용성과 유지보수성을 높일 수 있습니다. 이 구조는 확장성이 뛰어나 새로운 페이지나 기능을 추가할 때 기존 패턴을 따르기 쉽고, 애플리케이션이 성장함에 따라 필요한 경우 추가 라우트 그룹을 도입할 수 있는 유연성을 제공합니다.