Ch 05. 그룹으로 묶다 — 라우트 그룹
서랍 속 칸막이
책상 서랍을 열면 칸막이로 구분되어 있는 경우가 있습니다. 문구류는 왼쪽, 메모지는 오른쪽. 칸막이가 서랍 자체의 위치를 바꾸지는 않습니다. 그냥 안에서 정리만 해줄 뿐입니다.
라우트 그룹이 딱 그런 역할입니다. 폴더 이름을 괄호 ()로 감싸면, 그 폴더는 URL 경로에 포함되지 않습니다. 코드 정리를 위한 폴더일 뿐입니다.
(group) 문법
소괄호로 감싼 폴더는 라우트 그룹입니다. URL 생성에서 무시됩니다.
app/├── (auth)/│ ├── login/│ │ └── page.tsx → /login│ └── register/│ └── page.tsx → /register└── (main)/ ├── page.tsx → / └── about/ └── page.tsx → /about
(auth) 폴더가 있더라도 URL은 /auth/login이 아니라 /login입니다. (auth)는 URL에 나타나지 않습니다.
언제 유용한가
로그인, 회원가입, 비밀번호 재설정처럼 인증 관련 페이지들은 관련성이 높습니다. 한 폴더에 모아두고 싶지만, URL에 /auth가 붙는 건 원하지 않을 수 있습니다. 이럴 때 라우트 그룹을 씁니다.
// 파일: app/(auth)/login/page.tsx
export default function LoginPage() {
return (
<div>
<h1>로그인</h1>
<form>
<input type="email" placeholder="이메일" />
<input type="password" placeholder="비밀번호" />
<button type="submit">로그인</button>
</form>
</div>
);
}
```text
```tsx
// 파일: app/(auth)/register/page.tsx
export default function RegisterPage() {
return (
<div>
<h1>회원가입</h1>
{/* 회원가입 폼 */}
</div>
);
}
```text
이 페이지들은 `/login`, `/register`로 접근합니다. `(auth)` 폴더명은 URL에 나오지 않습니다.
### 그룹마다 다른 레이아웃 적용하기
라우트 그룹의 가장 강력한 활용은 그룹별로 다른 레이아웃을 적용하는 것입니다. 같은 루트 레이아웃을 공유하지만, 그룹 안에서는 별도의 레이아웃을 쓸 수 있습니다.
app/ ├── layout.tsx ← 루트 레이아웃 (모두 공유) ├── (auth)/ │ ├── layout.tsx ← 인증 페이지 전용 레이아웃 │ ├── login/page.tsx → /login │ └── register/page.tsx → /register └── (main)/ ├── layout.tsx ← 일반 페이지 전용 레이아웃 └── page.tsx → /
인증 페이지에는 헤더/푸터가 없는 심플한 레이아웃을, 일반 페이지에는 네비게이션이 포함된 레이아웃을 따로 줄 수 있습니다.```tsx// 파일: app/(auth)/layout.tsxexport default function AuthLayout({ children,}: { children: React.ReactNode;}) { return ( <div style={{ minHeight: '100vh', display: 'flex', alignItems: 'center', justifyContent: 'center', }} > <div style={{ width: '400px' }}>{children}</div> </div> );}
이 레이아웃은 로그인과 회원가입 페이지에만 적용됩니다. 루트 레이아웃의 헤더/푸터는 여전히 감싸고 있습니다.
다음 챕터에서는
다음 챕터에서는 길을 잃었을 때, 또는 오류가 났을 때 사용자에게 어떤 화면을 보여줄지를 다룹니다. loading.tsx, error.tsx, not-found.tsx 세 가지 특별한 파일을 만나봅니다.