본 글은 유니티에서 발간한 전자책 'Level up your programming with game programming patterns'을 정리한 글입니다. 원문은 다음 링크에서 확인하실 수 있습니다.
https://unity.com/kr/resources/level-up-your-code-with-game-programming-patterns
해당 도서를 정리한 마지막 글입니다.
1. Model View Controller(MVC)
Model View Controller (MVC)는 유저 인터페이스를 개발할 때 흔히 사용되는 디자인 패턴의 일종이다.
MVC의 일반적인 아이디어는 소프트웨어의 로직을 데이터와 표시(presentation) 부분으로 분리하는 것이다. 이렇게 하면 불필요한 의존성이 줄어들고 스파게티 코드를 방지할 수 있다.
MVC 패턴은 애플리케이션을 다음 세 가지 레이어로 분할한다:
- 데이터를 저장하는 Model
Model은 엄격한 데이터 컨테이너로 값들을 보유한다. 게임 로직을 실행하거나 계산을 수행하지 않는다.
- 인터페이스를 담당하는 View
View는 데이터를 화면에 그래픽으로 표시하고 렌더링한다.
- 로직을 처리하는 Controller
Controller는 뇌다. 게임 데이터를 처리하고 값이 런타임에서 어떻게 변경되는지 계산한다.

세 파트는 위 도식에서와 같이 상호작용한다. Model은 애플리케이션의 데이터를 관리하고, View는 해당 데이터를 유저에게 표시한다. Controller는 입력을 처리하고 게임 데이터에 대한 어떤 결정이나 계산을 수행한다. 그런 다음 결과를 다시 Model로 보낸다.
따라서 Controller 자체는 어떤 게임 데이터도 포함하지 않는다. View도 마찬가지다. MVC 디자인은 각 레이어가 하는 일을 제한한다. 하나는 데이터를 보유하고, 다른 하나는 데이터를 처리하고, 마지막 하나는 해당 데이터를 유저에게 표시한다.
표면적으로는 이것을 단일 책임 원칙의 확장으로 생각할 수 있다. 각 부분은 한 가지 일을 하고 그 일을 잘한다. 이것이 MVC 아키텍처의 장점 중 하나이다.
2. Model View Presenter(MVP) and Unity
유니티 프로젝트를 MVC로 개발할 때 기존의 UI 프레임워크(UI Toolkit, Unity UI 등)가 자연스럽게 View의 역할을 한다. 엔진이 완전한 유저 인터페이스 구현을 제공하기 때문에 개별 UI 구성 요소를 처음부터 개발할 필요가 없다.
그러나 전통적인 MVC 패턴을 따르려면 런타임에서 Model의 데이터 변경을 반영하기 위해 View-specific 코드가 필요하다. 이 접근 방식은 유효하지만, 많은 유니티 개발자가 View가 Model을 직접 관찰하지 않는 MVC의 변형을 사용하는 경우가 많다. 이 경우 View는 다음과 같이 동작한다:

MVC의 이러한 변형을 Model View Presenter(MVP) 디자인이라고 한다. MVP는 여전히 서로 다른 세 파트의 레이어를 분리하지만, 각 파트의 책임을 약간 변경한다.
MVP에서 Presenter는 마치 MVC의 Controller와 비슷하지만, Controller와 다르게 다른 레이어들 간의 매개체 역할을 수행한다. 또한 MVC에선 Controller가 입력을 처리했지만 MVP에선 View가 입력을 처리한다.
이 디자인에 이벤트와 옵저버 패턴이 어떻게 들어가는지 주목할 필요가 있다. 먼저 유저는 Unity UI의 버튼, 토글 및 슬라이더 구성 요소와 상호 작용할 수 있다. View는 UI 이벤트를 통해 이 입력을 Presenter에게 다시 보내고, Presenter는 Model을 조작한다. 이후 Model의 상태 변경 이벤트는 Presenter에게 데이터가 업데이트되었음을 알리고, Presenter는 수정된 데이터를 View에 전달하여 View가 이를 바탕으로 UI를 새로 고친다.
3. Example: Health Interface
캐릭터나 아이템의 체력을 보여주는 간단한 시스템을 생각해보자. 모든 것을 데이터와 UI를 섞어놓은 하나의 클래스에 담을 수 있지만, 이는 잘 확장되지 않을 것이다. 기능을 추가할수록 확장하기가 더 복잡해진다.
대신에 보다 MVP 중심적인 방식으로 체력 구성 요소를 다시 작성할 수 있다. 이를 위해 스크립트를 Health와 HealthPresenter로 나눈다. Health 컴포넌트는 다음과 같이 작성할 수 있다.


이 예제에서 Health는 Model로 작용한다. 실제 체력 값을 저장하고, 값이 변경될 때마다 이벤트인 HealthChanged를 호출한다. Health는 게임플레이 로직을 포함하지 않고, 데이터를 증가시키고 감소시키는 메서드만 포함한다.
그러나 대부분의 객체는 직접 Health를 조작하지 않을 것이며, 대신에 HealthPresenter를 사용할 것이다.


