# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Development Commands

The main application is located in the `front/` directory. All commands should be run from this directory:

```bash
cd front
```

### Core Commands
- `npm run dev` - Start development server
- `npm run build` - Production build with TypeScript compilation (`prod.yml`)
- `npm run build:dev` - Vite-only build (`stg.yml` · `dev.yml`)
- `npm run guard` - Menu exposure key guard (`scripts/exposure-guard.test.mjs`, also runs in CI)
- `npm run lint` - Run ESLint with TypeScript support
- `npm run preview` - Preview production build
- `npm run generate` - Generate GraphQL types

## Project Architecture

This is a React TypeScript application following Feature-Sliced Design (FSD) architecture patterns with Zustand for state management.

### Directory Structure

- **`src/api/`** - API layer with service modules for external communication
- **`src/entities/`** - Domain entities with global state management (Zustand stores)
- **`src/features/`** - Business features with hooks and UI components
- **`src/layouts/`** - Application layouts (BasicLayout, AuthLayout, AlimTalkLayout)
- **`src/pages/`** - Route pages organized by domain
- **`src/shared/`** - Shared utilities, components, and helpers
- **`src/widget/`** - Reusable composite components

### State Management

The application uses Zustand for state management with domain-specific stores in `entities/*/model/store.ts`:
- Global app state (`_global`)
- User authentication (`user`)
- Analysis data (`analysis`)
- Payment subscriptions (`subscribe`)
- Board/notifications (`board`, `alarm`)
- And other domain-specific stores

### Key Technologies

- **React 18** with TypeScript
- **Vite** for bundling and development
- **React Router v6** for navigation
- **Zustand** for state management
- **React Hook Form** for form handling
- **PDF generation** with pdf-lib and pdfmake
- **Payment integration** with TossPayments
- **Chart visualization** with Nivo

### Code Conventions

From the README.md:
- Folder names: lowerCamelCase
- Components: UpperCamelCase  
- Page components: suffix with "Page" (e.g., `LoginPage.tsx`)

### Branch and Commit Conventions

**Commit format**: `{type}: description`

Types: feat, fix, docs, refactor, test, perf, style, build, ci, WIP, chore

**Branch prefixes**: feature/, enhancement/, refactor/, chore/, update/, bugfix/, hotfix/, release/, test/, docs/, experiment/

## 메뉴 노출 키

- 새 라우트는 `src/shared/exposure/exposure.registry.json` 에 전체 경로로 적는다. 메뉴로 여닫을 기능이면 `routes`(노출 키), 아니면 `ungated`(사유).
- `keys` 는 서버 `release.registry.ts` 의 사본이다. 새 키는 서버에 먼저 넣고 키 이름 · `kind` · `name` · `owner` · `removeBy` 를 글자까지 같게 옮긴다. 공개 전 기능은 `kind: "launch"` 다.
- 상시 키(`permanent`) 집합은 `front/scripts/exposure-guard.test.mjs` 의 동결 목록과 같아야 한다. 서버 등록부와의 대조는 G8 이 옆 저장소 `../insuniverse-server` 를 읽어 한다 — 사이트만 받은 CI 에서는 건너뛰므로 로컬에서 돈다.
- 메뉴 · 카드 · 하위 메뉴 · 마이페이지 항목은 `useExposure().showPath(링크)` 로 거른다(외부 링크는 `isOn(키)`). 꺼진 주소는 `App.tsx` 가 없는 주소와 같은 빈 화면으로 보낸다.
- `npm run guard` 가 빠뜨림을 붉힌다(배포 CI 의 「메뉴 노출 키 누락 검사」 · PR 의 「PR 노출 검사」).
- 기본값은 「지금 운영에 보이는 화면만 노출」 이다. stg 에만 있는 새 화면 · 경로는 출시 키로 건다 — 상시 키에 걸린 경로와 `ungated` 경로는 운영에 이미 있는 것뿐이다(`npm run guard` G7 의 `PROD_LEVEL_ROUTES` · `PROD_LEVEL_UNGATED`, 예외는 서버가 출시 키로 닫는 고객 링크 `SERVER_CLOSED_UNGATED`).
- 서버 API 가 없는 새 화면의 출시 키는 서버 등록부에 `noRoute`(사유)를 달아 만든다 — 서버 접근 계약 R7 「고아 키」 면제. 빈 사유는 붉다. `noRoute` 는 서버에만 두고 이 등록부로 옮기지 않는다.

