본문 바로가기

Unity/디자인 패턴

[Unity] MVP(Model-View-Presenter) 패턴 이해 및 활용

반응형

소프트웨어 개발에서의 디자인 패턴의 중요성

소프트웨어 개발에서 디자인 패턴은 반복적으로 발생하는 문제들을 해결하기 위한 최적화된 방법론을 제공합니다. 이러한 패턴은 개발자가 이미 검증된 해결책을 사용함으로써 코드의 유지보수성을 높이고, 개발 시간을 단축시키며, 더 나아가 시스템의 확장성까지 고려할 수 있게 합니다. 특히 복잡한 애플리케이션을 설계할 때, 디자인 패턴은 코드를 모듈화하고 재사용성을 높이는 데 중요한 역할을 합니다.

MVP(Model-View-Presenter) 패턴 개요

MVP(Model-View-Presenter) 패턴은 이러한 디자인 패턴 중 하나로, 사용자 인터페이스(UI) 로직을 보다 명확하게 분리하기 위해 고안되었습니다.

MVP 패턴은 세 가지 주요 구성 요소인 Model, View, 그리고 Presenter로 구성됩니다. 이 패턴의 핵심은 사용자 인터페이스를 담당하는 View와 비즈니스 로직을 처리하는 Model 사이의 의존성을 줄이고, Presenter가 중재자 역할을 하도록 하는 것입니다. 이를 통해 각 컴포넌트는 자신의 역할에만 집중할 수 있으며, 다른 컴포넌트와의 결합도를 낮춰 보다 유연한 코드 구조를 구현할 수 있습니다.

  • Model: 애플리케이션의 데이터와 비즈니스 로직을 담당합니다.
  • View: 사용자에게 보여지는 UI 요소를 관리하며, 데이터를 표시하는 역할을 합니다.
  • Presenter: Model과 View 사이의 중간자로서, 사용자의 입력을 처리하고, Model의 데이터를 View에 전달합니다.

MVP 패턴은 복잡한 UI를 갖춘 애플리케이션에서 특히 유용하며, 각 구성 요소를 분리함으로써 코드의 테스트 용이성과 유지보수성을 크게 향상시킵니다. 이 글에서는 MVP 패턴의 기본 구조와 각 구성 요소의 역할에 대해 자세히 다룰 예정이며, 실제 사례를 통해 이 패턴의 이점을 설명할 것입니다.

이제 MVP 패턴에 대한 자세한 내용을 알아보도록 하겠습니다.

Model: 데이터와 비즈니스 로직을 담당하는 부분

Model은 애플리케이션의 데이터 및 비즈니스 로직을 포함하는 계층입니다. 이 계층은 데이터베이스와 같은 데이터 소스와 상호작용하며, 비즈니스 규칙을 적용하여 데이터를 처리합니다. 또한, Model은 외부에서 데이터에 접근하거나 수정할 수 있는 인터페이스를 제공하며, Presenter와의 통신을 통해 데이터 업데이트 사항을 전달합니다.

  • 주요 역할:
    • 데이터 저장 및 관리
    • 비즈니스 로직 처리
    • Presenter에 데이터 제공

View: 사용자 인터페이스(UI)를 담당하는 부분

View는 사용자에게 보여지는 화면과 UI 요소를 담당하는 계층입니다. 사용자의 입력을 수집하고, 이를 Presenter에 전달하며, Presenter로부터 받은 데이터를 화면에 표시하는 역할을 합니다. 중요한 점은 View는 가능한 한 단순하게 유지되어야 하며, 비즈니스 로직을 포함하지 않아야 합니다. View는 사용자와 상호작용하는 부분에만 집중합니다.

  1. 주요 역할:
    • UI 요소 관리 및 렌더링
    • 사용자 입력 수집
    • Presenter와의 데이터 교환

Presenter: Model과 View 사이에서 중재 역할을 하는 부분

