SPRING

[Spring] MVC, MVP, MVVM의 차이는 무엇일까?

sagecode 2025. 6. 7. 22:58

Spring 프레임워크에서 주로 사용되는 MVC 구조는 익숙하지만, 프론트엔드나 모바일 개발 환경에서는 MVP, MVVM 구조도 자주 등장한다. 각 구조는 어떤 차이를 가지고 있고, 어떤 상황에서 각 구조를 사용하는걸까?

 

1. MVC (Model-View-Controller) 패턴

애플리케이션의 구성요소를 Model, View, Controller 3가지 역할로 구분하여 개발 프로세스에서 각각의 구성 요소에만 집중해서 개발할 수 있다.

 

구성 요소

(1) 모델(Model)

모델은 애플리케이션의 데이터인 데이터베이스, 상수, 변수 등을 뜻한다. 뷰에서 데이터를 생성하거나 수정하면 컨트롤러를 통해 모델을 생성하거나 갱신한다.

 

(2) 뷰(View)

뷰는 사용자에게 보여지는 인터페이스 요소, 화면을 뜻한다. 모델이 가지고있는 정보를 따로 저장하지 않아야 하며 단순히 유저가 이벤트를 생성했을 때 컨트롤러에 전달하는 역할을 한다.

 

(3) 컨트롤러(Controller)

컨트롤러는 하나 이상의 모델과 하나 이상의 뷰를 잇는 다리 역할을 한다. 모델이나 뷰의 변경 알림을 받게 되면 이를 해석하여 각각의 구성 요소에 해당 내용을 알려준다.

 

흐름 설명

예를 들어 사용자가 /user/1이라는 URL로 요청을 보냈다고 하자.

  1. Controller가 해당 요청을 받아 처리한다.
  2. 필요한 경우 Model에서 데이터를 조회하거나 로직을 처리한다.
  3. 결과를 가지고 View에 전달하여 사용자에게 응답한다.
@Controller
public class UserController {
    @GetMapping("/user/{id}")
    public String getUser(@PathVariable Long id, Model model) {
        User user = userService.findById(id);
        model.addAttribute("user", user);
        return "user/view"; // View 반환
    }
}

스프링의 MVC는 @PathVariable, @RequestParam 등의 어노테이션을 기반으로 사용자의 요청 값들을 쉽게 분석할 수 있고, 사용자의어떤 요청이 유효한 요청인지 구분도 가능하다.

장점

  • 역할이 분리되어 코드 구조가 깔끔하다.
  • Spring처럼 프레임워크에서 잘 지원한다.

단점

  • Controller와 View가 밀접하게 연결되어, 복잡한 UI일수록 Controller가 복잡해진다.
  • 하나의 View에서 여러 Model/Controller를 참조하게 될 경우, 의존성 관리가 어려워진다.

2. MVP (Model-View-Presenter) 패턴

MVP 패턴은 MVC 패턴으로부터 파생되었으며 MVC에서 C에 해당하는 컨트롤러가 프레젠터(Presenter)로 교체된 패턴이다.

 

Presenter의 역할

View와 Model 사이의 중재자. View의 동작을 직접 제어한다.

View 측에서는 인터페이스를 사이에 두어 Presenter는 오직 “View의 기능 이름”만 알고 있으면 된다.

흐름 설명

  1. View는 사용자 입력을 Presenter에게 위임한다.
  2. Presenter는 Model을 호출해 데이터를 처리하거나 가져온다.
  3. 결과를 View에 전달해 화면을 업데이트한다.
public interface LoginView {
    void showSuccess();
    void showError(String msg);
}
public class LoginPresenter {
    private final LoginService service;
    private final LoginView view;

    public LoginPresenter(LoginService service, LoginView view) {
        this.service = service;
        this.view = view;
    }

    public void login(String id, String pw) {
        if (service.login(id, pw)) {
            view.showSuccess();
        } else {
            view.showError("로그인 실패");
        }
    }
}
public class LoginViewImpl implements LoginView {
    @Override
    public void showSuccess() {
        System.out.println("로그인 성공!");
    }

    @Override
    public void showError(String msg) {
        System.out.println("에러: " + msg);
    }
}

 

장점

  • View와 비즈니스 로직(Presenter)이 완전히 분리되어 테스트 용이
  • View를 인터페이스로 만들어 모의 객체(Mock)로 테스트 가능

단점

  • View가 많아지면 인터페이스와 Presenter 클래스를 하나씩 1:1로 늘려야 해서 번거로움

3. MVVM (Model-View-ViewModel) 패턴

MVVM 패턴은 MVC의 C에 해당하는 컨트롤러가 뷰모델(ViewModel)로 바뀐 패턴이다.

 

ViewModel의 역할?

ViewModel은 View를 더 추상화한 계층이며, View와 ViewModel 사이의 양방향 데이터 바인딩을 지원하여 UI를 별도의 코드 없이 자동으로 갱신할 수 있도록 돕는다. View는 상태 변화에 대해 직접 처리하지 않고, ViewModel의 데이터를 구독함으로써 자동으로 반응할 수 있다.

 

흐름 설명

 

  1. 사용자가 View를 통해 액션 실행
  2. View가 ViewModel에 이벤트를 전달
  3. ViewModel은 Model에 필요한 로직 처리를 요청
  4. Model에서 처리된 결과를 ViewModel에 전달
  5. ViewModel의 상태가 바뀌면, View는 이를 자동으로 관찰하고 UI를 갱신

장점

  • View와 로직(ViewModel)이 완전히 분리되어 테스트가 쉬움
  • ViewModel은 프레임워크(UI)에 의존하지 않기 때문에 단위 테스트 가능
  • 상태 관리가 명확하고 바인딩을 통해 UI 갱신이 자동화 됨
  • 여러 View에서 동일한 ViewModel 사용 가능

단점

  • 데이터 바인딩 도구(예: LiveData, RxJS, Vue의 reactive 등)에 대한 학습 비용이 존재
  • 바인딩이 많아질수록 디버깅이 어려움
  • ViewModel이 너무 많은 상태를 관리하게 되면 비대해질 수 있다.