/// 애플리케이션 전체 예외 클래스들 /// /// 각 레이어별로 명확한 예외 계층 구조를 제공합니다. /// 앱 예외 기본 클래스 abstract class AppException implements Exception { final String message; final String? code; final dynamic originalError; const AppException({required this.message, this.code, this.originalError}); @override String toString() => '$runtimeType: $message${code != null ? ' (코드: $code)' : ''}'; } /// 비즈니스 로직 예외 class BusinessException extends AppException { const BusinessException({ required String message, String? code, dynamic originalError, }) : super(message: message, code: code, originalError: originalError); } /// 검증 예외 class ValidationException extends AppException { final Map? fieldErrors; const ValidationException({ required String message, this.fieldErrors, String? code, }) : super(message: message, code: code); @override String toString() { final base = super.toString(); if (fieldErrors != null && fieldErrors!.isNotEmpty) { final errors = fieldErrors!.entries .map((e) => '${e.key}: ${e.value}') .join(', '); return '$base [필드 오류: $errors]'; } return base; } } /// 데이터 예외 class DataException extends AppException { const DataException({ required String message, String? code, dynamic originalError, }) : super(message: message, code: code, originalError: originalError); } /// 저장소 예외 class StorageException extends DataException { const StorageException({ required String message, String? code, dynamic originalError, }) : super(message: message, code: code, originalError: originalError); } /// 권한 예외 class PermissionException extends AppException { final String permission; const PermissionException({ required String message, required this.permission, String? code, }) : super(message: message, code: code); @override String toString() => '$runtimeType: $message (권한: $permission)'; } /// 위치 서비스 예외 class LocationException extends AppException { const LocationException({ required String message, String? code, dynamic originalError, }) : super(message: message, code: code, originalError: originalError); } /// 설정 예외 class ConfigurationException extends AppException { const ConfigurationException({required String message, String? code}) : super(message: message, code: code); } /// UI 예외 class UIException extends AppException { const UIException({ required String message, String? code, dynamic originalError, }) : super(message: message, code: code, originalError: originalError); } /// 리소스를 찾을 수 없음 예외 class NotFoundException extends AppException { final String resourceType; final dynamic resourceId; const NotFoundException({ required this.resourceType, required this.resourceId, String? message, }) : super( message: message ?? '$resourceType을(를) 찾을 수 없습니다 (ID: $resourceId)', code: 'NOT_FOUND', ); } /// 중복 리소스 예외 class DuplicateException extends AppException { final String resourceType; const DuplicateException({required this.resourceType, String? message}) : super(message: message ?? '이미 존재하는 $resourceType입니다', code: 'DUPLICATE'); } /// 추천 엔진 예외 class RecommendationException extends BusinessException { const RecommendationException({required String message, String? code}) : super(message: message, code: code); } /// 알림 예외 class NotificationException extends AppException { const NotificationException({ required String message, String? code, dynamic originalError, }) : super(message: message, code: code, originalError: originalError); }