@wondev/dotenv-example 1.0.2 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +38 -0
- package/CLAUDE.md +1 -40
- package/bin/index.js +64 -55
- package/package.json +8 -2
- package/prompts/20260102_165844.md +3 -0
- package/prompts/20260102_170026.md +3 -0
- package/prompts/20260102_170120.md +4 -0
- package/prompts/20260102_170500.md +3 -0
- package/prompts/20260102_170839.md +3 -0
- package/prompts/20260102_171046.md +3 -0
- package/prompts/20260102_171147.md +38 -0
- package/prompts/20260102_171336.md +76 -0
- package/prompts/20260102_171546.md +40 -0
- package/.claude/README.md +0 -60
- package/.claude/commands/business_logic.md +0 -143
- package/.claude/commands/generate-prd.md +0 -175
- package/.claude/commands/gotobackend.md +0 -569
- package/.claude/commands/playwrightMCP_install.md +0 -113
- package/.claude/commands/setting_dev.md +0 -731
- package/.claude/commands/tech-lead.md +0 -404
- package/.claude/commands/user-flow.md +0 -839
- package/.claude/settings.local.json +0 -9
- package/.cursor/README.md +0 -10
- package/.cursor/mcp.json +0 -31
- package/.cursor/rules/common/cursor-rules.mdc +0 -53
- package/.cursor/rules/common/git-convention.mdc +0 -86
- package/.cursor/rules/common/self-improve.mdc +0 -72
- package/.cursor/rules/common/tdd.mdc +0 -81
- package/.cursor/rules/common/vibe-coding.mdc +0 -114
- package/.cursor/rules/supabase/supabase-bootstrap-auth.mdc +0 -236
- package/.cursor/rules/supabase/supabase-create-db-functions.mdc +0 -136
- package/.cursor/rules/supabase/supabase-create-migration.mdc +0 -50
- package/.cursor/rules/supabase/supabase-create-rls-policies.mdc +0 -248
- package/.cursor/rules/supabase/supabase-declarative-database-schema.mdc +0 -78
- package/.cursor/rules/supabase/supabase-postgres-sql-style-guide.mdc +0 -133
- package/.cursor/rules/supabase/supabase-writing-edge-functions.mdc +0 -105
- package/.cursor/rules/web/design-rules.mdc +0 -381
- package/.cursor/rules/web/nextjs-convention.mdc +0 -237
- package/.cursor/rules/web/playwright-test-guide.mdc +0 -176
- package/.cursor/rules/web/toss-frontend.mdc +0 -695
- package/.env +0 -4
|
@@ -1,237 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: This rule defines unified conventions and best practices for building scalable, maintainable, and consistent fullstack applications with Next.js, covering file naming, directory structure, component architecture, and technology stack guidelines based on React 19 and Next.js 15.
|
|
3
|
-
globs: **/*.js,**/*.jsx,**/*.ts,**/*.tsx
|
|
4
|
-
alwaysApply: false
|
|
5
|
-
---
|
|
6
|
-
# NextJS Convention
|
|
7
|
-
|
|
8
|
-
## Package Manager
|
|
9
|
-
|
|
10
|
-
pnpm을 사용합니다.
|
|
11
|
-
만약 pnpm 에러가 난다면 `npm install -g pnpm` 명령어로 pnpm을 설치합니다.
|
|
12
|
-
|
|
13
|
-
## File Name Convention
|
|
14
|
-
|
|
15
|
-
- 모든 파일명은 `kebab-case` 로 작성합니다.
|
|
16
|
-
- `not-found.tsx`, `mdx-components.tsx` 처럼, 최대한 간결하게 하되, 단어 사이는 하이픈으로 연결합니다.
|
|
17
|
-
|
|
18
|
-
## Function/Variable Convention
|
|
19
|
-
|
|
20
|
-
- `camelCase` 로 작성합니다.
|
|
21
|
-
- TypeScript 타입은 반드시 정의해야 합니다.
|
|
22
|
-
|
|
23
|
-
## Component Convention
|
|
24
|
-
|
|
25
|
-
- Component 명은 `PascalCase` 로 작성합니다. (Component 파일명도 예외없이 `kebab-case`로 작성합니다)
|
|
26
|
-
- Component는 재사용 가능하도록 설계해야 합니다.
|
|
27
|
-
|
|
28
|
-
## Directory Convention
|
|
29
|
-
|
|
30
|
-
`app` 외부에 프로젝트 파일 저장하는 방법을 사용합니다.
|
|
31
|
-
|
|
32
|
-
### src/app
|
|
33
|
-
|
|
34
|
-
- 라우팅 용으로 사용한다. (라우팅과 관련된 파일만 넣어놓는다)
|
|
35
|
-
- e.g. `page.tsx`, `layout.tsx`, `opengraph-image.tsx`
|
|
36
|
-
|
|
37
|
-
### src/actions
|
|
38
|
-
|
|
39
|
-
- 무조건 API 대신 Server Action을 사용한다. 불가피한 경우에만 API를 사용한다.
|
|
40
|
-
- NextJS Server Action 파일들을 넣어놓는다.
|
|
41
|
-
|
|
42
|
-
### src/components
|
|
43
|
-
|
|
44
|
-
- 여러 페이지에서 공통으로 사용할 컴포넌트
|
|
45
|
-
- Button, Loading...
|
|
46
|
-
|
|
47
|
-
### src/constants
|
|
48
|
-
|
|
49
|
-
- 공통으로 사용 할 상수
|
|
50
|
-
|
|
51
|
-
### src/hooks
|
|
52
|
-
|
|
53
|
-
- 페이지 곳곳에서 사용되는 공통 훅
|
|
54
|
-
|
|
55
|
-
### src/utils
|
|
56
|
-
|
|
57
|
-
- 공통으로 사용되는 유틸 함수
|
|
58
|
-
- e.g. supabase/client.ts, supabase/server.ts ...
|
|
59
|
-
|
|
60
|
-
### src/states
|
|
61
|
-
|
|
62
|
-
- props drilling을 막기 위한 전역 state를 모아둔다.
|
|
63
|
-
- 전역 상태관리는 최대한 남발하지 않으며 jotai를 사용한다.
|
|
64
|
-
|
|
65
|
-
### src/types
|
|
66
|
-
|
|
67
|
-
- 각종 타입 스크립트의 정의가 들어가는 곳
|
|
68
|
-
|
|
69
|
-
### tests
|
|
70
|
-
|
|
71
|
-
- 테스트 파일을 모아두는 곳
|
|
72
|
-
|
|
73
|
-
## Package Convention
|
|
74
|
-
|
|
75
|
-
### Vitest
|
|
76
|
-
|
|
77
|
-
```sh
|
|
78
|
-
pnpm install -D vitest @vitejs/plugin-react jsdom @testing-library/react @testing-library/dom vite-tsconfig-paths
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
`vitest.config.mts`
|
|
82
|
-
```json
|
|
83
|
-
import { defineConfig } from 'vitest/config'
|
|
84
|
-
import react from '@vitejs/plugin-react'
|
|
85
|
-
import tsconfigPaths from 'vite-tsconfig-paths'
|
|
86
|
-
|
|
87
|
-
export default defineConfig({
|
|
88
|
-
plugins: [tsconfigPaths(), react()],
|
|
89
|
-
test: {
|
|
90
|
-
environment: 'jsdom',
|
|
91
|
-
},
|
|
92
|
-
})
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
`package.json`
|
|
96
|
-
```json
|
|
97
|
-
{
|
|
98
|
-
"scripts": {
|
|
99
|
-
"dev": "next dev",
|
|
100
|
-
"build": "next build",
|
|
101
|
-
"start": "next start",
|
|
102
|
-
"test": "vitest" // 추가
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
테스트 예시: `__tests__/page.test.tsx`
|
|
108
|
-
```tsx
|
|
109
|
-
import { expect, test } from 'vitest'
|
|
110
|
-
import { render, screen } from '@testing-library/react'
|
|
111
|
-
import Page from '../app/page'
|
|
112
|
-
|
|
113
|
-
test('Page', () => {
|
|
114
|
-
render(<Page />)
|
|
115
|
-
expect(screen.getByRole('heading', { level: 1, name: 'Home' })).toBeDefined()
|
|
116
|
-
})
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
### TailwindCSS
|
|
120
|
-
|
|
121
|
-
- 모든 스타일은 TailwindCSS를 사용해야 합니다.
|
|
122
|
-
- TailwindCSS v4 버전을 사용합니다.
|
|
123
|
-
- 그러므로 `tailwind.config.js`, `tailwind.config.ts` 파일은 사용하지 않고 `globals.css` 파일만을 사용합니다.
|
|
124
|
-
|
|
125
|
-
### ShadCN Component
|
|
126
|
-
|
|
127
|
-
- 모든 UI 컴포넌트는 ShadCN을 사용해야 합니다.
|
|
128
|
-
- 컴포넌트 사용 전 설치 여부를 확인해야 합니다: `/component/ui` 디렉토리 체크
|
|
129
|
-
- 컴포넌트 설치 명령어를 사용해야 합니다: `pnpx shadcn@latest add [component-name]`
|
|
130
|
-
|
|
131
|
-
### lucide-react
|
|
132
|
-
|
|
133
|
-
- 모든 아이콘은 lucide-react를 사용해야 합니다.
|
|
134
|
-
- 아이콘 임포트 방법: `import { IconName } from 'lucide-react';`
|
|
135
|
-
- 예시: `import { Menu, X } from 'lucide-react';`
|
|
136
|
-
|
|
137
|
-
### Jotai
|
|
138
|
-
|
|
139
|
-
- 전역 상태관리는 Jotai를 사용해야 합니다.
|
|
140
|
-
|
|
141
|
-
### React Query
|
|
142
|
-
|
|
143
|
-
- 데이터 패칭은 React Query를 사용해야 합니다.
|
|
144
|
-
|
|
145
|
-
### Supabase
|
|
146
|
-
|
|
147
|
-
- 데이터베이스는 Supabase를 사용해야 하며 `@supabase/supabase-js`를 사용해야 합니다.
|
|
148
|
-
- 사용자 인증은 Supabase Auth를 사용해야 하며 `@supabase/ssr`를 사용해야 합니다.
|
|
149
|
-
- 클라이언트 파일은 `utils/supabase` 폴더에 넣어야 합니다.
|
|
150
|
-
|
|
151
|
-
## Analysis Process
|
|
152
|
-
|
|
153
|
-
Before responding to any request, follow these steps:
|
|
154
|
-
|
|
155
|
-
1. Request Analysis
|
|
156
|
-
- Determine task type (code creation, debugging, architecture, etc.)
|
|
157
|
-
- Identify languages and frameworks involved
|
|
158
|
-
- Note explicit and implicit requirements
|
|
159
|
-
- Define core problem and desired outcome
|
|
160
|
-
- Consider project context and constraints
|
|
161
|
-
|
|
162
|
-
2. Solution Planning
|
|
163
|
-
- Break down the solution into logical steps
|
|
164
|
-
- Consider modularity and reusability
|
|
165
|
-
- Identify necessary files and dependencies
|
|
166
|
-
- Evaluate alternative approaches
|
|
167
|
-
- Plan for testing and validation
|
|
168
|
-
|
|
169
|
-
3. Implementation Strategy
|
|
170
|
-
- Choose appropriate design patterns
|
|
171
|
-
- Consider performance implications
|
|
172
|
-
- Plan for error handling and edge cases
|
|
173
|
-
- Ensure accessibility compliance
|
|
174
|
-
- Verify best practices alignment
|
|
175
|
-
|
|
176
|
-
## Feature Implementation Workflow
|
|
177
|
-
|
|
178
|
-
기능을 구현할 때는 **반드시** 다음의 조건과 단계를 따릅니다:
|
|
179
|
-
1. **계획 수립 및 검토:**
|
|
180
|
-
- 요구사항 분석을 바탕으로 구체적인 구현 계획을 세웁니다.
|
|
181
|
-
- 수립된 계획을 사용자에게 제시하고, 진행 전에 반드시 검토와 승인을 받습니다.
|
|
182
|
-
2. **단계적 구현 및 검증:**
|
|
183
|
-
- 기능 구현 과정을 논리적인 작은 단위로 세분화하여 단계적으로 진행합니다.
|
|
184
|
-
- 각 단계의 핵심 로직에는 서버 및 클라이언트 환경 모두에 로그(예: `console.group`, `console.log`)를 추가합니다.
|
|
185
|
-
- 로그는 기능의 정상 작동 여부를 확인하고, 잠재적인 문제를 조기에 발견하여 디버깅하는 데 활용됩니다.
|
|
186
|
-
- 구현이 완료되고 안정화된 후에는 디버깅 목적의 로그는 제거하거나, 필요한 경우 최소한으로 유지하는 것을 고려합니다.
|
|
187
|
-
- 각 단계 구현 후에는 충분한 테스트와 검증을 통해 의도한 대로 작동하는지 확인합니다.
|
|
188
|
-
|
|
189
|
-
## Code Style and Structure
|
|
190
|
-
|
|
191
|
-
### General Principles
|
|
192
|
-
|
|
193
|
-
- Write concise, readable TypeScript code
|
|
194
|
-
- Use functional and declarative programming patterns
|
|
195
|
-
- Follow DRY (Don't Repeat Yourself) principle
|
|
196
|
-
- Implement early returns for better readability
|
|
197
|
-
- Structure components logically: exports, subcomponents, helpers, types
|
|
198
|
-
|
|
199
|
-
### Naming Conventions
|
|
200
|
-
|
|
201
|
-
- Use descriptive names with auxiliary verbs (isLoading, hasError)
|
|
202
|
-
- Prefix event handlers with "handle" (handleClick, handleSubmit)
|
|
203
|
-
- Use lowercase with dashes for directories (components/auth-wizard)
|
|
204
|
-
- Favor named exports for components
|
|
205
|
-
|
|
206
|
-
### TypeScript Usage
|
|
207
|
-
|
|
208
|
-
- Use TypeScript for all code
|
|
209
|
-
- Prefer interfaces over types
|
|
210
|
-
- Avoid enums; use const maps instead
|
|
211
|
-
- Implement proper type safety and inference
|
|
212
|
-
- Use `satisfies` operator for type validation
|
|
213
|
-
|
|
214
|
-
## React 19 and Next.js 15 Best Practices
|
|
215
|
-
|
|
216
|
-
### Component Architecture
|
|
217
|
-
|
|
218
|
-
- Favor React Server Components (RSC) where possible
|
|
219
|
-
- Minimize 'use client' directives
|
|
220
|
-
- Implement proper error boundaries
|
|
221
|
-
- Use Suspense for async operations
|
|
222
|
-
- Optimize for performance and Web Vitals
|
|
223
|
-
|
|
224
|
-
### Async Request APIs
|
|
225
|
-
|
|
226
|
-
```typescript
|
|
227
|
-
// Always use async versions of runtime APIs
|
|
228
|
-
const cookieStore = await cookies()
|
|
229
|
-
const headersList = await headers()
|
|
230
|
-
const { isEnabled } = await draftMode()
|
|
231
|
-
|
|
232
|
-
// Handle async params in layouts/pages
|
|
233
|
-
const params = await props.params
|
|
234
|
-
const searchParams = await props.searchParams
|
|
235
|
-
```
|
|
236
|
-
|
|
237
|
-
<!-- https://github.com/PatrickJS/awesome-cursorrules/blob/main/rules/nextjs15-react19-vercelai-tailwind-cursorrules-prompt-file/.cursorrules -->
|
|
@@ -1,176 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: Playwright 테스트 작성 가이드
|
|
3
|
-
globs:
|
|
4
|
-
alwaysApply: false
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# Playwright 테스트 작성 가이드
|
|
8
|
-
|
|
9
|
-
## 1. 프로젝트 구조
|
|
10
|
-
|
|
11
|
-
```
|
|
12
|
-
tests/
|
|
13
|
-
├── e2e/ # E2E 테스트
|
|
14
|
-
├── integration/ # 통합 테스트
|
|
15
|
-
├── fixtures/ # 테스트 데이터
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
-
## 2. 테스트 파일 작성 규칙
|
|
19
|
-
|
|
20
|
-
### 파일 명명 규칙
|
|
21
|
-
|
|
22
|
-
- 테스트 파일은 .spec.ts 확장자 사용
|
|
23
|
-
- 파일명은 하이픈(-)으로 구분하고 테스트 대상을 명확히 표현
|
|
24
|
-
|
|
25
|
-
```
|
|
26
|
-
login.spec.ts
|
|
27
|
-
create-post.spec.ts
|
|
28
|
-
user-profile.spec.ts
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
### 기본 테스트 구조
|
|
32
|
-
|
|
33
|
-
```ts
|
|
34
|
-
import { test, expect } from '@playwright/test';
|
|
35
|
-
import { TEST_USERS } from '../fixtures/users';
|
|
36
|
-
|
|
37
|
-
test.describe('인증 및 로그인 테스트', () => {
|
|
38
|
-
test.beforeEach(async ({ page }) => {
|
|
39
|
-
await page.goto('/login');
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
test('유효한 자격증명으로 로그인 시 대시보드로 이동', async ({ page }) => {
|
|
43
|
-
// 테스트 로직
|
|
44
|
-
});
|
|
45
|
-
});
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
## 3. 테스트 케이스 작성 규칙
|
|
49
|
-
|
|
50
|
-
### 테스트 설명
|
|
51
|
-
|
|
52
|
-
```ts
|
|
53
|
-
// ❌ 잘못된 예
|
|
54
|
-
test('login test', async ({ page }) => {});
|
|
55
|
-
|
|
56
|
-
// ✅ 좋은 예
|
|
57
|
-
test('유효한 이메일과 비밀번호로 로그인 시 대시보드로 이동해야 함', async ({
|
|
58
|
-
page,
|
|
59
|
-
}) => {});
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
### 테스트 단계 구분
|
|
63
|
-
|
|
64
|
-
```ts
|
|
65
|
-
test('상품 구매 프로세스', async ({ page }) => {
|
|
66
|
-
await test.step('상품 페이지 진입', async () => {
|
|
67
|
-
await page.goto('/products/1');
|
|
68
|
-
await expect(page).toHaveURL('/products/1');
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
await test.step('장바구니에 추가', async () => {
|
|
72
|
-
await page.getByRole('button', { name: '장바구니 추가' }).click();
|
|
73
|
-
await expect(page.getByRole('alert')).toHaveText(
|
|
74
|
-
'장바구니에 추가되었습니다',
|
|
75
|
-
);
|
|
76
|
-
});
|
|
77
|
-
});
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
## 4. Locator 전략
|
|
81
|
-
|
|
82
|
-
### 우선순위
|
|
83
|
-
|
|
84
|
-
```ts
|
|
85
|
-
// 1. Role과 접근성 속성 (최우선)
|
|
86
|
-
page.getByRole('button', { name: '로그인' });
|
|
87
|
-
page.getByLabel('이메일');
|
|
88
|
-
page.getByRole('textbox', { name: '비밀번호' });
|
|
89
|
-
page.getByRole('heading', { name: '회원가입' });
|
|
90
|
-
|
|
91
|
-
// 2. 텍스트 및 기타
|
|
92
|
-
page.getByText('계정 만들기');
|
|
93
|
-
page.getByPlaceholder('이메일을 입력하세요');
|
|
94
|
-
|
|
95
|
-
// 3. 테스트 ID (Role과 접근성 속성으로 선택이 어려운 경우에 사용)
|
|
96
|
-
// ⚠️ 사용 전 반드시 해당 요소에 data-testid 속성이 정의되어 있는지 확인
|
|
97
|
-
page.getByTestId('submit-button');
|
|
98
|
-
|
|
99
|
-
// 안티 패턴
|
|
100
|
-
// ❌ 피해야 할 방식
|
|
101
|
-
page.locator('.login-btn');
|
|
102
|
-
page.locator('div > button');
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
## 5. 검증(Assertions) 가이드
|
|
106
|
-
|
|
107
|
-
```ts
|
|
108
|
-
// 요소 상태 검증
|
|
109
|
-
await expect(page.getByRole('button')).toBeEnabled();
|
|
110
|
-
await expect(page.getByRole('alert')).toBeVisible();
|
|
111
|
-
|
|
112
|
-
// 텍스트 검증
|
|
113
|
-
await expect(page.getByRole('heading')).toHaveText('환영합니다');
|
|
114
|
-
|
|
115
|
-
// URL 검증
|
|
116
|
-
await expect(page).toHaveURL(/.*dashboard/);
|
|
117
|
-
|
|
118
|
-
// 다중 요소 검증
|
|
119
|
-
await expect(page.getByRole('listitem')).toHaveCount(3);
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
## 6. 테스트 데이터 관리
|
|
123
|
-
|
|
124
|
-
```ts
|
|
125
|
-
// tests/fixtures/users.ts
|
|
126
|
-
export const TEST_USERS = {
|
|
127
|
-
valid: {
|
|
128
|
-
email: 'test@example.com',
|
|
129
|
-
password: 'password123',
|
|
130
|
-
},
|
|
131
|
-
invalid: {
|
|
132
|
-
email: 'invalid@example.com',
|
|
133
|
-
password: 'wrong',
|
|
134
|
-
},
|
|
135
|
-
};
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
## 7. 모킹 전략
|
|
139
|
-
|
|
140
|
-
다음과 같은 경우에만 API 모킹을 사용합니다:
|
|
141
|
-
|
|
142
|
-
- 외부 API 의존성이 있는 경우
|
|
143
|
-
- 테스트 환경에서 실제 API가 사용 불가능한 경우
|
|
144
|
-
- 특정 에러 상황 테스트가 필요한 경우
|
|
145
|
-
|
|
146
|
-
```ts
|
|
147
|
-
// 특정 에러 상황 테스트를 위한 모킹 예시
|
|
148
|
-
test('API 에러 발생 시 에러 메시지 표시', async ({ page }) => {
|
|
149
|
-
await page.route('**/api/users', (route) => {
|
|
150
|
-
route.fulfill({
|
|
151
|
-
status: 500,
|
|
152
|
-
contentType: 'application/json',
|
|
153
|
-
body: JSON.stringify({ error: '서버 오류가 발생했습니다.' }),
|
|
154
|
-
});
|
|
155
|
-
});
|
|
156
|
-
|
|
157
|
-
await page.goto('/users');
|
|
158
|
-
await expect(page.getByRole('alert')).toHaveText('서버 오류가 발생했습니다.');
|
|
159
|
-
});
|
|
160
|
-
```
|
|
161
|
-
|
|
162
|
-
## 8. 인증 상태 관리 (storageState)
|
|
163
|
-
|
|
164
|
-
### 인증이 필요한 테스트에서 사용
|
|
165
|
-
|
|
166
|
-
```typescript
|
|
167
|
-
// tests/e2e/protected-route.spec.ts
|
|
168
|
-
import { test } from '@playwright/test';
|
|
169
|
-
|
|
170
|
-
test.use({ storageState: './tests/fixtures/auth.json' });
|
|
171
|
-
|
|
172
|
-
test('인증이 필요한 페이지 접근', async ({ page }) => {
|
|
173
|
-
await page.goto('/dashboard');
|
|
174
|
-
// ... 테스트 로직
|
|
175
|
-
});
|
|
176
|
-
```
|