# CLAUDE.md

프로젝트별 가이드. 일반 규칙은 `~/.claude/CLAUDE.md` 참조.

## Project Overview

**SubManager** - 구독 관리 앱 (Flutter 3.x)

| 항목 | 기술 |
|------|------|
| DB | Hive (로컬 전용) |
| 상태관리 | Provider + ChangeNotifier |
| 디자인 | Material 3 |
| 광고 | google_mobile_ads |

**버전**: 1.0.1+3

## Quick Commands

```bash
# Hive 모델 생성
dart run build_runner build --delete-conflicting-outputs

# 빌드
flutter build apk --release           # APK
flutter build appbundle --release     # AAB (Play Store)

# 버전업 후 디바이스 설치
flutter install --release
```

## Architecture

```text
lib/
├── controllers/     # 비즈니스 로직 (3개)
│   ├── add_subscription_controller.dart
│   ├── detail_screen_controller.dart
│   └── sms_scan_controller.dart
├── models/          # Hive 모델 (@HiveType)
│   ├── subscription_model.dart    (typeId: 0)
│   ├── category_model.dart        (typeId: 1)
│   └── payment_card_model.dart    (typeId: 2)
├── providers/       # ChangeNotifier 상태관리
├── screens/         # 화면 위젯
├── services/        # 외부 서비스 연동
├── widgets/         # 재사용 컴포넌트
├── utils/           # 유틸리티 헬퍼
├── routes/          # 라우팅 정의
├── theme/           # 테마/색상
└── l10n/            # 다국어 (ko/en/ja/zh)
```

## Key Services

| Service | 역할 |
|---------|------|
| `AdService` | 전면 광고 (Completer 패턴) |
| `SmsScanner` | SMS 파싱 → 구독 자동 감지 (Isolate 사용) |
| `NotificationService` | 로컬 알림 |
| `ExchangeRateService` | 환율 조회 |
| `url_matcher/` | 서비스명 → URL 매칭 |

## Routes

| Path | Screen |
|------|--------|
| `/` | MainScreen |
| `/add-subscription` | AddSubscriptionScreen |
| `/subscription-detail` | DetailScreen (requires SubscriptionModel) |
| `/sms-scanner` | SmsScanScreen |
| `/analysis` | AnalysisScreen |
| `/settings` | SettingsScreen |
| `/payment-card-management` | PaymentCardManagementScreen |

## Project Rules

1. **로컬 전용**: 서버/Firebase/외부 DB 금지
2. **권한 거부 시**: 수동 입력 폴백 (SMS), 기능 비활성화 (알림)
3. **외부 API**: Clearbit Logo API만 허용
4. **Isolate 주의**: `compute()` 내부에서 Flutter 바인딩/Context 접근 불가

## Known Patterns

### 전면 광고 (AdService)

```dart
// Completer 패턴으로 광고 완료 대기
final completer = Completer<bool>();
ad.fullScreenContentCallback = FullScreenContentCallback(
  onAdDismissedFullScreenContent: (ad) {
    completer.complete(true);
  },
);
ad.show();
return completer.future;
```

### SMS 스캔 (Isolate)

```dart
// Isolate 내부에서는 하드코딩 사용
// Flutter 바인딩, Context, Provider 접근 불가
return 'Unknown service';  // AppLocalizations 사용 불가
```

## Response Format

```text
[모델명]. I have reviewed all the following rules: [규칙]. Proceeding with the task. Master!
```
