IT기술/플러터 (flutter)

Flutter 앱 아키텍처 완벽 가이드: MVC, MVVM, Clean Architecture 비교 분석

후스파 2025. 7. 5. 11:43
반응형

플러터 애플리케이션의 구조화를 위해 널리 사용되는 MVC, MVVM, Clean Architecture의 핵심 개념과 차이점, 실무 적용 방법에 대해 설명하겠습니다. 각 아키텍처의 장단점과 활용 시나리오를 통해 프로젝트에 맞는 최적의 설계 방식을 선택할 수 있습니다.


MVC (Model-View-Controller)

구조

Model데이터와 비즈니스 로직 관리
ViewUI 렌더링 및 사용자 인터랙션 수신
ControllerModel-View 간 데이터 흐름 제어

Flutter 구현 예시

// Model: 데이터 클래스  
class Product {  
  final String name;  
  final double price;  
  Product(this.name, this.price);  
}  

// View: UI 위젯  
class ProductView extends StatelessWidget {  
  final Product product;  
  ProductView(this.product);  

  @override  
  Widget build(BuildContext context) {  
    return Column(  
      children: [Text(product.name), Text('\$${product.price}')],  
    );  
  }  
}  

// Controller: 상태 관리 (Provider 예시)  
class ProductController extends ChangeNotifier {  
  Product _product = Product('Laptop', 1200);  
  void updatePrice(double newPrice) {  
    _product = Product(_product.name, newPrice);  
    notifyListeners();  
  }  
}  

장단점

  • 장점: 단순한 구조로 소규모 프로젝트 적합
  • 단점: 대규모 앱에서 Controller의 복잡도 증가 및 테스트 어려움

MVVM (Model-View-ViewModel)

구조

Model데이터 소스 및 순수 비즈니스 로직
ViewUI 표시 및 사용자 입력 전달
ViewModelModel 데이터를 View에 맞게 변환, 상태 관리

Flutter 구현 예시 (Riverpod 사용)

// ViewModel  
@riverpod  
class ProductViewModel extends _$ProductViewModel {  
  @override  
  Product build() => Product('Laptop', 1200);  

  void updatePrice(double newPrice) {  
    state = Product(state.name, newPrice);  
  }  
}  

// View  
class ProductView extends ConsumerWidget {  
  @override  
  Widget build(BuildContext context, WidgetRef ref) {  
    final product = ref.watch(productViewModelProvider);  
    return Column(  
      children: [  
        Text(product.name),  
        Text('\$${product.price}'),  
        ElevatedButton(  
          onPressed: () => ref.read(productViewModelProvider.notifier).updatePrice(1000),  
          child: Text('할인 적용'),  
        ),  
      ],  
    );  
  }  
}  

장단점

  • 장점: View-ViewModel 분리로 테스트 용이성 향상
  • 단점: 복잡한 데이터 바인딩 구현 필요

Clean Architecture

계층 구조

PresentationUI 및 상태 관리 (MVVM/BLoC 적용)
Domain엔티티, 유스케이스, 인터페이스 정의
Data데이터 소스 구현 (API, 로컬 DB)

프로젝트 구조 예시

lib/  
├── core/  
├── features/  
│   └── product/  
│       ├── data/  
│       │   ├── models/  
│       │   └── repositories/  
│       ├── domain/  
│       │   ├── entities/  
│       │   └── usecases/  
│       └── presentation/  
│           ├── providers/  
│           └── screens/  
└── main.dart  

장단점

  • 장점: 계층 간 의존성 역전으로 유지보수성 극대화
  • 단점: 초기 설정 복잡도가 높아 소규모 프로젝트 비효율적

아키텍처 비교 및 선택 가이드

적합 규모소규모중규모대규모
학습 곡선낮음중간높음
테스트 용이성제한적우수최상
유연성낮음중간높음
도구ProviderRiverpod, BLoCDDD + 상태 관리

실무 적용 전략

MVP/MVVM + Clean Architecture 조합

  • Presentation 계층: MVVM 패턴 적용 (ViewModel ↔ View)
  • Domain 계층: UseCase로 비즈니스 로직 캡슐화
  • Data 계층: Repository 패턴으로 데이터 소스 추상화
// Domain Layer  
abstract class ProductRepository {  
  Future getProductById(int id);  
}  

// Data Layer  
class ProductRepositoryImpl implements ProductRepository {  
  final ProductRemoteDataSource remoteSource;  
  @override  
  Future getProductById(int id) async { ... }  
}  

// Presentation Layer (MVVM)  
class ProductViewModel {  
  final ProductRepository repository;  
  ProductViewModel(this.repository);  

  Future loadProduct(int id) async { ... }  
}  

상태 관리 도구 선택

  • Riverpod: MVVM 구현에 적합한 선언적 DI
  • BLoC: 복잡한 비즈니스 로직 처리에 강점
  • GetX: 빠른 프로토타이핑에 최적화

마무리

프로젝트 요구사항에 맞는 아키텍처 선택

  • 소규모 앱: MVC 또는 MVVM 단독 사용
  • 중규모 앱: MVVM + Clean Architecture 경량화 버전
  • 대규모 엔터프라이즈 앱: Clean Architecture + DDD 철저 적용

각 아키텍처는 고유한 장단점을 가지고 있으며, 프로젝트의 규모와 복잡도, 팀의 경험 수준에 따라 적절한 선택이 필요합니다. 초기에는 단순한 구조로 시작하여 필요에 따라 점진적으로 복잡한 아키텍처로 발전시키는 것이 효과적인 전략입니다.
 
 

반응형