Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 68 additions & 0 deletions .claude/commands/api.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
$ARGUMENTS 기능에 대한 API 호출 함수와 TanStack Query 훅을 생성해주세요.

이 프로젝트의 API 패턴:

### 1. API 함수 (src/lib/)
```tsx
// src/lib/xxxApi.ts
const API_BASE = process.env.NEXT_PUBLIC_API_URL;

export const xxxApi = {
getList: async (params: ListParams): Promise<ListResponse> => {
const res = await fetch(`${API_BASE}/xxx?${new URLSearchParams(params)}`);
if (!res.ok) throw new Error('Failed to fetch');
return res.json();
},

getById: async (id: string): Promise<ItemResponse> => {
const res = await fetch(`${API_BASE}/xxx/${id}`);
if (!res.ok) throw new Error('Failed to fetch');
return res.json();
},

create: async (data: CreateData): Promise<ItemResponse> => {
const res = await fetch(`${API_BASE}/xxx`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
});
if (!res.ok) throw new Error('Failed to create');
return res.json();
},
};
```

### 2. Query 훅 (src/queries/ 또는 src/hooks/)
```tsx
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';

export const useXxxList = (params: ListParams) => {
return useQuery({
queryKey: ['xxx', 'list', params],
queryFn: () => xxxApi.getList(params),
});
};

export const useXxxDetail = (id: string) => {
return useQuery({
queryKey: ['xxx', 'detail', id],
queryFn: () => xxxApi.getById(id),
enabled: !!id,
});
};

export const useCreateXxx = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: xxxApi.create,
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['xxx'] });
},
});
};
```

사용 예시:
- `/api review` - 리뷰 API 및 쿼리 훅 생성
- `/api whiskey` - 위스키 API 및 쿼리 훅 생성
- `/api user` - 사용자 API 및 쿼리 훅 생성
29 changes: 29 additions & 0 deletions .claude/commands/component.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
$ARGUMENTS 이름으로 새로운 React 컴포넌트를 생성해주세요.

이 프로젝트의 컴포넌트 규칙:
- 함수형 컴포넌트 사용
- TypeScript로 props 타입 정의
- Tailwind CSS로 스타일링
- named export 사용

컴포넌트 구조:
```tsx
interface Props {
// props 정의
}

export function ComponentName({ ...props }: Props) {
return (
// JSX
);
}
```

생성 위치:
- 재사용 컴포넌트: `src/components/`
- 페이지 전용 컴포넌트: 해당 페이지의 `_components/` 폴더

사용 예시:
- `/component Button` - Button 컴포넌트 생성
- `/component ReviewCard` - ReviewCard 컴포넌트 생성
- `/component src/app/(primary)/settings/_components/ProfileForm` - 특정 경로에 생성
21 changes: 21 additions & 0 deletions .claude/commands/fix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
$ARGUMENTS 버그를 분석하고 수정해주세요.

(인자로 에러 메시지나 증상을 설명하면 더 정확한 분석이 가능합니다)

다음 단계로 진행해주세요:

1. **문제 파악**: 에러 메시지, 콘솔 로그, 재현 조건 확인
2. **원인 분석**: 관련 코드를 찾아 근본 원인 파악
3. **해결책 제시**: 가능한 해결 방안 설명
4. **수정 적용**: 코드 수정 및 테스트
5. **검증**: 수정 후 정상 동작 확인

수정 시 주의사항:
- 기존 기능에 영향 없도록 최소한의 변경
- 타입 안전성 유지
- 관련 테스트 업데이트 (필요시)

사용 예시:
- `/fix` - 현재 에러 수정
- `/fix TypeError: Cannot read property 'map' of undefined` - 특정 에러 수정
- `/fix 로그인 후 리다이렉트가 안됨` - 증상 기반 수정
35 changes: 35 additions & 0 deletions .claude/commands/hook.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
$ARGUMENTS 이름으로 커스텀 훅을 생성해주세요.

파일 위치: `src/hooks/`