### 메뉴 노출 — 필수 검증

노출 키 · 라우트 · 메뉴 · 카드 · 하위 메뉴 · 마이페이지 항목을 건드린 커밋은 올리기 전에 로컬에서 녹색을 본다. GitHub 필수 검사로 걸지 않는다(2026-11-10 결정). 정본은 로컬 검증이고 `pr-check.yml` 은 같은 명령을 PR 에서 한 번 더 도는 보조다.

```bash
(cd front && npm run guard)                                              # = node --test scripts/exposure-guard.test.mjs, G8 서버 키 대조 포함
(cd front && npx vitest run --minWorkers=1 --maxWorkers=2 src/shared/exposure)  # 출시 키 기본 숨김 · 상시 키 기본 보임
bash ../.claude/meta/2026-11-09-release-control/verify-local.sh          # 부모 release-control 체크아웃에만 있다: 세 저장소 한 번에
```

| 바꾼 것 | 붉으면 고칠 곳 |
|---|---|
| 새 라우트 · 메뉴 | `exposure.registry.json` 의 `routes`(노출 키) 또는 `ungated`(사유). stg 에만 있는 화면은 출시 키. `ungated` 를 늘리면 G7 동결 목록도 같은 PR 에서 |
| 새 회원 · 공개 API 호출 | 서버 접근 계약 등록표 `release` 칸(`../insuniverse-server/CLAUDE.md` 「노출 키」) |
| 키 추가 · 이름 변경 | 서버 `release.registry.ts` 와 이 등록부 둘 다(G8) + 상시 키면 G1 · G7 동결 목록 |

## Important Notes

- This is an insurance analysis platform ("보험유니버스") with user subscription management
- The app includes mobile bridge functionality for native app integration
- Multi-environment support (development, staging, production)
- Korean language support with moment.js localization
- PDF generation capabilities for analysis reports
- Payment processing integration
- Educational content with video streaming capabilities

## Common Issues and Solutions

### Modal Navigation Issues
- **Problem**: `/main` redirect when navigating from modals
- **Cause**: Modal callbacks executing after navigation, AuthGuard re-evaluation
- **Solution**: Always close modal before navigation with proper delay
- **Files**: `src/features/subscribe/hooks/useCheckSubscription.ts`, `src/features/products/hooks/useProducts.tsx`

### Advertisement Loading Race Conditions
- **Problem**: Advertisement logic executing before API data is fetched
- **Cause**: useEffect running on initial render with undefined data
- **Solution**: Always check `isAdFetched` before processing advertisement logic
- **Pattern**: Combine related useEffects to avoid duplicate logic
- **Files**: `src/features/analyze/ui/AnalyzeAd.tsx`, `src/features/alimtalk/ui/AlimtalkAd.tsx`

### Code Review Checklist
When reviewing code changes, always check for:
1. **useEffect dependencies**: Ensure all necessary dependencies are included
2. **Race conditions**: Check for async operations that might complete out of order
3. **Modal management**: Verify modals are closed before navigation
4. **Duplicate logic**: Look for opportunities to combine related useEffects
5. **Loading states**: Ensure data fetching completion is properly checked

## Development Environment Setup

1. Navigate to `front/` directory
2. Install dependencies: `npm install`
3. Set up environment variables based on the mode (development/staging/production)
4. Run development server: `npm run dev`