Presenter는 Model과 View 사이에서 중재자 역할을 하며, 이 두 컴포넌트를 분리하는 주요 역할을 합니다. Presenter는 View로부터 사용자 입력을 받아서 Model에 전달하고, Model에서 처리된 데이터를 다시 View로 전달하여 화면에 표시되도록 합니다. 이 과정에서 Presenter는 비즈니스 로직과 UI 로직을 연결해주는 중심적인 역할을 하게 됩니다. Presenter는 View와 Model에 의존하지만, 두 컴포넌트는 서로를 직접 참조하지 않으므로, 독립성이 유지됩니다.

  1. 주요 역할:
    • 사용자 입력 처리 및 Model로 전달
    • Model에서 데이터 가져오기 및 View에 전달
    • 비즈니스 로직 처리 및 UI 업데이트

MVP 패턴의 작동 방식

MVP(Model-View-Presenter) 패턴은 사용자 인터페이스(UI)를 구축할 때, 각 구성 요소(View, Presenter, Model)가 어떻게 상호작용하는지를 명확하게 정의하여 소프트웨어의 구조를 체계화하는 데 중점을 둡니다. 이 섹션에서는 MVP 패턴이 실제로 어떻게 작동하는지를 단계별로 설명합니다.

1. View가 사용자 입력을 받는 과정

먼저, 사용자가 애플리케이션의 UI에서 특정 동작을 수행하면, 이 동작은 View에 의해 감지됩니다. View는 사용자에게 보여지는 화면과 UI 요소를 관리하는 부분으로, 버튼 클릭, 텍스트 입력 등의 사용자 인터페이스 이벤트를 수집합니다.

  • 예시: 사용자가 로그인 화면에서 "로그인" 버튼을 클릭하면, View는 이 이벤트를 캡처합니다.

2. Presenter가 이를 처리하고 Model과 상호작용하는 과정

View는 캡처된 사용자 입력 이벤트를 Presenter에게 전달합니다. Presenter는 이 입력을 처리하고, 적절한 비즈니스 로직을 실행하기 위해 Model과 상호작용합니다. Presenter는 사용자 입력을 해석하고, Model로부터 필요한 데이터를 요청하거나, 데이터를 업데이트하는 등의 작업을 수행합니다.

  • 예시: Presenter는 "로그인" 버튼 클릭 이벤트를 받으면, 사용자가 입력한 사용자 이름과 비밀번호를 확인하고, 이를 Model에 전달하여 로그인 절차를 수행하도록 요청합니다.

Presenter와 Model의 상호작용:

  • Presenter는 필요한 데이터를 Model에 요청합니다. 예를 들어, 로그인 요청이 있을 경우, Presenter는 사용자 이름과 비밀번호를 전달하여 Model이 이 정보를 바탕으로 인증 작업을 수행하게 합니다.
  • Model은 비즈니스 로직을 처리한 후, 그 결과를 Presenter에게 전달합니다. Model은 데이터베이스와 상호작용하거나 비즈니스 규칙을 적용하여 데이터를 처리합니다.
  • 예시: Model은 데이터베이스에서 사용자 정보를 조회하여, 입력된 정보가 유효한지 확인한 후, 그 결과를 Presenter에게 반환합니다.

3. 최종적으로 View에 데이터를 표시하는 과정

Presenter는 Model로부터 받은 데이터를 바탕으로 UI를 업데이트할 수 있는 로직을 실행합니다. Presenter는 데이터를 가공하여 View에 전달하고, View는 이를 화면에 적절하게 표시합니다.

  • 예시: Presenter는 Model로부터 "로그인 성공" 또는 "로그인 실패" 메시지를 받아, 이 메시지를 View에 전달합니다. View는 이를 사용자에게 적절하게 표시합니다. 만약 로그인에 성공했다면, 홈 화면으로 전환될 수 있고, 실패했다면 오류 메시지가 표시됩니다.

