|
| 1 | +--- |
| 2 | +description: |
| 3 | +globs: |
| 4 | +alwaysApply: true |
| 5 | +--- |
| 6 | +# Next.js 15 App Router Co-location 폴더 구조 가이드 |
| 7 | + |
| 8 | +## 프로젝트 구조 원칙 |
| 9 | + |
| 10 | +### 1. Co-location 패턴 |
| 11 | +- 관련된 파일들을 가능한 한 가까운 곳에 배치 |
| 12 | +- 언더스코어(_) 접두사로 라우팅에 포함되지 않는 폴더 구분 |
| 13 | +- Route Groups `(groupName)`으로 관련 페이지 그룹화 |
| 14 | + |
| 15 | +### 2. 계층적 공유 |
| 16 | +- 상위 레벨일수록 더 넓은 범위에서 공유 |
| 17 | +- 도메인별 특화 vs 전역 공통 요소 명확히 구분 |
| 18 | + |
| 19 | +## 폴더 구조 |
| 20 | + |
| 21 | +``` |
| 22 | +src/ |
| 23 | +├── app/ # Next.js App Router |
| 24 | +│ ├── (domain)/ # Route Group 예시 (비즈니스 도메인명으로 변경) |
| 25 | +│ │ ├── _types/ # 해당 도메인 그룹 전용 타입 |
| 26 | +│ │ │ ├── domain.types.ts |
| 27 | +│ │ │ └── index.ts |
| 28 | +│ │ ├── _schemas/ # 해당 도메인 그룹 전용 Zod 스키마 |
| 29 | +│ │ │ ├── form.schema.ts |
| 30 | +│ │ │ └── index.ts |
| 31 | +│ │ ├── _utils/ # 해당 도메인 그룹 전용 유틸 |
| 32 | +│ │ │ ├── domainUtils.ts |
| 33 | +│ │ │ └── index.ts |
| 34 | +│ │ ├── _constants/ # 해당 도메인 그룹 전용 상수 |
| 35 | +│ │ │ ├── domain.constants.ts |
| 36 | +│ │ │ └── index.ts |
| 37 | +│ │ ├── _api/ # 해당 도메인 그룹 전용 API/TanStack Query |
| 38 | +│ │ │ ├── domain.api.ts |
| 39 | +│ │ │ ├── domain.queries.ts |
| 40 | +│ │ │ └── index.ts |
| 41 | +│ │ ├── _hooks/ # 해당 도메인 그룹 공통 훅 |
| 42 | +│ │ │ ├── useDomainData.ts |
| 43 | +│ │ │ └── index.ts |
| 44 | +│ │ ├── _components/ # 해당 도메인 그룹 공통 컴포넌트 |
| 45 | +│ │ │ ├── DomainLayout.tsx |
| 46 | +│ │ │ └── index.ts |
| 47 | +│ │ ├── feature/ # 페이지별 폴더 (기능명으로 변경) |
| 48 | +│ │ │ ├── _components/ # 해당 페이지 전용 컴포넌트 |
| 49 | +│ │ │ │ ├── FeatureSection.tsx |
| 50 | +│ │ │ │ └── index.ts |
| 51 | +│ │ │ ├── _hooks/ # 해당 페이지 전용 훅 |
| 52 | +│ │ │ │ ├── useFeatureData.ts |
| 53 | +│ │ │ │ └── index.ts |
| 54 | +│ │ │ └── page.tsx |
| 55 | +│ │ └── layout.tsx |
| 56 | +│ ├── globals.css |
| 57 | +│ ├── layout.tsx |
| 58 | +│ ├── loading.tsx |
| 59 | +│ ├── error.tsx |
| 60 | +│ └── not-found.tsx |
| 61 | +├── components/ # 전역 공통 UI 컴포넌트 |
| 62 | +│ ├── ui/ |
| 63 | +│ │ ├── Button.tsx |
| 64 | +│ │ └── index.ts |
| 65 | +│ └── index.ts |
| 66 | +├── hooks/ # 전역 공통 훅 |
| 67 | +│ ├── useLocalStorage.ts |
| 68 | +│ └── index.ts |
| 69 | +├── lib/ # 전역 공통 라이브러리 |
| 70 | +│ ├── utils/ # 전역 공통 유틸리티 |
| 71 | +│ │ ├── dateUtils.ts |
| 72 | +│ │ ├── stringUtils.ts |
| 73 | +│ │ └── index.ts |
| 74 | +│ ├── api/ # 전역 API 관련 |
| 75 | +│ │ ├── client.ts |
| 76 | +│ │ ├── types.ts |
| 77 | +│ │ └── index.ts |
| 78 | +│ ├── validations/ # 전역 검증 로직 |
| 79 | +│ │ ├── common.schema.ts |
| 80 | +│ │ ├── validators.ts |
| 81 | +│ │ └── index.ts |
| 82 | +│ └── index.ts |
| 83 | +├── types/ # 전역 공통 타입 |
| 84 | +│ ├── global.types.ts |
| 85 | +│ └── index.ts |
| 86 | +├── constants/ # 전역 상수 |
| 87 | +│ ├── config.ts |
| 88 | +│ └── index.ts |
| 89 | +└── styles/ # 전역 스타일 (vanilla-extract) |
| 90 | + ├── globals.css.ts |
| 91 | + ├── theme.css.ts |
| 92 | + └── index.ts |
| 93 | +``` |
| 94 | + |
| 95 | +## 정적 자산 및 설정 파일 |
| 96 | + |
| 97 | +``` |
| 98 | +public/ # 정적 자산 |
| 99 | +├── images/ |
| 100 | +│ ├── icons/ |
| 101 | +│ └── logos/ |
| 102 | +├── favicon.ico |
| 103 | +└── robots.txt |
| 104 | + |
| 105 | +.env.local # 환경 변수 (로컬) |
| 106 | +.env.example # 환경 변수 예시 |
| 107 | +next.config.js # Next.js 설정 |
| 108 | +middleware.ts # Next.js 미들웨어 (루트) |
| 109 | +``` |
| 110 | + |
| 111 | +## 테스트 구조 |
| 112 | + |
| 113 | +### 테스트 파일 위치 규칙 |
| 114 | +- **단위 테스트**: 테스트하려는 모듈과 같은 폴더에 `.test.ts` 또는 `.test.tsx` 확장자로 배치 |
| 115 | +- **통합/E2E 테스트**: 별도 `__tests__` 폴더에서 관리 |
| 116 | + |
| 117 | +``` |
| 118 | +__tests__/ # 테스트 루트 폴더 |
| 119 | +├── unit/ # 단위 테스트 (모듈별로 구성) |
| 120 | +│ ├── components/ |
| 121 | +│ │ └── Button.test.tsx |
| 122 | +│ ├── hooks/ |
| 123 | +│ │ └── useLocalStorage.test.ts |
| 124 | +│ └── utils/ |
| 125 | +│ └── domainUtils.test.ts |
| 126 | +├── integration/ # 통합 테스트 |
| 127 | +│ ├── api/ |
| 128 | +│ │ └── domain.integration.test.ts |
| 129 | +│ └── pages/ |
| 130 | +│ └── feature.integration.test.tsx |
| 131 | +└── e2e/ # E2E 테스트 |
| 132 | + ├── specs/ |
| 133 | + │ ├── domain-flow.spec.ts |
| 134 | + │ └── user-journey.spec.ts |
| 135 | + ├── fixtures/ |
| 136 | + │ └── test-data.json |
| 137 | + └── support/ |
| 138 | + ├── commands.ts |
| 139 | + └── helpers.ts |
| 140 | +``` |
| 141 | + |
| 142 | +## 네이밍 규칙 |
| 143 | + |
| 144 | +### 파일 네이밍 |
| 145 | +- **컴포넌트**: PascalCase (예: `Button.tsx`, `DomainLayout.tsx`) |
| 146 | +- **훅**: camelCase with `use` 접두사 (예: `useLocalStorage.ts`, `useDomainData.ts`) |
| 147 | +- **유틸/API**: camelCase (예: `domainUtils.ts`, `domain.api.ts`) |
| 148 | +- **타입/스키마**: camelCase (예: `domain.types.ts`, `form.schema.ts`) |
| 149 | +- **상수**: camelCase (예: `domain.constants.ts`) |
| 150 | +- **스타일**: camelCase with `.css.ts` 확장자 (예: `Button.css.ts`, `theme.css.ts`) |
| 151 | + |
| 152 | +### 폴더 네이밍 |
| 153 | +- **Route Groups**: `(groupName)` 형태 |
| 154 | +- **비라우팅 폴더**: `_folderName` 형태 (언더스코어 접두사) |
| 155 | +- **일반 폴더**: kebab-case 또는 camelCase |
| 156 | + |
| 157 | +## 사용 기술 스택 고려사항 |
| 158 | + |
| 159 | +### 주요 라이브러리 |
| 160 | +- **폼 관리**: react-hook-form + zod |
| 161 | +- **데이터 페칭**: TanStack Query + ky |
| 162 | +- **스타일링**: vanilla-extract |
| 163 | +- **타입스크립트**: 모든 파일에서 TypeScript 사용 |
| 164 | + |
| 165 | +### API 및 상태 관리 |
| 166 | +- **API 호출**: `_api` 폴더에 `.api.ts` (ky 사용) + `.queries.ts` (TanStack Query) |
| 167 | +- **스키마 검증**: `_schemas` 폴더에 Zod 스키마 정의 |
| 168 | +- **타입 정의**: `_types` 폴더에 도메인별 타입 정의 |
| 169 | +- **상수 정의**: `_constants` 폴더에 도메인별 상수 정의 |
| 170 | + |
| 171 | +### 전역 공통 요소 구성 |
| 172 | +- **유틸리티**: `lib/utils/` 폴더에 기능별로 분리 (날짜, 문자열, 포맷팅 등) |
| 173 | +- **API 클라이언트**: `lib/api/` 폴더에 전역 API 설정 및 타입 |
| 174 | +- **검증 로직**: `lib/validations/` 폴더에 공통 스키마 및 검증 함수 |
| 175 | +- **스타일링**: `styles/` 폴더에 전역 테마 및 공통 스타일, 컴포넌트별 스타일은 해당 컴포넌트와 같은 위치 |
| 176 | + |
| 177 | +## 핵심 규칙 |
| 178 | + |
| 179 | +1. **응집도 우선**: 관련된 코드는 가능한 한 가까이 배치 |
| 180 | +2. **도메인 분리**: Route Groups를 활용하여 비즈니스 도메인별로 분리 |
| 181 | +3. **재사용성 고려**: 전역 공통 요소와 도메인별 요소 명확히 구분 |
| 182 | +4. **테스트 근접성**: 단위 테스트는 테스트 대상과 같은 폴더에 배치 |
| 183 | +5. **스타일 근접성**: vanilla-extract 스타일 파일은 해당 컴포넌트와 같은 폴더에 배치 |
| 184 | +6. **일관성 유지**: 네이밍 규칙과 폴더 구조 일관성 유지 |
0 commit comments