2022.12.04 네이버 블로그에 업로드했던 글을 이전한 게시글입니다.

 

 

 

 

Unity로 MVC, MV(R)P, MVVM패턴을 구현해보려고한다.

MVC, MVP, MVVM에대한 설명은 많았지만 유니티로 구현한 설명은 적은것같아 공부겸 정리해보려고한다.

 

 

간단하게

체력 100인 캐릭터가 존재하며

Attack을 누르면 체력이 10씩 깎이며

Heal을 누르면 5씩 늘어나는 기능을 만들어보려고 한다.

 


[VIEW와 MODEL]

각 패턴의 공통인 View와 Model부터 작성한다

●Model

사용되는 데이터의 모임이다.

데이터와 데이터를 처리하는 부분을 Model 이라고 한다.

 

우선 HP가 필요하므로 Model에 HP를 작성한다.

public class Model
{
    private int _hp;
    public int HP { get=>_hp; set=>_hp = value; }
}

 

 

●VIEW

사용자에게 보여지는 UI부분이다.

현재 상태로는 버튼과 HP를 표현하는 텍스트가 있다.

변하는값은 HP를 표현하는 텍스트이므로 텍스트만 우선 작성한다

 

using UnityEngine;
using UnityEngine.UI;

public class View : MonoBehaviour
{
    [SerializeField]
    private Text _hpTxt;
}

 

 

 

 


[ MVC 패턴 ]

MVC패턴은 Model, View, Controller이다.

Model과 View가 연결되어있고, Controller에서 입력을 담당한다.

현재의 기능으로 설명하면,

  1. 버튼을 누르는 Action이 Controller로 들어온다.
  2. Controller에서 Model에게 HP값 변경을 요청한다.
  3. Model에서는 HP를 변경하고 이 값을 View에서 표시한다

●Controller

 

 

Controller에서는 버튼이 눌렸는지 확인만 담당한다.

 

 

using UnityEngine;
using UnityEngine.UI;

public class Controller : MonoBehaviour
{
    [SerializeField]
    private Button _attactButton;
    [SerializeField]
    private Button _healButton;

    [SerializeField]
    private Model _model;
    
    private void Start()
    {
        //Attack버튼이 눌리면 Model의 Attack을 호출한다
        _attactButton.onClick.AddListener(() =>
        {
            _model.Attack();
        });

        //Heal버튼이 눌리면 Model의 Heal을 호출한다
        _healButton.onClick.AddListener(() =>
        {
            _model.Heal();
        });
    }
}

 

 

●View

 

 

View에서는 받은 값을 사용자가 보는 화면에 표시만 한다.

 

using UnityEngine;
using UnityEngine.UI;

public class View : MonoBehaviour
{
    [SerializeField]
    private Text _hpTxt;

    public void ShowHPTxt(int hpValue)
    {
        _hpTxt.text = hpValue.ToString();
    }
}

 

●Model

Model에서 실제 데이터 처리와 View와의 연동을 담당한다.

using UnityEngine;

public class Model : MonoBehaviour
{
    private int _hp = 100;

    [SerializeField]
    private View _view;

    /// <summary>
    /// Attack버튼이 눌렸을 때
    /// hp - 10
    /// View에 표시요청
    /// </summary>
    public void Attack()
    {
        _hp -= 10;
        _view.ShowHPTxt(_hp);
    }

    /// <summary>
    /// Heal버튼이 눌렸을 때
    /// hp + 5
    /// View에 표시요청
    /// </summary>
    public void Heal()
    {
        _hp += 5;
        _view.ShowHPTxt(_hp);
    }
}

 


 

[ MVP 패턴 ]

MVP(MV(R)P)패턴은 Model, View, Presenter이다.

Model에서 데이터, View에서 화면을 담당하고 중간에 중개자 역할을 하는 Presenter가 존재한다.

 

 

 

현재의 기능으로 설명하면,

  1. 버튼을 누르는 Action이 View로 들어온다.
  2. View에서 Presenter에게 HP값 변경을 요청한다.
  3. Presenter는 Model에게 정보를 요청하고 받아온 정보를 View로 재송신한다

●View

이제 View에서 버튼 액션을 확인한다.

 

 

 

View의 버튼이 눌리면 Presenter에 값 변경을 요청한다.

 

using UnityEngine;
using UnityEngine.UI;

