개발일기
🏗️ Flutter 앱 구조 설계: MVVM 패턴과 Clean Architecture 적용하기
뱅우
2025. 6. 11. 13:38
반응형
Flutter로 프로젝트 규모가 커질수록 상태 관리만큼 중요한 것이 바로 앱 구조 설계입니다.
안드로이드 개발자에게 익숙한 MVVM 패턴과 클린 아키텍처를 Flutter에 적용해보면 어떤 모습일까요?
실무 프로젝트에 바로 도입 가능한 구조를 소개합니다.
📌 1. 왜 MVVM 또는 Clean Architecture가 필요할까?
- 프로젝트가 커질수록 UI 코드와 비즈니스 로직이 섞임
- 테스트하기 어렵고, 유지보수 불가능
- 팀 협업 시 역할 분리가 명확하지 않음
→ 이를 해결하려면 UI(View), 상태(ViewModel), 도메인(UseCase), 데이터(DataSource/Repository)를 분리하는 구조가 필요합니다.
🧱 2. 구조 구성도
lib/
┣ features/
┃ ┗ user/
┃ ┣ data/
┃ ┃ ┗ user_api.dart
┃ ┣ domain/
┃ ┃ ┣ user_model.dart
┃ ┃ ┗ user_repository.dart
┃ ┣ application/
┃ ┃ ┗ get_user_usecase.dart
┃ ┣ presentation/
┃ ┃ ┣ user_viewmodel.dart
┃ ┃ ┗ user_screen.dart
👀 3. 각 레이어 설명
레이어 | 역할 | 예시 |
---|---|---|
View | UI 구현, ViewModel 호출 | user_screen.dart |
ViewModel | UI 상태 관리, 유즈케이스 호출 | user_viewmodel.dart |
UseCase | 도메인 비즈니스 로직 담당 | get_user_usecase.dart |
Repository | 외부 API, DB 통합 추상화 | user_repository.dart |
DataSource | 실제 API, 로컬 DB 연동 | user_api.dart |
🧑💻 4. 코드 예시
📄 user_viewmodel.dart
class UserViewModel extends ChangeNotifier {
final GetUserUseCase useCase;
UserViewModel(this.useCase);
UserModel? user;
Future loadUser() async {
user = await useCase.execute();
notifyListeners();
}
}
📄 get_user_usecase.dart
class GetUserUseCase {
final UserRepository repo;
GetUserUseCase(this.repo);
Future execute() {
return repo.fetchUser();
}
}
📄 user_repository.dart
abstract class UserRepository {
Future<UserModel> fetchUser();
}
📄 user_api.dart
class UserApi implements UserRepository {
final Dio dio;
UserApi(this.dio);
@override
Future<UserModel> fetchUser() async {
final res = await dio.get('/user');
return UserModel.fromJson(res.data);
}
}
⚙️ 5. 의존성 주입(DI)은 어떻게?
- Provider, Riverpod, GetIt 등 사용 가능
- 간단한 예:
ChangeNotifierProvider(create: ...)
📣 6. 실무 도입 팁
- 프로젝트 초반부터 구조 설계에 시간 투자
- 기능 단위 모듈화로 협업 분업 구조 만들기
- Repository 인터페이스 → 테스트 쉽게 만듦
📌 정리
- MVVM은 Flutter에서도 충분히 유효한 구조
- 클린 아키텍처 방식으로 기능별 책임을 나누면 유지보수 용이
- UseCase → ViewModel 분리 구조로 비즈니스 로직 정리
반응형