본문 바로가기
Swift/디자인패턴

[Architecture] MVC vs MVVM Key Differences with examples 정리

by 마라민초닭발로제 2024. 12. 5.

https://shakuro.com/blog/mvc-vs-mvvm

 

Exploring MVC vs MVVM: Choosing the Right Architecture | Shakuro

Dive into the differences between MVC and MVVM architectures. Learn how to choose the best one for your project. Check out the article to learn more.

shakuro.com

 

 

테스트 관점에서의 MVC vs MVVM

MVC

  • 테스트 범위 제한: Model은 독립적으로 테스트할 수 있지만 Controller와 View의 테스트가 복잡.
  • 유닛 테스트 부족: Controller에서 비즈니스 로직을 다룰 경우 테스트 커버리지가 떨어질 가능성 존재 .

MVVM

  • 테스트 효율성: ViewModel이 View와 독립적이기 때문에 UI 없이도 유닛 테스트 가능.
  • 자동화 가능성: 이벤트 기반 코드가 많아 Mock을 활용한 테스트 작성이 용이.

MVC와 MVVM의 차이점

  1. 책임 분리 (Separation of Concerns)
    • MVC:
      Controller가 사용자 입력 처리 및 View와 Model 사이의 연결 역할을 담당합니다. 하지만 View와 Controller의 결합도가 높아지기 쉬움으로, 복잡한 UI를 처리할 때 코드가 비대해질 가능성이 큽니다.
    • MVVM:
      ViewModel이 도입되어, View와 Model 간의 데이터 변환 및 로직 처리를 맡습니다. View는 단순히 데이터와 상호작용하는 레이어로 역할이 축소되며, View와 ViewModel 간의 결합도가 낮아져 재사용성과 테스트가 용이합니다.
  2. 데이터 흐름 (Data Flow)
    • MVC:
      사용자 액션이 Controller → Model → View 순으로 흐릅니다. 데이터 업데이트는 Controller를 통해서만 이뤄지며, 이벤트에 따른 수동적인 View 업데이트가 필요합니다.
    • MVVM:
      양방향 데이터 바인딩을 지원하므로, View와 ViewModel이 상호 연결되어 데이터 변경이 실시간으로 반영됩니다. ViewModel이 View에 필요한 데이터만 노출하기 때문에 더욱 직관적입니다.
  3. 테스트 가능성 (Testability)
    • MVC:
      Model은 테스트하기 쉽지만, Controller와 View의 의존성이 높아 별도의 Mocking이 필요하고, 테스트 작성이 까다로울 수 있습니다.
    • MVVM:
      ViewModel은 UI와 분리된 로직만 포함하므로 View를 제외한 테스트가 용이합니다. ViewModel을 독립적으로 테스트할 수 있어 TDD(Test Driven Development)에 적합합니다.

Binding 관점에서의 차이점 및 iOS에서의 적용

Binding의 개념

  • MVC:
    iOS에서 MVC는 데이터 바인딩을 지원하지 않습니다. 따라서 데이터 업데이트 시 직접 View의 상태를 갱신하는 코드가 필요하며, 데이터 흐름을 명시적으로 관리해야 합니다. 예를 들어, NotificationCenter나 Delegate 패턴을 사용하여 데이터 변경을 View에 전달합니다.
  • MVVM:
    MVVM은 데이터 바인딩을 기본으로 하며, iOS에서는 Combine, RxSwift, 또는 SwiftUI의 @State, @Binding을 활용해 이를 구현합니다. 이 방식은 데이터 흐름을 간결하게 하고, 상태 변화를 자동으로 UI에 반영할 수 있게 합니다.
  1. iOS에서의 구현 방식
    • MVC:
      • Delegate나 NotificationCenter를 사용해 Model-View 간 데이터를 전달.
      • 데이터가 변경되면 Controller에서 View를 갱신하는 작업이 필요.
// MVC 예시
class ViewController: UIViewController {
    var model: UserModel?

    override func viewDidLoad() {
        super.viewDidLoad()
        NotificationCenter.default.addObserver(self, selector: #selector(updateView), name: .dataUpdated, object: nil)
    }

    @objc func updateView() {
        // 데이터 변경 시 View 갱신
    }
}

 

 

MVVM:

  • SwiftUI와 @State, @Binding, 또는 Combine의 Published와 같은 바인딩 메커니즘 활용.
  • 상태 변화가 View에 즉각 반영되며, ViewModel이 데이터 로직을 캡슐화함.
// MVVM 예시
class UserViewModel: ObservableObject {
    @Published var userName: String = "User"
}

struct ContentView: View {
    @StateObject var viewModel = UserViewModel()

    var body: some View {
        Text(viewModel.userName) // ViewModel의 상태가 자동으로 바인딩되어 반영
    }
}

 

효율성 차이

  • MVC: 데이터 흐름을 명시적으로 제어하기 때문에 간단한 프로젝트에서는 적합하지만, 복잡한 UI에서는 코드가 길어지고 관리가 어려워질 수 있습니다.
  • MVVM: 데이터 바인딩을 통해 UI와 로직이 분리되므로 코드의 재사용성과 유지보수가 용이합니다. 하지만 초기 설정과 학습 곡선이 있을 수 있습니다. 그러나 ViewModel을 적절하게 불리하지 못한다면 MVC와 마찬가지로 관리가 어려워질 수 있습니다.

 

결론

  • MVC는 단순하고 작은 프로젝트에서 빠른 개발과 유지보수에 적합.
  • MVVM은 대규모 프로젝트와 복잡한 UI 요구사항에서 더 나은 조직화와 테스트 환경을 제공.

 

개인적인 생각

MVC아키텍쳐는 MVVM보다 나쁜 아키텍쳐가 아닙니다. 시중에 있는 많은 프로젝트와 과거 어플리케이션들이 MVC로 만들어졌습니다. MVC가 갖는 치명적인 단점은 관심사의 분리입니다. ViewController가 비대해지는 문제는 VIewController를 쪼개면 된다고 생각합니다. 객체지향적으로 SRP를 적용해서 사용하는 Actor가 누군지 확인하고 관심사 분리를 한다면 충분히 관리 가능한 코드를 작성할 수 있습니다. 

 

또한 MVVM은 만능이 아닙니다. MVVM을 사용하게 되면, 사용하는 Binding Library에 의존적입니다. 이를 위해서 선행 공부가 필요하고 Custom으로 만들었을 때 러닝 커브 때문에 온보딩 기간이 길어질 수 있습니다. 또한 상기에 적었듯이 적절한 관심사 분리가 진행되지 않는다면 MVC가 갖고있는 치명적인 단점인 테스팅 부분에서도 MVC와 비슷한 문제가 발생합니다.

 

MVC나 MVVM이나 자신의 프로젝트에 맞는 것을 고르면 좋다고 생각합니다. 일정이 급박하다면 가장 자신있는 아키텍쳐로 진행해도 좋고, 활용하는 Application을 중점으로 아키텍쳐를 설정하면 좋을 것 같습니다.