

- MVP 는 Model, View, Presenter의 약자입니다.
- MVP 방식은 MVC 방식의 아래 글과 같은 단점을 보완하여 개발 된 디자인 패턴입니다.
MVC 패턴의 단점
- View와 Controller 간 강한 결합
- Controller의 역할 모호성
- 테스트 어려움
- 구조적 혼란
- 사용자 입력 처리 분산
MVP 패턴의 MVC 패턴 단점 보완 내용
- Presenter를 통해 단방향 의존성으로 연결
- Presenter가 모든 로직을 담당하며 역할을 명확히 분리
- Presenter와 View를 인터페이스로 분리해 테스트 가능성 향상
- View, Model, Presenter의 역할을 엄격히 분리
- Presenter로 모든 입력 처리 로직을 집중
- 데이터와 로직 처리
- 데이터의 상태를 저장하고 변경하며, 데이터베이스나 네트워크와의 상호작용 수행
- Model은 Presenter에 데이터를 전달하거나 데이터를 받아 수정
public class PlayerModel
{
public string Name { get; private set; }
public int Score { get; private set; }
// Presenter로 변경 사항을 알리는 콜백
public event System.Action<int> OnScoreUpdated;
public PlayerModel(string name)
{
Name = name;
Score = 0;
}
public void AddScore(int points)
{
Score += points;
// 점수가 변경되었음을 알림
OnScoreUpdated?.Invoke(Score);
}
}
- 사용자와 상호작용 하는 화면 (UI)
- 사용자 입력을 Presenter에 전달
- Presenter에서 전달받은 데이터를 화면에 표시
public class PlayerView : MonoBehaviour
{
public Text playerNameText;
public Text playerScoreText;
public Button scoreButton;
private PlayerPresenter presenter;
public void SetPresenter(PlayerPresenter presenter)
{
this.presenter = presenter;
}
public void DisplayPlayerInfo(string name, int score)
{
playerNameText.text = $"Name: {name}";
playerScoreText.text = $"Score: {score}";
}
private void Start()
{
scoreButton.onClick.AddListener(() => presenter.OnScoreButtonClicked());
}
}
- Model과 View 간의 중간 역할
- View에서 입력받은 요청을 처리하고 Model을 업데이트하거나 데이터를 요청
- Model에서 받은 데이터를 가공하여 View에 전달
- View와 1:1로 연결되며 View에 대한 참조를 가지고 있음
public class PlayerPresenter
{
private PlayerModel model;
private PlayerView view;
public PlayerPresenter(PlayerModel model, PlayerView view)
{
this.model = model;
this.view = view;
// Model의 상태 변경을 감지하기 위한 콜백 등록
model.OnScoreUpdated += UpdateScore;
view.SetPresenter(this);
UpdateView();
}
public void OnScoreButtonClicked()
{
model.AddScore(10);
}
private void UpdateView()
{
view.DisplayPlayerInfo(model.Name, model.Score);
}
private void UpdateScore(int newScore)
{
view.DisplayPlayerInfo(model.Name, newScore);
}
}
- View에서 사용자 입력 이벤트
- View는 해당 이벤트를 Presenter에 전달
- Presenter는 Model을 업데이트하거나 Model에 데이터 요청
- Model에서 데이터를 처리한 후 결과를 Presenter로 반환
- Presenter는 데이터를 가공하여 View에 전달
- View가 받은 데이터를 화면에 표시
- scoreButton.onClick.AddListener : 1번
- AddListener(() => presenter.OnScoreButtonClicked()) : 2번
- model.AddScore(10) : 3번
- OnScoreUpdated?.Invoke(Score) : 4번
- view.DisplayPlayerInfo(model.Name, newScore) : 5번
- playerScoreText.text = $"Score: {score}" : 6번
- 역할 분리로 인한 유지보수성 향상
- View, Model, Presenter의 역할이 명확히 분리되므로 코드 관리가 용이합니다
- 변경 사항이 생겨도 각 요소는 독립적이기 때문에 수정 범위가 좁아집니다
- 테스트 가능성 증가
- Presenter는 View와 Model에 강하게 결합되지 않고, 인터페이스를 통해 간접적으로 소통하므로 테스트가 용이합니다.
- 결과적으로 단위 테스트와 통합 테스트가 더 쉽고 빠르게 작성 가능합니다.
- UI 논리와 비즈니스 로직의 분리
- 비즈니스 로직(Model과 Presenter에 위치)은 UI(View)와 독립적으로 동작하므로, UI를 변경하거나 교체하더라도 핵심 로직을 그대로 재사용할 수 있습니다
- 유연성과 확장성
- MVP는 프로젝트가 커지고 복잡해져도 구조를 유지하기 쉽습니다
- UI와 로직이 독립적이므로 다른 플랫폼으로의 확장이 쉬워집니다
- 재사용성 증가
- Presenter와 Model은 View에 의존하지 않으므로 다른 프로젝트나 모듈에서 재사용하기 쉽습니다
- 병렬 작업 가능
- View와 Presenter가 독립적이기 때문에 개발팀이 병렬로 작업하기 적합합니다
- 코드 중복 방지
- Presenter를 통해 UI 로직과 비즈니스 로직이 관리되므로, 여러 View에서 동일한 로직을 반복 구현할 필요가 없습니다
- 단방향 데이터 흐름
- View와 Presenter 간의 단방향 데이터 흐름으로 인해 의존성이 낮아지고 코드의 구조가 명확해집니다
- 둘의 Model은 용도는 별 차이가 없습니다.
- 하지만 View - Controller, View - Presenter의 데이터 흐름이 다릅니다.
// View (MVC)
public void OnScoreButtonClicked(System.Action onButtonClick)
{
// Controller에서 이벤트를 등록
scoreButton.onClick.AddListener(() => onButtonClick?.Invoke());
}
// View (MVP)
private void Start()
{
// View가 Presenter에만 이벤트를 전달
scoreButton.onClick.AddListener(() => presenter.OnScoreButtonClicked());
}
--------------------------------------------------------------------------------------------------
// Controller (MVC)
public PlayerController(PlayerModel model, PlayerView view)
{
this.model = model;
this.view = view;
// View가 Controller와 직접 연결
view.OnScoreButtonClicked(OnScoreButtonClicked);
// 초기 데이터 표시
view.SetPlayerInfo(model.Name, model.Score);
}
// Presenter (MVP)
public PlayerPresenter(PlayerModel model, PlayerView view)
{
this.model = model;
this.view = view;
// View가 Presenter를 참조하도록 설정
view.SetPresenter(this);
UpdateView(); // Presenter가 초기 View 업데이트
}
public void OnScoreButtonClicked()
{
model.AddScore(10);
UpdateView(); // Presenter가 View를 간접적으로 업데이트
}
- MVC는 View가 Controller와 양방향 연결입니다. (View -> Conroller, Controller -> View)
- View ↔ Controller ↔ Model
- MVP는 View가 Presenter에 단방향 연결합니다.
- View → Presenter → Model

MVP의 작동 흐름에서 설명한 것처럼 작동 흐름이 똑같이 흘러갑니다.
MVC 패턴과 MVP 패턴의 방식이 비슷하다고 느껴져 혼란이 왔습니다. 그래서 찾아보면서 양방향과 단방향의 차이를 알고 나서부터는 눈에 슬 보이기 시작하였지만 추후에 사용할 때에는 잘 사용해야 MVP 패턴을 다른 사람이 알아볼 듯 합니다.. 그래도 지식이 늘어났다고 생각이 듭니다..