UI 에서 자주 사용하는 아키텍쳐 패턴 아래는 간단한 예시

Model: HealthModel.cs

using System;
using UnityEngine;

public class HealthModel : MonoBehaviour
{
    public event Action OnHealthChanged;

    private const int k_MinHealth = 0;
    private const int k_MaxHealth = 100;
    private int _currentHealth;

    public int CurrentHealth
    {
        get => _currentHealth;
        set
        {
            _currentHealth = Mathf.Clamp(value, k_MinHealth, k_MaxHealth);
            OnHealthChanged?.Invoke();
        }
    }

    public int MinHealth => k_MinHealth;
    public int MaxHealth => k_MaxHealth;

    public void Increment(int amount) => CurrentHealth += amount;
    public void Decrement(int amount) => CurrentHealth -= amount;
    public void Restore() => CurrentHealth = k_MaxHealth;
}

View: HealthView.cs

using UnityEngine;
using UnityEngine.UI;

public class HealthView : MonoBehaviour
{
    [SerializeField] private Slider _healthSlider;
    [SerializeField] private Text _healthLabel;

    public void SetMaxHealth(int maxHealth)
    {
        _healthSlider.maxValue = maxHealth;
    }

    public void UpdateHealthDisplay(int currentHealth, int maxHealth)
    {
        _healthSlider.value = currentHealth;
        if (_healthLabel != null)
        {
            _healthLabel.text = $"{currentHealth} / {maxHealth}";
        }
    }

    public void Show() => gameObject.SetActive(true);
    public void Hide() => gameObject.SetActive(false);
}

Presenter: HealthPresenter.cs

using UnityEngine;

public class HealthPresenter : MonoBehaviour
{
    [Header("Model")]
    [SerializeField] private HealthModel _model;

    [Header("View")]
    [SerializeField] private HealthView _view;
    
     // 외부에서 호출할 수 있는 API
    public void ApplyDamage(int amount) => _model.Decrement(amount);
    public void ApplyHeal(int amount) => _model.Increment(amount);
    public void ResetHealth() => _model.Restore();

    private void Start()
    {
        if (_model == null || _view == null)
        {
            Debug.LogError("Model or View not assigned in Presenter.");
            return;
        }

        _model.OnHealthChanged += OnHealthChanged;

        _view.SetMaxHealth(_model.MaxHealth);
        _model.Restore(); // 초기화
        UpdateView();
    }

    private void OnDestroy()
    {
        _model.OnHealthChanged -= OnHealthChanged;
    }

    private void OnHealthChanged()
    {
        UpdateView();
    }

    private void UpdateView()
    {
        _view.UpdateHealthDisplay(_model.CurrentHealth, _model.MaxHealth);
    }
}

구조 정리

[외부 입력]
   ↓
Presenter.ApplyDamage(10)
   ↓
Model.Decrement(10) → 내부에서 CurrentHealth 변경
   ↓
Model.OnHealthChanged 이벤트 발생
   ↓
Presenter.OnHealthChanged() 콜백 호출됨
   ↓
Presenter.UpdateView() 실행
   ↓
View.UpdateHealthDisplay(currentHealth, maxHealth)
역할 설명
Model (HealthModel) 상태(데이터)를 보관하고, 변경 시 이벤트 발행
Presenter (HealthPresenter) Model의 상태를 조작하고, 변화가 생기면 View를 갱신
View (HealthView) 순수 UI 표시만 담당 (직접 데이터를 가지거나 수정하지 않음)
외부 버튼이나 다른 UI/게임 로직에서 Presenter에게 요청을 보내는 주체

핵심 규칙: