Next.js 프로젝트 생성
채팅 어플리케이션 Aurora 프로젝트를 진행하면서 우리는 기존에 즐겨 사용하던 React 에서 Next.js 기반으로 도전을하게 되었는데 그 이유는 다음과 같다.
React가 아닌 Next.js를 선택한 이유
🚀 성능
- SSR로 초기 로딩 빨라짐: 서버에서 미리 HTML 만들어서 보내줘서 사용자가 더 빨리 볼 수 있음
- 이미지 자동 최적화: 프로필 사진, 파일 업로드 등 알아서 최적화해줌
🔍 SEO & 공유
- 메타데이터 쉽게 설정: CSR에서의 복잡한 설정 대신 메타데이터 주입으로 간단하게 설정 가능
- 검색엔진 최적화: 공개 서버나 도움말 페이지가 구글에서 잘 검색됨
🛣️ 라우팅
- 파일 기반 라우팅:
/projects/[project_id]/[channel_id]이런 복잡한 경로 관리가 직관적 - 로딩/에러 상태 분리: 각 페이지별로 스켈레톤이나 에러 화면 깔끔하게 관리
🔧 개발 편의성
- API Routes: 백엔드 API를 같은 프로젝트에서 관리 가능
- 풀스택 개발: 프론트엔드랑 백엔드 한번에 배포
- TypeScript 기본 지원: 타입 안전성 보장
⚡ 하이브리드 렌더링
- ISR: 공개 서버 목록은 미리 생성, 채팅은 실시간으로
- 클라이언트/서버 적절히 섞어서 사용: 필요한 곳에만 서버 렌더링
결론
React 장점 + 성능 + SEO + 개발 편의성이 모두 필요한 복잡한 앱에는 Next.js가 답이라고 생각하여 Next.js로의 개발을 시작하게 되었음 그렇다면 이제 실제 프로젝트 구조를 설계를 해볼 차례인데 이번 프로젝트에서 Next.js의 강력한 기능 중 하나인 라우팅 그룹을 사용해보자.
Next.js App Router 라우트 그룹으로 프로젝트 구조화하기
디스코드나 메타모스트 같은 복잡한 웹 애플리케이션을 개발할 때, 가장 중요한 것 중 하나가 폴더 구조이다. Next.js App Router의 라우트 그룹(Route Groups) 기능을 활용하면 대규모 프로젝트를 논리적으로 구조화하고, 각 영역별로 다른 레이아웃을 적용이 가능하다.
이 글에서는 메타모스트 스타일의 채팅 애플리케이션을 예시로, 라우트 그룹을 활용한 효과적인 폴더 구조를 우리의 프로젝트에 맞게 설계해보았다..
프로젝트 요구사항
우리가 만들 애플리케이션의 플로우는 다음과 같다:
- 로그인/회원가입
- 서버 URL 입력 (메타모스트처럼)
- 프로젝트 선택/생성
- 프로젝트 내 채널 이용
각 단계마다 완전히 다른 UI/UX가 필요하고, 특히 워크스페이스 영역에서는 기존 헤더나 네비게이션이 필요 없다.
라우트 그룹이란?
라우트 그룹은 Next.js App Router에서 제공하는 기능으로, 괄호 ()****로 감싼 폴더를 의미한다.
핵심 특징
- URL에 포함되지 않음:
(auth)/login→ URL은/login - 독립적인 레이아웃 적용 가능: 각 그룹마다 다른
layout.tsx사용 - 논리적 그룹핑: 관련된 페이지들을 함께 관리
기본 예시
plainapp/ ├── (auth)/ │ ├── login/ │ │ └── page.tsx # URL: /login │ └── register/ │ └── page.tsx # URL: /register └── (main)/ └── dashboard/ └── page.tsx # URL: /dashboard
완성된 폴더 구조
메타모스트 스타일 애플리케이션의 최종 폴더 구조는 다음과 같니다:
plainsrc/ └── app/ ├── page.tsx # 홈 (인증 체크 후 리다이렉트) │ ├── (auth)/ # 🔐 인증 관련 (헤더 없음) │ ├── login/ │ │ └── page.tsx # /login │ ├── register/ │ │ └── page.tsx # /register │ ├── components/ │ ├── hooks/ │ ├── types/ │ └── layout.tsx # 인증 전용 레이아웃 │ ├── (onboarding)/ # 🚀 온보딩 (헤더 있음) │ ├── server-connect/ │ │ └── page.tsx # /server-connect │ ├── components/ │ ├── hooks/ │ ├── types/ │ └── layout.tsx # 헤더 포함 레이아웃 │ ├── (projects)/ # 💬 워크스페이스 (헤더 없음) │ ├── project/ │ │ ├── page.tsx # /workspace │ │ ├── create/ │ │ │ └── page.tsx # /workspace/create │ │ └── layout.tsx │ │ │ ├── [project_id]/ # 동적 라우팅 │ │ ├── page.tsx # /team123 (기본 채널로 리다이렉트) │ │ ├── channels/ │ │ │ └── [channel_id]/ │ │ │ └── page.tsx # /team123/channels/general │ │ ├── messages/ │ │ │ └── [user_id]/ │ │ │ └── page.tsx # /team123/messages/john │ │ ├── settings/ │ │ │ └── page.tsx # /team123/settings │ │ └── layout.tsx # 워크스페이스 사이드바 레이아웃 │ │ │ ├── components/ │ ├── hooks/ │ ├── types/ │ └── layout.tsx # 워크스페이스 영역 공통 레이아웃 │ └── layout.tsx # 전역 레이아웃 (HTML, 폰트 등)
| URL | 적용되는 레이아웃 |
|---|---|
/login | RootLayout + AuthLayout |
/server-connect | RootLayout + OnboardingLayout (헤더 있음) |
/workspace | RootLayout + WorkspaceAreaLayout (헤더 없음) |
/team123/channels/general | RootLayout + WorkspaceAreaLayout + WorkspaceLayout |
핵심 장점
1. 논리적 분리가 명확
각 라우트 그룹이 담당하는 역할이 명확:
(auth)→ 인증 관련(onboarding)→ 초기 설정(workspace)→ 실제 서비스 이용
2. 레이아웃 관리가 직관적
각 영역별로 완전히 다른 UI/UX를 적용할 수 있음:
- 인증 페이지: 중앙 정렬, 심플한 디자인
- 온보딩: 헤더 포함, 안내 메시지
- 워크스페이스: 풀스크린, 사이드바, 다크 테마
3. 코로케이션(Colocation) 패턴
관련된 리소스들을 함께 관리할 수 있음:
typescript// 같은 그룹 내에서 import
import { useAuth } from '../hooks/useAuth';
import { LoginForm } from '../components/LoginForm';
import { AuthUser } from '../types/auth';
4. 팀 협업에 최적화
- 인증 담당자 →
(auth)폴더만 작업 - 채팅 담당자 →
(workspace)폴더만 작업 - 충돌 최소화 및 코드 리뷰 효율성 증대
5. 확장성
새로운 기능 영역을 쉽게 추가할 수 있음:
plain(admin)/ → 관리자 패널 (mobile)/ → 모바일 전용 페이지 (public)/ → 비로그인 사용자용
전역 공통 요소 관리
라우트 그룹별로 관리하는 것과 별도로, 전역에서 사용하는 요소들은 따로 관리:
plainsrc/ ├── lib/ # 전역 유틸리티 ├── components/ │ └── ui/ # shadcn/ui 같은 공통 컴포넌트 └── types/ └── global.ts # 전역 타입들
마무리
Next.js App Router의 라우트 그룹을 활용하면:
- 논리적으로 명확한 구조를 만들 수 있다
- 각 영역별로 독립적인 레이아웃을 적용할 수 있다
- 관련 리소스들을 함께 관리하여 코드 응집도를 높일 수 있다
- 팀 협업과 확장성을 크게 개선할 수 있다
특히 디스코드, 슬랙, 메타모스트 같은 복잡한 애플리케이션을 개발할 때 이런 구조화가 필수적이다. 처음 설정할 때는 복잡해 보이지만, 프로젝트가 커질수록 그 가치를 확실히 느낄 수 있을 것이라고 생각한다.
