refactor: Clean Architecture 적용 및 코드베이스 전면 리팩토링
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

## 주요 변경사항

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

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

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

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

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

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

## 향후 계획
- 단위 테스트 커버리지 확대
- 통합 테스트 시나리오 추가
- 성능 모니터링 도구 통합
This commit is contained in:
JiWoong Sul
2025-08-11 00:04:28 +09:00
parent 6b5d126990
commit 162fe08618
113 changed files with 11072 additions and 3319 deletions

View File

@@ -3,21 +3,21 @@ import 'package:flutter/material.dart';
import 'package:get_it/get_it.dart';
import 'package:superport/models/company_model.dart';
import 'package:superport/models/user_model.dart';
import 'package:superport/services/mock_data_service.dart';
import 'package:superport/services/user_service.dart';
import 'package:superport/services/company_service.dart';
import 'package:superport/utils/constants.dart';
import 'package:superport/models/user_phone_field.dart';
// 사용자 폼의 상태 및 비즈니스 로직을 담당하는 컨트롤러
class UserFormController extends ChangeNotifier {
final MockDataService dataService;
final UserService _userService = GetIt.instance<UserService>();
final CompanyService _companyService = GetIt.instance<CompanyService>();
final GlobalKey<FormState> formKey = GlobalKey<FormState>();
// 상태 변수
bool _isLoading = false;
String? _error;
bool _useApi = true; // Feature flag
// API만 사용
// 폼 필드
bool isEditMode = false;
@@ -50,7 +50,7 @@ class UserFormController extends ChangeNotifier {
bool get isCheckingUsername => _isCheckingUsername;
bool? get isUsernameAvailable => _isUsernameAvailable;
UserFormController({required this.dataService, this.userId}) {
UserFormController({this.userId}) {
isEditMode = userId != null;
if (isEditMode) {
loadUser();
@@ -61,15 +61,29 @@ class UserFormController extends ChangeNotifier {
}
// 회사 목록 로드
void loadCompanies() {
companies = dataService.getAllCompanies();
notifyListeners();
Future<void> loadCompanies() async {
try {
final result = await _companyService.getCompanies();
companies = result;
notifyListeners();
} catch (e) {
debugPrint('회사 목록 로드 실패: $e');
companies = [];
notifyListeners();
}
}
// 회사 ID에 따라 지점 목록 로드
void loadBranches(int companyId) {
final company = dataService.getCompanyById(companyId);
branches = company?.branches ?? [];
final company = companies.firstWhere(
(c) => c.id == companyId,
orElse: () => Company(
id: companyId,
name: '알 수 없는 회사',
branches: [],
),
);
branches = company.branches ?? [];
// 지점 변경 시 이전 선택 지점이 새 회사에 없으면 초기화
if (branchId != null && !branches.any((b) => b.id == branchId)) {
branchId = null;
@@ -86,13 +100,7 @@ class UserFormController extends ChangeNotifier {
notifyListeners();
try {
User? user;
if (_useApi) {
user = await _userService.getUser(userId!);
} else {
user = dataService.getUserById(userId!);
}
final user = await _userService.getUser(userId!);
if (user != null) {
name = user.name;
@@ -155,15 +163,8 @@ class UserFormController extends ChangeNotifier {
notifyListeners();
try {
if (_useApi) {
final isDuplicate = await _userService.checkDuplicateUsername(value);
_isUsernameAvailable = !isDuplicate;
} else {
// Mock 데이터에서 중복 확인
final users = dataService.getAllUsers();
final exists = users.any((u) => u.username == value && u.id != userId);
_isUsernameAvailable = !exists;
}
final isDuplicate = await _userService.checkDuplicateUsername(value);
_isUsernameAvailable = !isDuplicate;
_lastCheckedUsername = value;
} catch (e) {
_isUsernameAvailable = null;
@@ -217,81 +218,32 @@ class UserFormController extends ChangeNotifier {
}
}
if (_useApi) {
if (isEditMode && userId != null) {
// 사용자 수정
await _userService.updateUser(
userId!,
name: name,
email: email.isNotEmpty ? email : null,
phone: phoneNumber,
companyId: companyId,
branchId: branchId,
role: role,
position: position.isNotEmpty ? position : null,
password: password.isNotEmpty ? password : null,
);
} else {
// 사용자 생성
await _userService.createUser(
username: username,
email: email,
password: password,
name: name,
role: role,
companyId: companyId!,
branchId: branchId,
phone: phoneNumber,
position: position.isNotEmpty ? position : null,
);
}
if (isEditMode && userId != null) {
// 사용자 수정
await _userService.updateUser(
userId!,
name: name,
email: email.isNotEmpty ? email : null,
phone: phoneNumber,
companyId: companyId,
branchId: branchId,
role: role,
position: position.isNotEmpty ? position : null,
password: password.isNotEmpty ? password : null,
);
} else {
// Mock 데이터 사용
List<Map<String, String>> phoneNumbersList = [];
for (var phoneField in phoneFields) {
if (phoneField.number.isNotEmpty) {
phoneNumbersList.add({
'type': phoneField.type,
'number': phoneField.number,
});
}
}
if (isEditMode && userId != null) {
final user = dataService.getUserById(userId!);
if (user != null) {
final updatedUser = User(
id: user.id,
companyId: companyId!,
branchId: branchId,
name: name,
role: role,
position: position.isNotEmpty ? position : null,
email: email.isNotEmpty ? email : null,
phoneNumbers: phoneNumbersList,
username: username.isNotEmpty ? username : null,
isActive: user.isActive,
createdAt: user.createdAt,
updatedAt: DateTime.now(),
);
dataService.updateUser(updatedUser);
}
} else {
final newUser = User(
companyId: companyId!,
branchId: branchId,
name: name,
role: role,
position: position.isNotEmpty ? position : null,
email: email.isNotEmpty ? email : null,
phoneNumbers: phoneNumbersList,
username: username,
isActive: true,
createdAt: DateTime.now(),
updatedAt: DateTime.now(),
);
dataService.addUser(newUser);
}
// 사용자 생성
await _userService.createUser(
username: username,
email: email,
password: password,
name: name,
role: role,
companyId: companyId!,
branchId: branchId,
phone: phoneNumber,
position: position.isNotEmpty ? position : null,
);
}
onResult(null);
@@ -314,9 +266,6 @@ class UserFormController extends ChangeNotifier {
super.dispose();
}
// API/Mock 모드 전환
void toggleApiMode() {
_useApi = !_useApi;
notifyListeners();
}
// API 모드만 사용 (Mock 데이터 제거됨)
// void toggleApiMode() 메서드 제거
}