Files
superport/lib/services/health_check_service.dart
JiWoong Sul 162fe08618
Some checks failed
Flutter Test & Quality Check / Test on macos-latest (push) Has been cancelled
Flutter Test & Quality Check / Test on ubuntu-latest (push) Has been cancelled
Flutter Test & Quality Check / Build APK (push) Has been cancelled
refactor: Clean Architecture 적용 및 코드베이스 전면 리팩토링
## 주요 변경사항

### 아키텍처 개선
- Clean Architecture 패턴 적용 (Domain, Data, Presentation 레이어 분리)
- Use Case 패턴 도입으로 비즈니스 로직 캡슐화
- Repository 패턴으로 데이터 접근 추상화
- 의존성 주입 구조 개선

### 상태 관리 최적화
- 모든 Controller에서 불필요한 상태 관리 로직 제거
- 페이지네이션 로직 통일 및 간소화
- 에러 처리 로직 개선 (에러 메시지 한글화)
- 로딩 상태 관리 최적화

### Mock 서비스 제거
- MockDataService 완전 제거
- 모든 화면을 실제 API 전용으로 전환
- 불필요한 Mock 관련 코드 정리

### UI/UX 개선
- Overview 화면 대시보드 기능 강화
- 라이선스 만료 알림 위젯 추가
- 사이드바 네비게이션 개선
- 일관된 UI 컴포넌트 사용

### 코드 품질
- 중복 코드 제거 및 함수 추출
- 파일별 책임 분리 명확화
- 테스트 코드 업데이트

## 영향 범위
- 모든 화면의 Controller 리팩토링
- API 통신 레이어 구조 개선
- 에러 처리 및 로깅 시스템 개선

## 향후 계획
- 단위 테스트 커버리지 확대
- 통합 테스트 시나리오 추가
- 성능 모니터링 도구 통합
2025-08-11 00:04:28 +09:00

167 lines
4.9 KiB
Dart

import 'dart:async';
import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';
import '../core/config/environment.dart';
import '../core/constants/app_constants.dart';
import '../data/datasources/remote/api_client.dart';
// 조건부 import - 웹 플랫폼에서만 dart:js 사용
import 'health_check_service_stub.dart'
if (dart.library.js) 'health_check_service_web.dart' as platform;
/// API 헬스체크 테스트를 위한 서비스
class HealthCheckService {
final ApiClient _apiClient;
Timer? _healthCheckTimer;
bool _isMonitoring = false;
HealthCheckService({ApiClient? apiClient})
: _apiClient = apiClient ?? ApiClient();
/// 헬스체크 API 호출
Future<Map<String, dynamic>> checkHealth() async {
try {
debugPrint('=== 헬스체크 시작 ===');
debugPrint('API Base URL: ${Environment.apiBaseUrl}');
debugPrint('Full URL: ${Environment.apiBaseUrl}/health');
final response = await _apiClient.get('/health');
debugPrint('응답 상태 코드: ${response.statusCode}');
debugPrint('응답 데이터: ${response.data}');
return {
'success': true,
'data': response.data,
'statusCode': response.statusCode,
};
} on DioException catch (e) {
debugPrint('=== DioException 발생 ===');
debugPrint('에러 타입: ${e.type}');
debugPrint('에러 메시지: ${e.message}');
debugPrint('에러 응답: ${e.response?.data}');
debugPrint('에러 상태 코드: ${e.response?.statusCode}');
// CORS 에러인지 확인
if (e.type == DioExceptionType.connectionError ||
e.type == DioExceptionType.unknown) {
debugPrint('⚠️ CORS 또는 네트워크 연결 문제일 가능성이 있습니다.');
}
return {
'success': false,
'error': e.message ?? '알 수 없는 에러',
'errorType': e.type.toString(),
'statusCode': e.response?.statusCode,
'responseData': e.response?.data,
};
} catch (e) {
debugPrint('=== 일반 에러 발생 ===');
debugPrint('에러: $e');
return {
'success': false,
'error': e.toString(),
};
}
}
/// 직접 Dio로 테스트 (인터셉터 없이)
Future<Map<String, dynamic>> checkHealthDirect() async {
try {
debugPrint('=== 직접 Dio 헬스체크 시작 ===');
final dio = Dio(BaseOptions(
baseUrl: Environment.apiBaseUrl,
connectTimeout: AppConstants.healthCheckTimeout,
receiveTimeout: AppConstants.healthCheckTimeout,
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
},
));
// 로깅 인터셉터만 추가
dio.interceptors.add(LogInterceptor(
requestBody: true,
responseBody: true,
requestHeader: true,
responseHeader: true,
error: true,
));
final response = await dio.get('/health');
return {
'success': true,
'data': response.data,
'statusCode': response.statusCode,
};
} catch (e) {
debugPrint('직접 Dio 에러: $e');
return {
'success': false,
'error': e.toString(),
};
}
}
/// 주기적인 헬스체크 시작 (30초마다)
void startPeriodicHealthCheck() {
if (_isMonitoring) return;
debugPrint('=== 주기적 헬스체크 모니터링 시작 ===');
_isMonitoring = true;
// 즉시 한 번 체크
_performHealthCheck();
// 30초마다 체크
_healthCheckTimer = Timer.periodic(AppConstants.healthCheckInterval, (_) {
_performHealthCheck();
});
}
/// 주기적인 헬스체크 중지
void stopPeriodicHealthCheck() {
debugPrint('=== 주기적 헬스체크 모니터링 중지 ===');
_isMonitoring = false;
_healthCheckTimer?.cancel();
_healthCheckTimer = null;
}
/// 헬스체크 수행 및 알림 표시
Future<void> _performHealthCheck() async {
final result = await checkHealth();
if (!result['success'] || result['data']?['status'] != 'healthy') {
_showBrowserNotification(result);
}
}
/// 브라우저 알림 표시
void _showBrowserNotification(Map<String, dynamic> result) {
if (!kIsWeb) return;
try {
final status = result['data']?['status'] ?? 'unreachable';
final message = result['error'] ?? 'Server status: $status';
debugPrint('=== 브라우저 알림 표시 ===');
debugPrint('상태: $status');
debugPrint('메시지: $message');
// 플랫폼별 알림 처리
platform.showNotification(
'Server Health Check Alert',
message,
status,
);
} catch (e) {
debugPrint('브라우저 알림 표시 실패: $e');
}
}
/// 모니터링 상태 확인
bool get isMonitoring => _isMonitoring;
}