다른 게임 오브젝트들은 Damage, Heal 및 Reset을 사용하여 체력 값을 수정하기 위해 HealthPresenter를 사용해야 하며, 평소에 HealthPresenter는 유저 인터페이스를 업데이트하기 위해 Health가 HealthChanged 이벤트를 발생시킬 때까지 기다린다.
샘플 프로젝트에서 유저는 타겟 오브젝트를 클릭하며 데미지를 입히거나 버튼을 사용하여 체력을 초기화할 수 있다. 이러한 작업은 Health를 직접 변경하는 것이 아니라 Damage 또는 Reset을 호출하는 HealthPresenter에게 알려진다. 또한, UI Text 및 UI Slider는 Health가 이벤트를 발생시키고 HealthPresenter에게 값이 변경되었음을 알리면 업데이트된다.
https://github.com/Unity-Technologies/game-programming-patterns-demo/tree/main/Assets/12%20MVP
4. Pros and Cons
MVP 및 MVC는 큰 애플리케이션에서 더 빛을 발한다. 게임을 개발하기 위해 큰 팀이 필요하고 출시 후 장기간 유지할 것으로 예상된다면 MVP 및 MVC로부터 다음과 같은 이점을 누릴 수 있다.
- 작업의 쉬운 분할
View와 Presenter를 분리했기 때문에 유저 인터페이스의 디자인과 업데이트가 나머지 코드와 거의 독립적으로 진행될 수 있다. 이를 통해 특화된 개발자들 사이에 업무를 나눌 수 있다. 가령 팀에 프론트엔드 전문가가 있다면 그들에게 View를 맡길 수 있고, 그들은 다른 모든 사람들로부터 독립적으로 작업할 수 있을 것이다.
- MVP 및 MVC를 사용한 단위 테스트의 단순화
이러한 디자인 패턴은 게임플레이 로직을 유저 인터페이스에서 분리한다. 따라서 실제로 플레이 모드에 들어가지 않고도 코드와 작업할 객체를 시뮬레이션할 수 있다. 이는 상당한 시간을 절약할 수 있다.
- 유지보수 가능한 읽기 쉬운 코드
이 디자인 패턴을 사용하면 일반적으로 더 작은 클래스를 만들게 되어 코드를 읽기 쉽게 만들고 의존성을 낮춘다. 의존성이 적으면 일반적으로 소프트웨어가 고장나는 곳이 적어지고 버그가 숨어있을 수 있는 곳도 적어진다.
MVC 및 MVP가 웹 개발이나 기업 소프트웨어에서 널리 사용되지만, 애플리케이션이 충분한 크기와 복잡성에 도달하기 전까지 그 이점이 나타나지 않을 수 있다. 유니티 프로젝트에서 이러한 패턴을 구현하기 전에 다음 사항을 고려해야 한다.
- 미리 계획하는 것이 필요하다.
이 가이드에서 설명한 다른 패턴과 달리, MVC와 MVP는 더 큰 아키텍처 패턴이다. 이를 사용하려면 책임에 따라 클래스를 분할해야 하며, 이는 조직화가 필요하고 더 많은 초기 작업을 요구한다.
- Unity 프로젝트의 모든 것이 해당 패턴에 맞지는 않는다.
"순수한" MVC 또는 MVP 구현에서는 화면에 렌더링되는 모든 것이 View의 일부이다. 하지만 모든 Unity 구성 요소가 데이터, 로직 및 인터페이스로 쉽게 분리되진 않는다(MeshRenderer 등). 또한, 간단한 스크립트는 MVC/MVP에서 많은 이점을 얻지 못할 수 있다.
어떤 지점에서 패턴의 가장 큰 이점을 얻을 수 있는지를 신중하게 고려해야 한다. 일반적으로 단위 테스트가 이를 안내해준다. MVC/MVP가 테스트를 용이하게 할 수 있다면 해당 애플리케이션 부분에 대해 패턴을 적용하는 것을 고려해라. 그렇지 않으면 프로젝트에 패턴을 강제로 적용하려고 하지마라.
'Unity > Study' 카테고리의 다른 글
| Unity C#) 디자인 패턴 가이드 #7. 옵저버 패턴(Observer pattern) (2) | 2024.03.19 |
|---|---|
| Unity C#) 디자인 패턴 가이드 #6. 스테이트 패턴(State pattern) (0) | 2024.03.17 |
| Unity C#) 디자인 패턴 가이드 #5. 커맨드 패턴(Command pattern) (0) | 2024.03.11 |
| Unity C#) 디자인 패턴 가이드 #4. 싱글톤 패턴(Singleton pattern) (3) | 2024.03.05 |
| Unity C#) 디자인 패턴 가이드 #3. 오브젝트 풀(Object pool) (1) | 2024.03.01 |