public class View : MonoBehaviour
{
    [SerializeField]
    private Text _hpTxt;
    [SerializeField]
    private Button _attactButton;
    [SerializeField]
    private Button _healButton;
    [SerializeField]
    private Presenter _presenter;
    private void Start()
    {
        //Attack버튼이 눌리면 Model의 Attack을 호출한다
        _attactButton.onClick.AddListener(() =>
        {
            _presenter.Attack();
        });

        //Heal버튼이 눌리면 Model의 Heal을 호출한다
        _healButton.onClick.AddListener(() =>
        {
            _presenter.Heal();
        });
    }

    public void ShowHPTxt(int hpValue)
    {
        _hpTxt.text = hpValue.ToString();
    }
}

 

●Presenter

 

Presenter에서는 Model의 값을 가지고있고,

View에서 요청한 값을 Model에서 받아와

다시 View 표시한다.

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Presenter : MonoBehaviour
{
    private Model _model = new Model();
    [SerializeField]
    private View _view;

    public void Attack()
    {
        _view.ShowHPTxt(_model.Attack());
    }

    public void Heal()
    {
        _view.ShowHPTxt(_model.Heal());
    }
}

 

 

●Model

 

Model은 데이터 처리만을 담당한다.

public class Model
{
    private int _hp = 100;

    /// <summary>
    /// Attack버튼이 눌렸을 때
    /// hp - 10
    /// View에 표시요청
    /// </summary>
    public int Attack()
    {
        return _hp -= 10;
    }

    /// <summary>
    /// Heal버튼이 눌렸을 때
    /// hp + 5
    /// View에 표시요청
    /// </summary>
    public int Heal()
    {
        return _hp += 5;
    }
}

 

MVP방식의 장점은 View와 Model의 의존성이 줄어든 것이지만

반대로 View와 Presenter와의 의존성이 높다.

 

 

 


 

[ MVVM 패턴 ]

MVVM패턴은 Model, View, View Model이다.

Model에서 데이터, View에서 화면을 담당하고

Model의 데이터를 View에 맞게 파싱해주는 ViewModel이 존재한다.

 

View에 맞게 파싱해주는 역할이므로 View의 갯수만큼 ViewModel이 늘어난다.

 

 

현재의 기능으로 설명하면,

  1. 값을 받아오는 것 까지는 MVP패턴과 비슷하다.
  2. Presenter의 중재자역할 대신 ViewModel에서는 Model에서 받아온 값을 View에 맞게 파싱한다.

●ViewModel

 

이번엔 ViewModel에서 View용 데이터를 가지고있고,

Model에서 받아온 데이터를 View용으로 파싱한 후 이 값을 View에서 표시한다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ViewModel : MonoBehaviour
{
    [SerializeField]
    private View _view;
    [SerializeField]
    private Model _model;

    private string _hpStr = string.Empty;
    public void Attack()
    {
        _hpStr = _model.Attack().ToString();
        _view.ShowHPTxt(_hpStr);
    }

    public void Heal()
    {
        _hpStr = _model.Heal().ToString();
        _view.ShowHPTxt(_hpStr);
    }
}

 

●Model

 

using UnityEngine;

public class Model : MonoBehaviour
{
    private int _hp = 100;

    /// <summary>
    /// Attack버튼이 눌렸을 때
    /// hp - 10
    /// View에 표시요청
    /// </summary>
    public int Attack()
    {
        return _hp -= 10;
    }

    /// <summary>
    /// Heal버튼이 눌렸을 때
    /// hp + 5
    /// View에 표시요청
    /// </summary>
    public int Heal()
    {
        return _hp += 5;
    }
}

 

●View

 

 

using UnityEngine;
using UnityEngine.UI;

public class View : MonoBehaviour
{
    [SerializeField]
    private Text _hpTxt;
    [SerializeField]
    private Button _attactButton;
    [SerializeField]
    private Button _healButton;
    private ViewModel _viewModel = new();
    private void Start()
    {
        //Attack버튼이 눌리면 Model의 Attack을 호출한다
        _attactButton.onClick.AddListener(() =>
        {
            _viewModel.Attack();
        });

        //Heal버튼이 눌리면 Model의 Heal을 호출한다
        _healButton.onClick.AddListener(() =>
        {
            _viewModel.Heal();
        });
    }

    public void ShowHPTxt(string hpValue)
    {
        _hpTxt.text = hpValue;
    }
}

 

 

Unity에서는 MVVM패턴이 잘맞지않는다는 의견이 있었다.

웹에 잘 맞는 패턴

디자인패턴은 개인의 자유이며 프로젝트의 요구사항에 따라 편한 패턴을 선택해서 사용하는것이 좋을 것 같다

+ Recent posts