본문 바로가기
개발/게임 디자인 패턴

게임 디자인 패턴 17. MVC 패턴 (MVC Pattern)

by 석시 2023. 11. 20.



프로젝트를 하다보면 데이터 (Model) 가 따로 있고, 그 데이터를 조작하는 부분 (Controller) 이 따로 있고, 그것을 보여주는 부분 (View) 이 따로 있게 되는 경우가 많을 것이다.

이 세가지 사이의 관계를 정의하기가 힘들텐데, 이 때 주로 사용하는 마법 같은 방법 중 하나가 바로 이 MVC 패턴 (MVC, Model-View-Controller Pattern) 이 아닌가 싶다.

디자인 패턴 중에서는 가장 직관적인 패턴 중 하나라고 생각한다.

백문이 불여일견, 직접 MVC 패턴으로 된 예제를 보자.


MVC 패턴으로 인벤토리 만들기

먼저, Model이 되는 데이터를 만들어 보는 것이다.

using System.Collections.Generic;

[System.Serializable]
public class Inventory
{
    public List<Slot> Slots;
    
    public Inventory(int numSlots)
    {
        Slots = new List<Slot>();
        
        for (int i = 0; i < numSlots; ++i)
        {
            Slot slot = new Slot();
            Slots.Add(slot);
        }
    }
   // ...
}

Slot은 아이템 하나를 넣기 위한 슬롯이라고 생각하면 좋다.

Inventory 데이터 자체에 변화를 줄 수 있는 로직들은 전부 Inventory 클래스 안에다가 메서드로 작성해주고, 이것을 Controller에서 호출해주기만 하면 모델에 대한 부분은 끝.

이 때 줄 수 있는 팁 중 하나는, 보통 Model이 되는 데이터는 Monobehaviour를 상속 받지 않고, 이러한 Model을 다루는 Controller Monobehaviour를 상속 받게 만든다.

Controller는 다음과 같이 만들 수 있다.

public class InventoryController : MonoBehaviour
{
    public Inventory Inventory;
    
    private void Awake()
    {
        Inventory = new Inventory(40);
    }
    
    // 그 외 Inventory를 다루는 로직들
}

이러면 사용자로부터 조작을 입력 받는다거나, 외부 환경으로부터 영향을 받아 모델에 영향을 주는 것을 컨트롤러가 전부 담당하게 되는 것이다.

View 역시 다음과 같이 쓸 수 있다.

public class InventoryUI : MonoBehaviour
{
    private Inventory _inventory;
    
    public void Init(Inventory inventory, bool setActive = false)
    {
        _inventory = inventory;
        gameObject.SetActive(setActive);
    }

    // ...
}

이 때 Controller가 참조하고 있는 InventoryView가 참조하고 있는 Inventory가 동일해야 한다는 점에 주의하자.

구조가 다음과 같이 되는 것이다.

한 줄 요약하자면 Model이 되는 데이터는 유저로부터 한 번 가려져 있고, View가 Model의 출력, Controller가 Model의 입력을 담당하게 되는 것이다.

사실 이는 MVC 패턴의 규칙에 위배된 구조인데, 이에 대해서는 뒤 파트에서 다루겠다.


MVC 패턴의 규칙

  1. Model의 경우는

사용자가 편집하길 원하는 모든 데이터를 가지고 있어야 하며, View나 Controller에 대해 전혀 몰라야 한다.

유니티에서는 때문에 보통 Monobehaviour 없이 Model을 구현하는 편이다.

또한 Model은 변경이 일어나게 되면, 변경 통지에 대한 처리 방법을 구현해야하는데 이는 보통 event로 구현이 된다.

이렇게 구현하면 View는 자연스레 관찰자 패턴이 되는 것이다.

게임 디자인 패턴 3. 관찰자 패턴 (Observer Pattern)
기본적인 형태의 관찰자 패턴관찰자 패턴의 구현구현 1) event를 이용한 구현구현 2) 인터페이스를 이용한 구현관찰자 패턴의 주의점?사라진 리스너 문제 (Lapsed Listener Problem) 이번엔 관찰자 패턴이다. 사실 C#을 공부한 입장에서, 관찰자 패턴의 내용을 가만히 듣다보면 어딘가 모르게 익숙할 것이다. 상당히 자주 나오는 패턴이고 그 효과 역시 강력하기에 관찰자 패턴의 경우에는 라이브러리나 키워드를 통해 기본적으로 지원하는 경우가 많다. C#에서는 event 키워드가 바로 그것이다. event에 대해 처음 들었다면 아래 글에 간단하게 event에 대해 적혀 있으니 가볍게 읽어보자.[내일배움단] 사전캠프 C# TIL 8. 알아두면 좋을 것들Generic참고) object 타입Generi..
https://seoksii.tistory.com/70

  1. View의 경우는

Model이 가지고 있는 정보를 따로 저장해서는 안된다.

Model에 변경이 있다면 변경 통지를 받아 그것을 어떻게 처리할 지 구현해야한다.

유니티에서는 앞서 언급한 event를 이용한 관찰자 패턴으로 쉽게 구현된다.

또한 View는 Model이나 Controller 같이 다른 구성요소들을 몰라야 한다.

위에서 언급한 View가 Model을 직접 참조하는 것은 좋지 못하다.

View에서 Model의 데이터를 변경할 수 있는 여지가 있기 때문에 두 사이의 연결은 event나 인터페이스를 통해 느슨하게 연결되는 것이 코드의 유지보수 측면에서 좋다.

  1. Controller의 경우는

Controller에서 Model과 View를 직접 참조하는 것이 좋다.

따라서 처음 초기화 시 Controller에서 Model을 직접 생성해주거나 Controller의 생성자(초기화) 파라미터로 Model을 받게 해주고, View와 Model 사이의 연결을 Controller가 연결해주게 만들면 되는 것이다.


Uploaded by N2T