MVP 패턴의 상호작용 과정 요약

  1. 사용자 입력 → View: 사용자는 UI에서 이벤트를 발생시킵니다. (예: 버튼 클릭)
  2. View → Presenter: View는 이 이벤트를 Presenter에게 전달합니다.
  3. Presenter → Model: Presenter는 이벤트에 따라 비즈니스 로직을 처리하기 위해 Model과 상호작용합니다.
  4. Model → Presenter: Model은 요청된 데이터를 처리하고, 결과를 Presenter에게 반환합니다.
  5. Presenter → View: Presenter는 Model의 데이터를 바탕으로 View를 업데이트하도록 지시합니다.
  6. View 업데이트: View는 Presenter가 전달한 데이터를 화면에 표시합니다.

MVP 패턴의 장점

MVP(Model-View-Presenter) 패턴은 소프트웨어 개발에서 다양한 장점을 제공하며, 특히 테스트 용이성, 유지보수성, 그리고 재사용성 측면에서 두각을 나타냅니다.

1. 테스트 용이성

MVP 패턴의 가장 큰 장점 중 하나는 테스트 용이성입니다. 이 패턴은 비즈니스 로직을 View로부터 분리하여 Presenter에 집중시키기 때문에, 독립적인 단위 테스트가 가능합니다. 예를 들어, View가 UI에 집중하고 Presenter가 모든 로직을 처리하기 때문에, View를 테스트할 때는 UI 요소만 검증하면 되고, Presenter를 테스트할 때는 비즈니스 로직이 올바르게 동작하는지 확인할 수 있습니다. 이렇게 각 컴포넌트를 분리하여 테스트할 수 있기 때문에, 전체 애플리케이션의 신뢰성을 높일 수 있습니다​.

2. 유지보수성

MVP 패턴은 구조적 분리를 통해 코드의 유지보수성을 크게 향상시킵니다. 이 패턴에서는 View, Presenter, 그리고 Model이 명확하게 분리되어 있기 때문에, 각 부분의 수정이 다른 부분에 미치는 영향을 최소화할 수 있습니다. 예를 들어, UI 디자인이 변경되더라도 View만 수정하면 되며, Presenter나 Model에는 영향을 미치지 않습니다. 이는 애플리케이션의 요구사항이 변화할 때, 코드의 특정 부분만을 수정함으로써 빠르게 대응할 수 있게 합니다​.

3. 재사용성

MVP 패턴은 Presenter와 Model의 재사용성을 크게 향상시킵니다. Presenter는 여러 View에서 재사용될 수 있으며, 동일한 비즈니스 로직을 사용하는 경우에도 코드를 중복하지 않고 여러 UI에서 활용할 수 있습니다. Model 역시 비즈니스 로직을 캡슐화하고 있으므로, 다양한 부분에서 재사용이 가능하여 개발 시간을 단축하고 코드의 일관성을 유지할 수 있습니다. 이렇게 각 구성 요소의 독립성과 분리된 책임 덕분에, MVP 패턴은 다양한 프로젝트에서 유연하게 재사용될 수 있습니다​.

유니티(Unity)에 적용하기

1. 프로젝트 설정

먼저 유니티 프로젝트를 생성한 후, 필요한 스크립트를 생성합니다. 이번 포스트에서는 이전에 진행했던 MVC 디자인 패턴 포스트에서 사용한 프로젝트에 이어서 작업하겠습니다.

[Unity] MVC(Model-View-Controller) 패턴 이해 및 활용 - 오월의 사중주

새 Unity 프로젝트를 생성하거나, 기존 프로젝트에서 Model, View, Controller 폴더를 프로젝트의 Scripts 폴더 아래에 생성합니다. 각 폴더에 필요한 스크립트를 추가합니다. 기존 폴더에서 진행할 경우, 기존에 만들어둔 Player 스크립트 또한 각 역할 폴더에

새로운 Scene에서 작업하기 위해, Project 탭에서 우클릭 후 새 Scene을 생성합니다.

Main Camera의 ClearFlags는 Solid Color로 변경 후 검은색으로 바꿔줍니다.

Scripts 폴더 내의 기존 폴더들을 MVC 폴더를 생성하여 넣어주고, MVP 폴더를 만든 후 MVP 폴더 안에 Model, View, Presenter, Interface 폴더를 생성합니다. 이후 각 함수는 각 폴더의 위치에 맞게 생성해줍시다.

2. Model 클래스

