diff --git a/.cursorrules b/.cursorrules
new file mode 100644
index 00000000..a480cc00
--- /dev/null
+++ b/.cursorrules
@@ -0,0 +1,394 @@
+# .cursorrules
+
+> **디프만 18기 3팀 — 위시리스트 소비 결정 서비스**
+> 이 문서는 Cursor AI가 프로젝트 작업 시 반드시 따라야 할 규칙 및 컨텍스트를 정의합니다.
+> 팀원 전원이 공유하는 AI 협업 규약이며, 모든 코드 생성/리팩토링은 이 규약을 따릅니다.
+
+---
+
+## 🎯 프로젝트 컨텍스트
+
+### 한 줄 정의
+**쌓인 위시리스트에서 먼저 살 것을 골라주는 소비 결정 서비스**
+
+### 타겟 유저
+위시리스트와 장바구니는 가득하지만, 선택 피로로 구매를 계속 미루는 패션·라이프스타일 중심의 **20~30대 모바일 쇼핑 사용자**.
+
+### 핵심 기능
+- **링크 기반 상품 저장** — 여러 쇼핑몰 링크를 한곳에 모음
+- **1:1 토너먼트 비교** — 두 개씩 비교해 최종 1순위 결정 (WOW 포인트)
+- **AI 소비 메이트** — 질문/공감/리마인드 (WOW 포인트)
+- **보류함 & 재판단 알림** — 방치된 위시 재방문 유도
+- **커머스 직접 연동** — 결정된 상품 즉시 구매
+
+### 플랫폼 전략
+**RN(Expo) 앱이 WebView로 Next.js 웹앱을 감싸는 구조.**
+→ 실제 UI/비즈니스 로직은 `apps/web`에 집중. 네이티브 기능만 `apps/app`에서 처리.
+
+---
+
+## 💻 기술 스택
+
+### 공통
+- **패키지 매니저**: pnpm 10.17.0
+- **모노레포**: Turborepo
+- **언어**: TypeScript 5.9.2
+- **배포**: Vercel (web), Expo (app)
+
+### apps/web (Next.js)
+- **프레임워크**: Next.js 16 (App Router)
+- **React**: 19.2.0
+- **상태관리**: Zustand
+- **스타일링**: Tailwind CSS v4 (루트 공통 설정, 각 앱에서 상속)
+- **API 통신**: TanStack Query (@tanstack/react-query)
+- **스키마 검증**: Zod
+- **API 모킹**: MSW (필요 시)
+- **아이콘**: Lucide React 우선 → 불가 시 SVG 컴포넌트화
+
+### apps/app (React Native)
+- **프레임워크**: React Native + Expo
+- **라우팅**: Expo Router
+- **주요 역할**: WebView로 `apps/web` 렌더링
+
+### CI/CD
+- **GitHub Actions**: PR 단위 빌드 검사 (`lint` → `check-types` → `build`)
+- **필수 통과 조건**: `pnpm install --frozen-lockfile`
+
+---
+
+## 📁 프로젝트 구조
+
+### 모노레포 루트
+```
+18th-team3-client/
+├── apps/
+│ ├── app/ # React Native + Expo (WebView 래퍼)
+│ └── web/ # Next.js 16 (메인 서비스)
+├── packages/
+│ ├── core/ # @repo/core — 웹뷰 통신용 type/hook/util
+│ ├── ui/ # @repo/ui — 공유 UI (현재 미사용)
+│ ├── eslint-config/ # @repo/eslint-config
+│ └── typescript-config/ # @repo/typescript-config
+├── prettier.config.mjs # 루트 Prettier (공통)
+├── .prettierignore
+└── turbo.json
+```
+
+### apps/web 내부 (고전 구조)
+```
+apps/web/src/
+├── app/ # Next.js App Router (layout, page, providers)
+│ ├── layout.tsx
+│ ├── page.tsx
+│ ├── providers.tsx # TanStack Query Provider
+│ └── fonts/
+├── components/ # 재사용 가능한 공통 UI 컴포넌트
+├── apis/ # API 호출 함수 (HTTP 메서드 prefix 컨벤션)
+├── hooks/ # 커스텀 훅
+├── utils/ # 공통 유틸리티 함수
+├── types/ # 공통 타입 정의 (T suffix)
+├── assets/ # 정적 리소스 (SVG, 이미지)
+├── styles/ # globals.css (Tailwind import)
+└── consts/ # 상수
+```
+
+### Path Alias
+`@/*` → `apps/web/src/*`
+
+---
+
+## 📝 네이밍 컨벤션
+
+| 대상 | 규칙 | 예시 |
+|---|---|---|
+| **컴포넌트 파일** | PascalCase | `ScaleResult.tsx` |
+| **일반 파일** (훅, 유틸) | camelCase | `useAuth.ts`, `formatDate.ts` |
+| **폴더** | kebab-case | `scale-result/` |
+| **타입** | T suffix | `UserT`, `ProductT` |
+| **API 함수** | HTTP 메서드 prefix | `getUser`, `postWishlist`, `patchProfile`, `deleteItem` |
+
+---
+
+## 🎨 코딩 컨벤션
+
+### 컴포넌트
+- **`function` 키워드 + default export**
+
+```tsx
+function MyComponent({ children }: MyComponentProps) {
+ return
{children}
;
+}
+
+export default MyComponent;
+```
+
+### 유틸 함수
+- **화살표 함수** 사용
+
+```ts
+const formatDate = (date: Date) => date.toISOString();
+```
+
+### 타입 선언
+- **`type` 사용** (interface 대신)
+- **T suffix** (컨벤션상 타입 선언 시)
+- Props 타입명: `{ComponentName}Props`
+
+```ts
+type UserT = {
+ id: number;
+ name: string;
+};
+
+type MyComponentProps = {
+ children: React.ReactNode;
+};
+```
+
+### Props 네이밍
+- **내부 핸들러**: `handle-` (예: `handleClick`, `handleSubmit`)
+- **외부에서 받는 props**: `on-` (예: `onClick`, `onSubmit`)
+
+```tsx
+function Button({ onClick }: ButtonProps) {
+ const handleClick = () => {
+ // 내부 로직
+ onClick?.();
+ };
+ return ;
+}
+```
+
+### 기타
+- **세미콜론**: 사용 (`semi: true`)
+- **따옴표**: `singleQuote: true` (`'홑따옴표'`)
+- **printWidth**: 100
+- **trailingComma**: `'es5'`
+- **arrowParens**: `'avoid'` (인자 1개 시 괄호 생략)
+
+---
+
+## 📦 Import 규칙
+
+### 정렬 (자동화됨 — `@trivago/prettier-plugin-sort-imports`)
+```
+1. 외부 라이브러리 ()
+2. 절대경로 (^@/)
+3. 상대경로 (^[./])
+```
+
+### 예시
+```tsx
+import { useState } from 'react';
+import { useQuery } from '@tanstack/react-query';
+
+import { apiClient } from '@/apis/apiClient';
+import { UserT } from '@/types/user';
+
+import { formatDate } from './utils';
+import styles from './Page.module.css';
+```
+
+### Prettier 옵션
+- `importOrderSeparation: true` (그룹 간 빈 줄)
+- `importOrderSortSpecifiers: true` (그룹 내 알파벳 정렬)
+
+---
+
+## 🚨 ESLint 주요 규칙
+
+- `no-console`: warn/error만 허용 (`console.log` 금지)
+- `no-nested-ternary`: error (중첩 삼항 금지)
+- `@typescript-eslint/consistent-type-imports`: error (`import type` 강제)
+- `@typescript-eslint/no-explicit-any`: error (`any` 금지)
+- `unused-imports/no-unused-imports`: error
+- `_` prefix 변수/인자는 unused 허용
+
+---
+
+## 🔀 Git 전략
+
+### 브랜치 구조
+```
+main ← dev ← {type}/{issue-number}-{description}
+```
+
+### 브랜치 네이밍
+- **패턴**: `{type}/{issue-number}-{description}`
+- **예시**: `feat/1-login-page`, `chore/3-web-setup`, `fix/5-auth-bug`
+- **타입**: `feat`, `fix`, `chore`, `docs`, `refactor`, `style`, `test`
+
+### 커밋 메시지
+- **형식**: `{type}: {한글 설명}`
+- **예시**:
+ - `feat: 로그인 페이지 구현`
+ - `chore: Prettier 설정 추가`
+ - `fix: 토큰 만료 처리 수정`
+
+### 머지 방식
+- **Squash Merge** 사용
+- PR 제목이 그대로 dev의 커밋 메시지가 됨 → PR 제목 신중히 작성
+
+### PR 컨벤션
+- **base 브랜치**: `dev` (main 아님)
+- **템플릿**:
+```markdown
+## 작업 내용
+[내용 정리]
+
+## 스크린샷
+
+## 연관 이슈
+closes #이슈번호
+```
+
+### 코드 리뷰 — PN 룰
+- **P1** (Request changes): 꼭 반영 — 중대한 오류 가능성
+- **P2** (Request changes): 적극 고려 — 수용 or 토론
+- **P3** (Comment): 웬만하면 반영 — 미반영 시 사유 설명
+- **P4** (Approve): 반영해도/안해도 OK — 고민 정도
+- **P5** (Approve): 사소한 의견 — 무시 가능
+
+### 리뷰 규칙
+- **랜덤 1명 승인** 시 머지 가능
+- 리뷰 자동 배정 워크플로우 사용
+
+---
+
+## 🌐 API 통신 — Response Schema 규약
+
+### 기본 원칙
+1. **HTTP Status Code는 REST 의미대로 사용** (200, 201, 400, 401, 403, 404, 500)
+2. **성공/실패 Body 구조 통일**
+3. **`fetch`는 4xx/5xx에서 자동 throw 안 함** → 반드시 `response.ok` 확인
+4. **`success` 필드 사용 안 함** (`response.ok`와 중복)
+
+### 응답 구조
+```json
+{
+ "status": 200,
+ "data": {},
+ "detail": "요청이 정상적으로 처리되었습니다.",
+ "code": "COMMON_SUCCESS"
+}
+```
+
+| 필드 | 설명 |
+|---|---|
+| `status` | HTTP Status Code와 동일 |
+| `data` | 실제 비즈니스 응답 데이터 (실패 시 `null`) |
+| `detail` | 응답 메시지 (사용자 표시용) |
+| `code` | 서버 정의 Enum 코드 (세부 분기용) |
+
+### 검증 오류 응답 (400)
+```json
+{
+ "status": 400,
+ "data": null,
+ "detail": "입력값이 올바르지 않습니다.",
+ "code": "INVALID_INPUT",
+ "errors": [
+ { "field": "url", "reason": "URL 형식이 올바르지 않습니다." }
+ ]
+}
+```
+
+### 페이지 응답 구조
+```json
+{
+ "status": 200,
+ "data": [ { "wishId": 1, "title": "셔츠" } ],
+ "detail": "요청이 정상적으로 처리되었습니다.",
+ "code": "COMMON_SUCCESS",
+ "pageInfo": { "nextCursor": "abc123", "hasNext": true }
+}
+```
+
+### 프론트엔드 fetch 처리 표준
+```ts
+export async function request(url: string, options?: RequestInit) {
+ const response = await fetch(url, options);
+
+ let body;
+ try {
+ body = await response.json();
+ } catch {
+ throw new Error('서버 응답을 해석할 수 없습니다.');
+ }
+
+ if (response.ok) {
+ return body.data;
+ }
+
+ throw new Error(body.detail || '요청 처리 중 오류가 발생했습니다.');
+}
+```
+
+### 검증 오류 세부 처리
+```ts
+if (response.status === 400 && body.errors) {
+ return body.errors;
+}
+```
+
+### 분기 처리 (세부 에러)
+```ts
+if (body.code === 'WISH_NOT_FOUND') {
+ // 특정 에러 처리
+}
+```
+
+### HTTP Status 사용 기준
+| 상황 | HTTP Status |
+|---|---|
+| 조회 성공 | 200 OK |
+| 생성 성공 | 201 Created |
+| 잘못된 요청 | 400 Bad Request |
+| 인증 실패 | 401 Unauthorized |
+| 권한 없음 | 403 Forbidden |
+| 리소스 없음 | 404 Not Found |
+| 서버 오류 | 500 Internal Server Error |
+
+---
+
+## 🤖 Cursor AI 작업 지침
+
+### 코드 생성 시
+- **위 컨벤션을 반드시 준수**
+- 신규 컴포넌트: `function` 키워드 + PascalCase 파일명 + default export
+- 신규 훅: 화살표 함수 + camelCase 파일명
+- 신규 타입: `type` 키워드 + T suffix
+- API 함수: HTTP 메서드 prefix (`getUser`, `postWishlist` 등)
+- 경로는 `@/*` 절대경로 우선, 같은 디렉토리는 상대경로
+
+### 커밋 메시지 제안 시
+- `{type}: {한글 설명}` 형식 사용
+- type: feat, fix, chore, docs, refactor, style, test
+
+### PR 작성 시
+- 제목: `{type}: {한글 설명}` 형식
+- 본문에 `closes #이슈번호` 포함
+- base 브랜치는 `dev`
+
+### 리뷰 코멘트 작성 시
+- PN 태그 (P1~P5) 사용
+- 이유 명확히 설명
+
+### API 관련 코드 생성 시
+- HTTP status 기반 분기 (`response.ok`)
+- body 구조: `{ status, data, detail, code }` 가정
+- fetch 래퍼 함수 활용 패턴
+
+
+### 추천 패턴
+- ✅ TanStack Query로 API 호출 래핑
+- ✅ Zod로 응답 검증
+- ✅ Zustand로 전역 상태
+- ✅ Tailwind 클래스 사용 (CSS Module 지양)
+- ✅ Error Boundary / Suspense는 필요한 페이지만 선택 적용
+
+### 의심스러울 때
+- 기존 코드 패턴 확인
+- 팀 컨벤션 우선 (이 문서)
+- `CLAUDE.md` 참고 (동일 내용)
+- 판단 어려우면 사용자에게 확인 요청
diff --git a/CLAUDE.md b/CLAUDE.md
new file mode 100644
index 00000000..35aaf74a
--- /dev/null
+++ b/CLAUDE.md
@@ -0,0 +1,386 @@
+# CLAUDE.md
+
+> **디프만 18기 3팀 — 위시리스트 소비 결정 서비스**
+> 이 문서는 Claude Code가 프로젝트 작업 시 반드시 따라야 할 규칙 및 컨텍스트를 정의합니다.
+> 팀원 전원이 공유하는 AI 협업 규약이며, 모든 코드 생성/리팩토링은 이 규약을 따릅니다.
+
+---
+
+## 🎯 프로젝트 컨텍스트
+
+### 한 줄 정의
+**쌓인 위시리스트에서 먼저 살 것을 골라주는 소비 결정 서비스**
+
+### 타겟 유저
+위시리스트와 장바구니는 가득하지만, 선택 피로로 구매를 계속 미루는 패션·라이프스타일 중심의 **20~30대 모바일 쇼핑 사용자**.
+
+### 핵심 기능
+- **링크 기반 상품 저장** — 여러 쇼핑몰 링크를 한곳에 모음
+- **1:1 토너먼트 비교** — 두 개씩 비교해 최종 1순위 결정 (WOW 포인트)
+- **AI 소비 메이트** — 질문/공감/리마인드 (WOW 포인트)
+- **보류함 & 재판단 알림** — 방치된 위시 재방문 유도
+- **커머스 직접 연동** — 결정된 상품 즉시 구매
+
+### 플랫폼 전략
+**RN(Expo) 앱이 WebView로 Next.js 웹앱을 감싸는 구조.**
+→ 실제 UI/비즈니스 로직은 `apps/web`에 집중. 네이티브 기능만 `apps/app`에서 처리.
+
+---
+
+## 💻 기술 스택
+
+### 공통
+- **패키지 매니저**: pnpm 10.17.0
+- **모노레포**: Turborepo
+- **언어**: TypeScript 5.9.2
+- **배포**: Vercel (web), Expo (app)
+
+### apps/web (Next.js)
+- **프레임워크**: Next.js 16 (App Router)
+- **React**: 19.2.0
+- **상태관리**: Zustand
+- **스타일링**: Tailwind CSS v4 (루트 공통 설정, 각 앱에서 상속)
+- **API 통신**: TanStack Query (@tanstack/react-query)
+- **스키마 검증**: Zod
+- **API 모킹**: MSW (필요 시)
+- **아이콘**: Lucide React 우선 → 불가 시 SVG 컴포넌트화
+
+### apps/app (React Native)
+- **프레임워크**: React Native + Expo
+- **라우팅**: Expo Router
+- **주요 역할**: WebView로 `apps/web` 렌더링
+
+### CI/CD
+- **GitHub Actions**: PR 단위 빌드 검사 (`lint` → `check-types` → `build`)
+- **필수 통과 조건**: `pnpm install --frozen-lockfile`
+
+---
+
+## 📁 프로젝트 구조
+
+### 모노레포 루트
+```
+18th-team3-client/
+├── apps/
+│ ├── app/ # React Native + Expo (WebView 래퍼)
+│ └── web/ # Next.js 16 (메인 서비스)
+├── packages/
+│ ├── core/ # @repo/core — 웹뷰 통신용 type/hook/util
+│ ├── ui/ # @repo/ui — 공유 UI (현재 미사용)
+│ ├── eslint-config/ # @repo/eslint-config
+│ └── typescript-config/ # @repo/typescript-config
+├── prettier.config.mjs # 루트 Prettier (공통)
+├── .prettierignore
+└── turbo.json
+```
+
+### apps/web 내부 (고전 구조)
+```
+apps/web/src/
+├── app/ # Next.js App Router (layout, page, providers)
+│ ├── layout.tsx
+│ ├── page.tsx
+│ ├── providers.tsx # TanStack Query Provider
+│ └── fonts/
+├── components/ # 재사용 가능한 공통 UI 컴포넌트
+├── apis/ # API 호출 함수 (HTTP 메서드 prefix 컨벤션)
+├── hooks/ # 커스텀 훅
+├── utils/ # 공통 유틸리티 함수
+├── types/ # 공통 타입 정의 (T suffix)
+├── assets/ # 정적 리소스 (SVG, 이미지)
+├── styles/ # globals.css (Tailwind import)
+└── consts/ # 상수
+```
+
+### Path Alias
+`@/*` → `apps/web/src/*`
+
+---
+
+## 📝 네이밍 컨벤션
+
+| 대상 | 규칙 | 예시 |
+|---|---|---|
+| **컴포넌트 파일** | PascalCase | `ScaleResult.tsx` |
+| **일반 파일** (훅, 유틸) | camelCase | `useAuth.ts`, `formatDate.ts` |
+| **폴더** | kebab-case | `scale-result/` |
+| **타입** | T suffix | `UserT`, `ProductT` |
+| **API 함수** | HTTP 메서드 prefix | `getUser`, `postWishlist`, `patchProfile`, `deleteItem` |
+
+---
+
+## 🎨 코딩 컨벤션
+
+### 컴포넌트
+- **`function` 키워드 + default export**
+
+```tsx
+function MyComponent({ children }: MyComponentProps) {
+ return {children}
;
+}
+
+export default MyComponent;
+```
+
+### 유틸 함수
+- **화살표 함수** 사용
+
+```ts
+const formatDate = (date: Date) => date.toISOString();
+```
+
+### 타입 선언
+- **`type` 사용** (interface 대신)
+- **T suffix** (컨벤션상 타입 선언 시)
+- Props 타입명: `{ComponentName}Props`
+
+```ts
+type UserT = {
+ id: number;
+ name: string;
+};
+
+type MyComponentProps = {
+ children: React.ReactNode;
+};
+```
+
+### Props 네이밍
+- **내부 핸들러**: `handle-` (예: `handleClick`, `handleSubmit`)
+- **외부에서 받는 props**: `on-` (예: `onClick`, `onSubmit`)
+
+```tsx
+function Button({ onClick }: ButtonProps) {
+ const handleClick = () => {
+ // 내부 로직
+ onClick?.();
+ };
+ return ;
+}
+```
+
+### 기타
+- **세미콜론**: 사용 (`semi: true`)
+- **따옴표**: `singleQuote: true` (`'홑따옴표'`)
+- **printWidth**: 100
+- **trailingComma**: `'es5'`
+- **arrowParens**: `'avoid'` (인자 1개 시 괄호 생략)
+
+---
+
+## 📦 Import 규칙
+
+### 정렬 (자동화됨 — `@trivago/prettier-plugin-sort-imports`)
+```
+1. 외부 라이브러리 ()
+2. 절대경로 (^@/)
+3. 상대경로 (^[./])
+```
+
+### 예시
+```tsx
+import { useState } from 'react';
+import { useQuery } from '@tanstack/react-query';
+
+import { apiClient } from '@/apis/apiClient';
+import { UserT } from '@/types/user';
+
+import { formatDate } from './utils';
+import styles from './Page.module.css';
+```
+
+### Prettier 옵션
+- `importOrderSeparation: true` (그룹 간 빈 줄)
+- `importOrderSortSpecifiers: true` (그룹 내 알파벳 정렬)
+
+---
+
+## 🚨 ESLint 주요 규칙
+
+- `no-console`: warn/error만 허용 (`console.log` 금지)
+- `no-nested-ternary`: error (중첩 삼항 금지)
+- `@typescript-eslint/consistent-type-imports`: error (`import type` 강제)
+- `@typescript-eslint/no-explicit-any`: error (`any` 금지)
+- `unused-imports/no-unused-imports`: error
+- `_` prefix 변수/인자는 unused 허용
+
+---
+
+## 🔀 Git 전략
+
+### 브랜치 구조
+```
+main ← dev ← {type}/{issue-number}-{description}
+```
+
+### 브랜치 네이밍
+- **패턴**: `{type}/{issue-number}-{description}`
+- **예시**: `feat/1-login-page`, `chore/3-web-setup`, `fix/5-auth-bug`
+- **타입**: `feat`, `fix`, `chore`, `docs`, `refactor`, `style`, `test`
+
+### 커밋 메시지
+- **형식**: `{type}: {한글 설명}`
+- **예시**:
+ - `feat: 로그인 페이지 구현`
+ - `chore: Prettier 설정 추가`
+ - `fix: 토큰 만료 처리 수정`
+
+### 머지 방식
+- **Squash Merge** 사용
+- PR 제목이 그대로 dev의 커밋 메시지가 됨 → PR 제목 신중히 작성
+
+### PR 컨벤션
+- **base 브랜치**: `dev` (main 아님)
+- **템플릿**:
+```markdown
+## 작업 내용
+[내용 정리]
+
+## 스크린샷
+
+## 연관 이슈
+closes #이슈번호
+```
+
+### 코드 리뷰 — PN 룰
+- **P1** (Request changes): 꼭 반영 — 중대한 오류 가능성
+- **P2** (Request changes): 적극 고려 — 수용 or 토론
+- **P3** (Comment): 웬만하면 반영 — 미반영 시 사유 설명
+- **P4** (Approve): 반영해도/안해도 OK — 고민 정도
+- **P5** (Approve): 사소한 의견 — 무시 가능
+
+### 리뷰 규칙
+- **랜덤 1명 승인** 시 머지 가능
+- 리뷰 자동 배정 워크플로우 사용
+
+---
+
+## 🌐 API 통신 — Response Schema 규약
+
+### 기본 원칙
+1. **HTTP Status Code는 REST 의미대로 사용** (200, 201, 400, 401, 403, 404, 500)
+2. **성공/실패 Body 구조 통일**
+3. **`fetch`는 4xx/5xx에서 자동 throw 안 함** → 반드시 `response.ok` 확인
+4. **`success` 필드 사용 안 함** (`response.ok`와 중복)
+
+### 응답 구조
+```json
+{
+ "status": 200,
+ "data": {},
+ "detail": "요청이 정상적으로 처리되었습니다.",
+ "code": "COMMON_SUCCESS"
+}
+```
+
+| 필드 | 설명 |
+|---|---|
+| `status` | HTTP Status Code와 동일 |
+| `data` | 실제 비즈니스 응답 데이터 (실패 시 `null`) |
+| `detail` | 응답 메시지 (사용자 표시용) |
+| `code` | 서버 정의 Enum 코드 (세부 분기용) |
+
+### 검증 오류 응답 (400)
+```json
+{
+ "status": 400,
+ "data": null,
+ "detail": "입력값이 올바르지 않습니다.",
+ "code": "INVALID_INPUT",
+ "errors": [
+ { "field": "url", "reason": "URL 형식이 올바르지 않습니다." }
+ ]
+}
+```
+
+### 페이지 응답 구조
+```json
+{
+ "status": 200,
+ "data": [ { "wishId": 1, "title": "셔츠" } ],
+ "detail": "요청이 정상적으로 처리되었습니다.",
+ "code": "COMMON_SUCCESS",
+ "pageInfo": { "nextCursor": "abc123", "hasNext": true }
+}
+```
+
+### 프론트엔드 fetch 처리 표준
+```ts
+export async function request(url: string, options?: RequestInit) {
+ const response = await fetch(url, options);
+
+ let body;
+ try {
+ body = await response.json();
+ } catch {
+ throw new Error('서버 응답을 해석할 수 없습니다.');
+ }
+
+ if (response.ok) {
+ return body.data;
+ }
+
+ throw new Error(body.detail || '요청 처리 중 오류가 발생했습니다.');
+}
+```
+
+### 검증 오류 세부 처리
+```ts
+if (response.status === 400 && body.errors) {
+ return body.errors;
+}
+```
+
+### 분기 처리 (세부 에러)
+```ts
+if (body.code === 'WISH_NOT_FOUND') {
+ // 특정 에러 처리
+}
+```
+
+### HTTP Status 사용 기준
+| 상황 | HTTP Status |
+|---|---|
+| 조회 성공 | 200 OK |
+| 생성 성공 | 201 Created |
+| 잘못된 요청 | 400 Bad Request |
+| 인증 실패 | 401 Unauthorized |
+| 권한 없음 | 403 Forbidden |
+| 리소스 없음 | 404 Not Found |
+| 서버 오류 | 500 Internal Server Error |
+
+---
+
+## 🤖 Claude 작업 지침
+
+### 코드 생성 시
+- **위 컨벤션을 반드시 준수**
+- 신규 컴포넌트: `function` 키워드 + PascalCase 파일명 + default export
+- 신규 훅: 화살표 함수 + camelCase 파일명
+- 신규 타입: `type` 키워드 + T suffix
+- API 함수: HTTP 메서드 prefix (`getUser`, `postWishlist` 등)
+- 경로는 `@/*` 절대경로 우선, 같은 디렉토리는 상대경로
+
+### 커밋 메시지 제안 시
+- `{type}: {한글 설명}` 형식 사용
+- type: feat, fix, chore, docs, refactor, style, test
+
+### PR 작성 시
+- 제목: `{type}: {한글 설명}` 형식
+- 본문에 `closes #이슈번호` 포함
+- base 브랜치는 `dev`
+
+### 리뷰 코멘트 작성 시
+- PN 태그 (P1~P5) 사용
+- 이유 명확히 설명
+
+### API 관련 코드 생성 시
+- HTTP status 기반 분기 (`response.ok`)
+- body 구조: `{ status, data, detail, code }` 가정
+- fetch 래퍼 함수 활용 패턴
+
+
+### 의심스러울 때
+- 기존 코드 패턴 확인
+- 팀 컨벤션 우선 (이 문서)
+- 판단 어려우면 사용자에게 확인