이 프로젝트의 훅 패턴:
```tsx
import { useState, useCallback, useRef } from 'react';

interface Options {
// 옵션 타입 정의 (필요시)
}

export const useXxx = (options?: Options) => {
const [state, setState] = useState<Type>(initialValue);
const ref = useRef<NodeJS.Timeout | null>(null);

const action = useCallback((params: ParamType) => {
// 로직 구현
}, []);

return { state, action };
};
```

규칙:
- `use` 접두사 사용
- named export 사용 (`export const useXxx`)
- useCallback으로 함수 메모이제이션
- 타입 명시적 정의
- cleanup 로직 포함 (필요시)

사용 예시:
- `/hook useBookmark` - 북마크 관련 훅 생성
- `/hook useDebounce` - 디바운스 훅 생성
- `/hook useLocalStorage` - 로컬스토리지 훅 생성
49 changes: 49 additions & 0 deletions .claude/commands/page.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
$ARGUMENTS 경로에 Next.js App Router 페이지를 생성해주세요.

파일 위치: `src/app/`

이 프로젝트의 페이지 패턴:

### 기본 페이지 구조
```tsx
// src/app/(primary)/xxx/page.tsx
import { Metadata } from 'next';

export const metadata: Metadata = {
title: '페이지 제목 | Bottle Note',
description: '페이지 설명',
};

export default function XxxPage() {
return (
<main className="container mx-auto px-4 py-6">
{/* 페이지 컨텐츠 */}
</main>
);
}
```

### 동적 라우트
```tsx
// src/app/(primary)/xxx/[id]/page.tsx
interface Props {
params: { id: string };
}

export default function XxxDetailPage({ params }: Props) {
const { id } = params;
// ...
}
```

### 레이아웃 그룹
- `(primary)` - 메인 레이아웃 (헤더, 푸터 포함)
- `(custom)` - 커스텀 레이아웃 (로그인, OAuth 등)

### 페이지 전용 컴포넌트
- 해당 페이지 폴더 내 `_components/` 디렉토리에 생성

사용 예시:
- `/page settings/profile` - 프로필 설정 페이지 생성
- `/page whiskey/[id]` - 위스키 상세 페이지 생성
- `/page search` - 검색 페이지 생성
21 changes: 21 additions & 0 deletions .claude/commands/refactor.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
$ARGUMENTS 코드를 리팩토링해주세요.

(인자가 없으면 현재 파일을 리팩토링합니다)

리팩토링 원칙:
1. **기능 유지**: 외부 동작은 변경하지 않음
2. **가독성 향상**: 명확한 네이밍, 적절한 추상화
3. **중복 제거**: DRY 원칙 적용
4. **단순화**: 불필요한 복잡성 제거
5. **타입 강화**: any 타입 제거, 더 정확한 타입 사용

체크리스트:
- [ ] 함수/컴포넌트가 단일 책임을 가지는가?
- [ ] 코드가 자기 문서화되어 있는가?
- [ ] 테스트가 깨지지 않는가?
- [ ] 성능에 부정적 영향이 없는가?

사용 예시:
- `/refactor` - 현재 파일 리팩토링
- `/refactor useAuth` - 특정 훅 리팩토링
- `/refactor src/store/modalStore.ts` - 특정 파일 리팩토링
18 changes: 18 additions & 0 deletions .claude/commands/review.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
$ARGUMENTS 파일/코드를 리뷰해주세요.

(인자가 없으면 현재 작업 중인 코드를 리뷰합니다)

다음 항목들을 확인해주세요:
1. **타입 안전성**: TypeScript 타입이 올바르게 정의되어 있는지
2. **코드 품질**: 중복 코드, 불필요한 복잡성이 없는지
3. **성능**: 불필요한 리렌더링, 메모리 누수 가능성
4. **접근성**: 기본적인 a11y 준수 여부
5. **에러 처리**: 예외 상황 처리가 적절한지
6. **테스트 가능성**: 테스트하기 쉬운 구조인지

문제가 발견되면 구체적인 개선 방안을 제시해주세요.