UserModel 클래스는 사용자의 데이터를 저장하는 역할을 합니다. 이 클래스는 간단하게 사용자 이름과 비밀번호만 관리하도록 하겠습니다.

public class UserModel
{
    public string Username { get; set; }
    public string Password { get; set; }
    
    public UserModel(string username, string password)
    {
        Username = username;
        Password = password;
    }
}

3. View 인터페이스

View는 사용자에게 보여지는 UI를 관리하며, 사용자 입력을 Presenter에게 전달합니다. 여기서는 IUserView 인터페이스를 정의하여 필요한 메서드를 선언합니다. 이 스크립트는 Interface 폴더에 넣어줍니다.

public interface IUserView
{
    void ShowLoginSuccess(string message);
    void ShowLoginFailure(string message);
    string GetUsername();
    string GetPassword();
}

4. Presenter 클래스

Presenter는 View와 Model 사이의 중재자 역할을 합니다. 사용자의 입력을 받아 Model을 업데이트하고, 결과를 View에 전달합니다.

public class UserPresenter
{
    private readonly IUserView _view;
    private UserModel _model;

    public UserPresenter(IUserView view)
    {
        _view = view;
    }

    public void OnLoginButtonClicked()
    {
        string username = _view.GetUsername();
        string password = _view.GetPassword();

        // 단순한 인증 로직 (예를 들어 "admin" / "1234" 조합으로만 성공 처리)
        if (username == "admin" && password == "1234")
        {
            _model = new UserModel(username, password);
            _view.ShowLoginSuccess("Login successful! Welcome " + _model.Username);
        }
        else
        {
            _view.ShowLoginFailure("Login failed! Please check your credentials.");
        }
    }
}

5. View 구현 (Unity UI 스크립트)

View는 Unity의 MonoBehaviour를 상속받아 구현합니다. Unity의 UI 요소를 사용해 사용자 입력을 받고, 이를 Presenter에 전달합니다.

using UnityEngine;
using TMPro;

public class LoginView : MonoBehaviour, IUserView
{
    public TMP_InputField usernameInput;
    public TMP_InputField passwordInput;
    public TMP_Text messageText;
    
    private UserPresenter _presenter;

    private void Start()
    {
        _presenter = new UserPresenter(this);
    }

    public void OnLoginButtonClicked()
    {
        _presenter.OnLoginButtonClicked();
    }

    public void ShowLoginSuccess(string message)
    {
        messageText.text = message;
        messageText.color = Color.green;
    }

    public void ShowLoginFailure(string message)
    {
        messageText.text = message;
        messageText.color = Color.red;
    }

    public string GetUsername()
    {
        return usernameInput.text;
    }

    public string GetPassword()
    {
        return passwordInput.text;
    }
}

6. Unity 씬 구성

  1. Create Empty 로 빈 오브젝트를 생성하고 Login Manager로 명명한 후, LoginView Script를 부착합니다.
  2. TMP_InputField 두 개를 생성하여 usernameInput과 passwordInput에 연결합니다.
  3. TMP_Text UI 요소를 생성하여 messageText에 연결합니다.
  4. Button UI 요소를 추가하고, OnLoginButtonClicked() 메서드를 버튼 클릭 이벤트에 연결합니다.

작동 방식

  • 사용자가 UI에서 로그인 버튼을 클릭하면, LoginView가 Presenter에 사용자 입력을 전달합니다.
  • Presenter는 입력된 정보를 확인하고, 결과를 View에 전달하여 사용자에게 성공 또는 실패 메시지를 보여줍니다.
  • 테스트 용으로 지정된 아이디 및 비밀번호는 admin / 1234 입니다.

Input Field 간단 팁

