본문 바로가기
Front-End/디자인 패턴

MVVM 패턴의 이해 - MVC, MVP 패턴과의 비교

by jakejeong 2025. 2. 12.

안녕하세요. 지난 시간 MVC를 기반으로 다양한 MV* 파생 모델들이 등장했고 첫 번째 형태인 MVP 모델을 살펴보았습니다.

오늘은 프론트엔드 아키텍처의 대표적인 디자인 패턴인 MVVM에 대해 알아보고, MVC, MVP 패턴과의 차이점을 살펴보겠습니다.

 

MVC에서 MVVM까지의 진화

MVC(Model-View-Controller) 패턴은 많은 개발자들이 애용하는 전통적인 디자인 패턴입니다. 하지만 MVC 패턴에서는 View와 Model이 서로 강한 의존성을 가지는 문제가 있었습니다. 이러한 문제를 해결하기 위해 MVP(Model-View-Presenter)와 MVVM(Model-View-ViewModel) 패턴이 등장하게 되었습니다.

MVVM 패턴의 구조와 동작 방식

MVVM 패턴은 다음과 같은 세 가지 주요 컴포넌트로 구성됩니다:

  1. Model: 데이터와 비즈니스 로직을 담당
  2. View: 사용자 인터페이스를 표현
  3. ViewModel: View와 Model 사이의 중재자 역할

다음은 간단한 MVVM 패턴 구현 예제입니다:

// Model
class UserModel {
    constructor(name, email) {
        this.name = name;
        this.email = email;
    }
}

// ViewModel
class UserViewModel {
    constructor() {
        this.model = new UserModel('', '');
        this.observers = [];
    }

    bindView(callback) {
        this.observers.push(callback);
    }

    notifyObservers() {
        this.observers.forEach(callback => callback(this.model));
    }

    updateUser(name, email) {
        this.model.name = name;
        this.model.email = email;
        this.notifyObservers();
    }
}

// View
class UserView {
    constructor(viewModel) {
        this.viewModel = viewModel;
        this.viewModel.bindView(this.render.bind(this));

        // DOM 요소 설정
        this.nameInput = document.getElementById('nameInput');
        this.emailInput = document.getElementById('emailInput');
        this.updateButton = document.getElementById('updateButton');

        this.setupEventListeners();
    }

    setupEventListeners() {
        this.updateButton.addEventListener('click', () => {
            this.viewModel.updateUser(
                this.nameInput.value,
                this.emailInput.value
            );
        });
    }

    render(model) {
        this.nameInput.value = model.name;
        this.emailInput.value = model.email;
    }
}

MVP vs MVVM: 주요 차이점

MVP (Model-View-Presenter)

  • Presenter가 View와 Model 사이의 중재자 역할을 합니다
  • View의 업데이트를 수동으로 처리해야 합니다
  • View와 Presenter가 1:1 관계를 가집니다

예제 코드로 보는 MVP 패턴:

// MVP 예제
class UserPresenter {
    constructor(view, model) {
        this.view = view;
        this.model = model;
    }

    updateUser(name, email) {
        this.model.name = name;
        this.model.email = email;
        // 수동으로 View 업데이트
        this.view.render(this.model);
    }
}

MVVM (Model-View-ViewModel)

  • ViewModel이 View와 Model 사이의 중재자 역할을 합니다
  • 데이터 바인딩을 통한 자동 View 업데이트가 가능합니다
  • View와 ViewModel이 1:n 관계를 가질 수 있습니다

각 패턴의 특징 비교

MVC의 한계

  • Controller가 View와 Model 모두에 의존적입니다
  • View와 Model이 직접 연결되어 있어 유지보수가 어렵습니다
  • 애플리케이션이 커질수록 Controller가 비대해지는 문제가 있습니다

MVP의 개선점

  • View와 Model를 완전히 분리하여 의존성을 제거했습니다.
  • 의존성이 제거되어 단위 테스트가 용이해졌습니다
  • Presenter가 변경 사항이 발생할 때마다 수동으로 View를 업데이트 해야 합니다.

MVVM의 장점

  • 데이터 바인딩을 통한 자동 View 업데이트로 코드가 간결해졌습니다
  • View와 ViewModel의 느슨한 결합으로 재사용성이 향상되었습니다
  • 복잡한 상태 관리가 용이해졌습니다

결론

MVVM 패턴은 MVC의 한계를 극복하고 MVP의 장점을 계승하면서, 데이터 바인딩이라는 강력한 기능을 더했습니다. 특히 최신 프론트엔드 프레임워크들은 MVVM 패턴을 표방하며 높은 점유율을 얻고 있습니다.

 

프레임워크를 사용하지 않더라도 컴포넌트를 설계하거나 부분적인 개발 과정에서 아키텍쳐 관점의 디자인 패턴은 굉장히 많이 활용됩니다.

이 글이 디자인 패턴에 관심있는 분들에게 많은 도움이 되기를 기원합니다.

반응형