사용 예시:
- `/review` - 현재 작업 중인 코드 리뷰
- `/review src/hooks/useToast.ts` - 특정 파일 리뷰
- `/review useModalStore` - 특정 함수/클래스 리뷰
47 changes: 47 additions & 0 deletions .claude/commands/store.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
$ARGUMENTS 이름으로 Zustand 스토어를 생성해주세요.

파일 위치: `src/store/`

이 프로젝트의 스토어 패턴:
```tsx
import { create } from 'zustand';

interface XxxState {
value: string;
isOpen: boolean;
}

interface XxxStore {
state: XxxState;
handleState: (newState: Partial<XxxState>) => void;
handleReset: () => void;
}

const initialState: XxxState = {
value: '',
isOpen: false,
};

const useXxxStore = create<XxxStore>((set) => ({
state: initialState,
handleState: (newState) =>
set((prev) => ({
state: { ...prev.state, ...newState },
})),
handleReset: () => set({ state: initialState }),
}));

export default useXxxStore;
```

규칙:
- `use...Store` 네이밍 사용
- State와 Store 인터페이스 분리
- initialState 별도 정의
- handleReset 함수 포함
- default export 사용

사용 예시:
- `/store filter` - filterStore 생성
- `/store cart` - cartStore 생성 (장바구니)
- `/store notification` - notificationStore 생성
25 changes: 25 additions & 0 deletions .claude/commands/test.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
$ARGUMENTS 에 대한 테스트 코드를 작성해주세요.

(인자가 없으면 현재 파일에 대한 테스트를 작성합니다)

이 프로젝트는 다음 테스트 도구를 사용합니다:
- Jest
- React Testing Library
- @testing-library/jest-dom

테스트 파일 규칙:
- 파일명: `*.test.tsx` 또는 `*.test.ts`
- 위치: 테스트 대상 파일과 같은 디렉토리

다음을 포함해주세요:
1. 기본 렌더링 테스트
2. 주요 기능 동작 테스트
3. 엣지 케이스 테스트
4. 에러 상태 테스트 (해당되는 경우)

테스트 실행: `pnpm test`

사용 예시:
- `/test` - 현재 파일 테스트 작성
- `/test useToast` - useToast 훅 테스트 작성
- `/test src/components/Button.tsx` - 특정 컴포넌트 테스트 작성
69 changes: 69 additions & 0 deletions .cursorrules
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Bottle Note Frontend - Cursor Rules

You are an expert in Next.js 14 (App Router), React 18, TypeScript, and Tailwind CSS.

## Project Context
- 위스키 리뷰 및 평가 플랫폼 프론트엔드
- 한국어 서비스이므로 한국어 주석/문서 가능

## Tech Stack
- Next.js 14 with App Router
- TypeScript strict mode
- React 18 with functional components
- TanStack Query v5 for server state
- Zustand v4 for client state
- React Hook Form + Yup for forms
- Tailwind CSS for styling
- NextAuth.js for authentication
- pnpm as package manager

## Code Style

### TypeScript
- Always use TypeScript with explicit types
- Define types in `src/types/` directory
- Avoid `any` type

### React
- Use functional components only
- Use named exports for components
- Place page-specific components in `_components/` folder

### Imports (ESLint enforced order)
1. react, next
2. External packages
3. Internal: components, hooks, types, utils, store, constants
4. Relative paths

### Styling
- Use Tailwind CSS classes
- Use `clsx` or `tailwind-merge` for conditional classes

### State Management
- Server state: TanStack Query (useQuery, useMutation)
- Client state: Zustand stores in `src/store/`
- Form state: React Hook Form

## Conventions
- console.log is not allowed (use console.warn or console.error)
- Props spreading is allowed
- No defaultProps required (use default parameters)

## File Structure
```
src/
├── app/ # Next.js pages
├── components/ # Reusable components
├── hooks/ # Custom hooks
├── lib/ # API clients, utilities
├── queries/ # TanStack Query hooks
├── store/ # Zustand stores
├── types/ # TypeScript types
├── utils/ # Utility functions
└── constants/ # Constants
```

## Testing
- Jest + React Testing Library
- Test files: `*.test.tsx`
- Run: `pnpm test`
Loading