TextMeshPro - Input Field의 Content Type 옵션은 입력 필드의 텍스트 입력을 특정 유형으로 제한하거나 포맷팅하는 데 사용됩니다. 각 옵션은 사용자가 입력할 수 있는 내용과 텍스트의 동작 방식을 정의합니다. 다음은 유니티의 TextMeshPro - Input Field에서 제공하는 각 Content Type의 기능에 대한 간략한 설명입니다:

  1. Standard: 기본 텍스트 입력 유형으로, 모든 문자와 숫자를 입력할 수 있습니다. 특별한 제한이나 포맷팅이 없습니다.
  2. Autocorrected: 모바일 기기에서 주로 사용되며, 자동 완성 기능을 사용합니다. 입력된 텍스트에 대해 자동 교정이 적용될 수 있습니다.
  3. Integer Number: 사용자가 정수(음수와 양수 모두 가능)만 입력할 수 있도록 제한합니다. 소수점이나 다른 문자 입력은 허용되지 않습니다.
  4. Decimal Number: 사용자가 실수(소수점 포함) 숫자를 입력할 수 있습니다. 숫자와 소수점 외에는 입력이 제한됩니다.
  5. Alphanumeric: 알파벳 문자(A-Z, a-z)와 숫자(0-9)만 입력할 수 있도록 제한합니다. 특수 문자는 허용되지 않습니다.
  6. Name: 이름 입력을 위한 필드로, 첫 글자를 자동으로 대문자로 변환합니다. 일반적으로 이름을 입력할 때 사용됩니다.
  7. Email Address: 이메일 주소 입력을 위한 필드로, 이메일 형식에 맞는 문자(알파벳, 숫자, '@', '.', 등)만 입력할 수 있도록 합니다.
  8. Password: 입력된 문자가 화면에 표시되지 않고, 대신에 '*' 또는 다른 마스킹 문자가 표시됩니다. 비밀번호와 같은 민감한 정보를 입력할 때 사용됩니다.
  9. Pin: 숫자 입력을 위한 필드로, 비밀번호와 마찬가지로 입력된 숫자가 마스킹됩니다. 주로 숫자로 구성된 비밀번호(PIN 코드)를 입력할 때 사용됩니다.
  10. Custom: 개발자가 직접 커스터마이징할 수 있는 입력 유형입니다. 특정 포맷이나 입력 제한이 필요한 경우, 직접 설정할 수 있습니다.

완성 프로젝트

완성된 프로젝트를 올려둔 Github 주소입니다.

UnityGithub/DesignPatternProject at main · ralskwo/UnityGithub

Contribute to ralskwo/UnityGithub development by creating an account on GitHub.

실제 MVP 패턴 적용 사례: 안드로이드 애플리케이션

1. 안드로이드 애플리케이션에서의 MVP 패턴 적용

MVP(Model-View-Presenter) 패턴은 안드로이드 애플리케이션 개발에서 널리 사용되는 아키텍처 패턴입니다. 이 패턴은 UI 로직과 비즈니스 로직을 명확하게 분리하여 코드의 유지보수성과 테스트 용이성을 높입니다. 특히, 안드로이드의 Activity나 Fragment에 비즈니스 로직을 포함하지 않고, 이 로직을 Presenter에 위임함으로써 Activity나 Fragment의 복잡도를 크게 줄일 수 있습니다.

2. 예제 코드 및 프로젝트 링크

여기 MVP 패턴을 사용한 안드로이드 프로젝트 세 가지를 소개합니다. 이 프로젝트들은 각각 GitHub에서 100개 이상의 별(star)을 받은 인기 있는 예제들입니다.

  1. kaedea/android-mvp-pattern
    이 프로젝트는 MVP 패턴을 사용하여 간단하고 명확한 안드로이드 애플리케이션을 구현한 예제입니다. 로그인 폼과 EventBus를 사용한 복잡한 구현 등 다양한 MVP 사용 사례를 포함하고 있으며, 약 700개의 별을 받아 개발자들에게 인기가 많습니다.
  2. jpotts18/android-mvp
    이 레포지토리는 안드로이드 MVP 아키텍처에 대한 참고 자료와 비디오 튜토리얼을 제공합니다. 로그인 화면부터 GitHub 리포지토리 목록을 표시하는 복잡한 활동까지 다양한 예제를 통해 MVP 패턴을 자세히 설명합니다. 이 프로젝트는 200개 이상의 별을 받아 MVP 패턴 학습에 유용한 자료입니다.
  3. raxden/android-mvp
    이 프로젝트는 Android 4.1(API 레벨 16) 이상을 지원하는 MVP 패턴을 위한 기본 라이브러리입니다. 다양한 예제와 문서가 포함되어 있어, 개발자가 자신의 애플리케이션에 MVP를 쉽게 통합할 수 있도록 돕습니다.

