1 minute read

MVP 패턴이란?


MVP(Model-View-Presenter)는 소프트웨어 디자인 패턴으로, MVC(Model-View-Controller) 패턴의 변형입니다.
View와 Presenter 사이의 의존성을 줄이고 역할을 더 명확히 하여, 특히 UI가 많은 애플리케이션에서 적합한 패턴입니다.

MVP-Process

구성요소


  • Model
    • 애플리케이션의 데이터와 로직을 담당.
    • 데이터를 가져오거나 업데이트하는 역할을 합니다.
    • Presenter와만 통신하며, View와 직접적으로 연결되지 않습니다.
  • View
    • 사용자 인터페이스를 담당하며, Presenter와의 소통을 위한 역할만 수행.
    • 사용자가 데이터를 입력하거나 UI를 확인하는 부분입니다.
    • 로직은 포함되지 않고, Presenter에서 전달받은 데이터를 기반으로 UI를 업데이트합니다.
  • Presenter
    • View와 Model을 중재하며, 비즈니스 로직을 처리합니다.
    • View에서 사용자 입력을 받고, Model을 통해 데이터를 처리한 뒤 결과를 다시 View에 전달합니다.
    • View와 Model 간의 강한 의존성을 제거합니다.



MVP의 동작 흐름


  1. 사용자가 View를 통해 입력을 제공.
  2. View는 Presenter에게 입력을 전달.
  3. Presenter는 Model에 데이터를 요청하거나 수정.
  4. Model의 데이터를 Presenter가 다시 View에 전달.
  5. View는 Presenter로부터 받은 데이터를 화면에 표시.


장단점


장점

  • 테스트 용이성
    • Presenter는 View에 의존하지 않고 인터페이스를 통해 작동하므로, 단위 테스트가 쉽습니다.
  • 독립적인 View
    • View는 Presenter와만 연결되어 있어, View를 교체하거나 수정할 때 영향을 최소화합니다.
  • 역할 분리
    • UI(View)와 로직(Presenter)이 분리되어, 유지보수성과 코드 재사용성이 높아집니다.

단점

  • 복잡성 증가
    • Presenter와 View 간의 연결을 위해 인터페이스를 정의해야 하므로, 코드 구조가 복잡해질 수 있습니다.
  • 작은 프로젝트에는 과도
    • 간단한 애플리케이션에서는 오히려 불필요하게 코드가 늘어날 수 있습니다.



MVP와 MVC의 차이점


  • View와의 의존성
    • MVC에서는 View와 Controller 간에 의존성이 있지만, MVP에서는 View가 Presenter와만 통신하며 인터페이스를 통해 연결됩니다.
  • 테스트 용이성
    • MVP는 View가 인터페이스를 사용하기 때문에 Mocking이 쉬워 테스트하기 용이합니다.
  • 데이터 흐름
    • MVC는 Controller가 사용자 입력을 받아 Model을 직접 갱신하고, View가 데이터를 구독하는 방식.
    • MVP는 Presenter가 모든 흐름(입력, 로직 처리, UI 업데이트)을 제어합니다.


샘플 코드


Model

using System;

public class UserModel
{
    private readonly string validUsername = "user";
    private readonly string validPassword = "password";

    public bool ValidateUser(string username, string password)
    {
        return username == validUsername && password == validPassword;
    }
}



View

using System;

public interface ILoginView
{
    string Username { get; }
    string Password { get; }
    void DisplayMessage(string message);
}

public class LoginView : ILoginView
{
    public string Username { get; private set; }
    public string Password { get; private set; }

    public void GetUserInput()
    {
        Console.Write("Enter Username: ");
        Username = Console.ReadLine();

        Console.Write("Enter Password: ");
        Password = Console.ReadLine();
    }

    public void DisplayMessage(string message)
    {
        Console.WriteLine(message);
    }
}



Presenter

public class LoginPresenter
{
    private readonly ILoginView _view;
    private readonly UserModel _model;

    public LoginPresenter(ILoginView view, UserModel model)
    {
        _view = view;
        _model = model;
    }

    public void HandleLogin()
    {
        string username = _view.Username;
        string password = _view.Password;

        if (_model.ValidateUser(username, password))
        {
            _view.DisplayMessage("Login Successful!");
        }
        else
        {
            _view.DisplayMessage("Invalid Username or Password.");
        }
    }
}



Top