Skip to content

Commit 2047e3d

Browse files
authored
Merge pull request #20 from YAPP-Github/chore/#19
2 parents 2576bd2 + 93d45e6 commit 2047e3d

File tree

2 files changed

+185
-0
lines changed

2 files changed

+185
-0
lines changed
Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
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. **일관성 유지**: 네이밍 규칙과 폴더 구조 일관성 유지

eslint.config.mjs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ const eslintConfig = [
2929
fixStyle: "inline-type-imports",
3030
},
3131
],
32+
"@typescript-eslint/consistent-type-definitions": ["error", "type"],
3233
"@typescript-eslint/no-unused-vars": "error",
3334
"no-empty": "error",
3435
"simple-import-sort/imports": "error",

0 commit comments

Comments
 (0)