이들 프로젝트는 실제 안드로이드 애플리케이션에서 MVP 패턴이 어떻게 사용되는지 이해하는 데 도움이 되는 훌륭한 자료들입니다. 각 프로젝트의 GitHub 링크를 통해 더 자세한 내용을 확인할 수 있습니다.

MVP 패턴 요약: 핵심 요점

MVP(Model-View-Presenter) 패턴은 애플리케이션의 UI 로직과 비즈니스 로직을 명확히 분리하여 유지보수성과 테스트 용이성을 높이는 데 중점을 둔 아키텍처 패턴입니다. 이 패턴은 세 가지 주요 컴포넌트로 구성됩니다:

  • Model: 데이터와 비즈니스 로직을 담당하며, 데이터의 저장 및 처리, 비즈니스 규칙의 적용 등을 수행합니다.
  • View: 사용자 인터페이스(UI)를 담당하며, 사용자가 상호작용하는 화면 요소를 표시합니다.
  • Presenter: Model과 View 사이에서 중재 역할을 하며, 사용자의 입력을 처리하고 그 결과를 View에 반영합니다. Presenter는 View와 직접 상호작용하지 않고 인터페이스를 통해 통신합니다, 이를 통해 View와 Presenter 간의 결합도를 낮춥니다.

결론: MVP 패턴을 선택할 때 고려할 사항

MVP(Model-View-Presenter) 패턴을 선택할 때는 다음과 같은 핵심 사항들을 고려해야 합니다:

  1. 프로젝트의 복잡성:
    • 프로젝트가 복잡하고 유지보수가 중요한 경우, MVP 패턴은 코드의 모듈화와 테스트 용이성을 크게 향상시킵니다.
    • 복잡한 애플리케이션에서는 다양한 UI 요소와 비즈니스 로직을 분리하여 관리할 필요가 있습니다.
    • MVP 패턴은 이러한 요구를 충족시키며, 코드를 더 잘 구조화하고 이해하기 쉽게 만들어줍니다​.
  2. 테스트 우선순위:
    • MVP 패턴의 가장 큰 장점 중 하나는 Presenter가 View와 독립적으로 동작할 수 있다는 점입니다.
    • 이는 단위 테스트를 매우 쉽게 만들어주며, 특히 테스트 자동화가 중요한 프로젝트에서 큰 이점을 제공합니다.
    • Presenter와 View 간의 인터페이스 기반 상호작용 덕분에, UI 로직이 변경되더라도 Presenter의 로직을 재사용하고 독립적으로 테스트할 수 있습니다.
  3. 개발 팀의 규모:
    • 큰 팀에서 여러 개발자가 함께 작업하는 경우, 코드의 명확한 분리와 역할 정의가 필수적입니다.
    • MVP 패턴은 이러한 환경에서 효과적으로 사용될 수 있습니다. 각 구성 요소가 독립적으로 개발되고 유지관리될 수 있어, 팀 간의 협업이 더 수월해집니다.
    • 이는 코드의 충돌을 줄이고, 모듈 단위의 개발이 가능하게 하여 대규모 프로젝트의 효율성을 극대화합니다​

결론적으로, MVP 패턴은 복잡한 애플리케이션 개발에서 코드의 모듈화, 유지보수성, 그리고 테스트 용이성을 극대화하는데 매우 효과적입니다. 특히 대규모 팀에서 작업할 때, 각 구성 요소가 명확히 분리되어 개발과 협업이 용이해집니다. 이러한 이점들은 복잡한 프로젝트에서 성공적인 소프트웨어 개발을 가능하게 합니다. 따라서 프로젝트의 요구사항에 따라 MVP 패턴을 신중히 고려하는 것이 바람직합니다.

반응형