[MVVM] 7.MVVM에서의 ViewModel 간 통신과 메시징 시스템, Mediator 패턴을 사용한 ViewModel 간 통신

7. MVVM에서의 ViewModel 간 통신과 메시징 시스템, Mediator 패턴을 사용한 ViewModel 간 통신

MVVM (Model-View-ViewModel) 패턴은 WPF (Windows Presentation Foundation) 애플리케이션에서 널리 사용되는 디자인 패턴입니다. MVVM의 주요 목적은 UI와 비즈니스 로직의 분리를 통해 유지보수성과 재사용성을 높이는 것입니다. 이 패턴에서 ViewModel은 View와 Model 간의 중재자 역할을 하며 데이터 바인딩을 통해 UI를 업데이트합니다. 그러나 애플리케이션이 복잡해짐에 따라 여러 ViewModel 간의 통신이 필요해지며, 이와 관련된 다양한 메커니즘이 필요합니다. 본 글에서는 ViewModel 간의 통신과 메시징 시스템, 그리고 Mediator 패턴을 사용한 ViewModel 간 통신을 자세히 살펴보겠습니다.

1. ViewModel 간 통신의 필요성

MVVM 패턴에서는 각 ViewModel이 특정한 뷰를 담당합니다. 그러나 대규모 애플리케이션에서는 여러 ViewModel이 상호작용해야 할 필요가 있습니다. 예를 들어, 사용자가 한 ViewModel에서 데이터를 입력하면 이 변화가 다른 ViewModel에 영향을 미칠 수 있습니다. 이러한 상황에서 ViewModel 간의 의사소통이 필수적입니다.

ViewModel 간의 통신을 필요로 하는 경우는 다음과 같습니다:

  • 상태 공유: 여러 ViewModel이 동일한 데이터를 공유할 때
  • 상호작용: 한 ViewModel의 작업 결과가 다른 ViewModel의 행동에 영향을 줄 때
  • 이벤트 처리: 여러 ViewModel에서 특정 이벤트가 발생했을 때

2. ViewModel 간의 통신 방법

ViewModel 간의 통신을 위한 방법에는 여러 가지가 있습니다. 여기서는 두 가지 주요 방법인 메시징 시스템과 Mediator 패턴에 대해 설명합니다.

2.1. 메시징 시스템

메시징 시스템은 ViewModel 간의 통신을 지원하는 일반적인 방법입니다. 이 시스템에서는 한 ViewModel이 메시지를 발송하고 다른 ViewModel이 이를 수신하여 반응하는 방식으로 동작합니다. WPF에서는 MvvmLight 또는 Prism과 같은 라이브러리를 사용하여 메시징 시스템을 구현할 수 있습니다.

다음은 MvvmLight를 사용하여 메시징 시스템을 구현한 예제 코드입니다:

using GalaSoft.MvvmLight.Messaging;

public class FirstViewModel : ViewModelBase
{
    public void DoAction()
    {
        // 작업 수행
        Messenger.Default.Send(new NotificationMessage("Hello from FirstViewModel"));
    }
}

public class SecondViewModel : ViewModelBase
{
    public SecondViewModel()
    {
        Messenger.Default.Register(this, OnNotify);
    }

    private void OnNotify(NotificationMessage message)
    {
        if (message.Content.ToString() == "Hello from FirstViewModel")
        {
            // 메시지 처리
        }
    }
}

위 코드는 FirstViewModel이 action을 수행하면서 메시지를 보냅니다. SecondViewModel은 이 메시지를 수신하여 처리하는 구조입니다. 이와 같은 구조는 ViewModel 간의 느슨한 결합을 유지하면서도 각 ViewModel 간의 상호작용을 촉진합니다.

2.2. Mediator 패턴

Mediator 패턴은 객체 간의 상호작용을 조정하는 중재자로서 기능을 수행하는 디자인 패턴입니다. 이 패턴을 사용하면 상호작용하는 객체 간의 의존성을 줄이고, 객체들 간의 커뮤니케이션을 중앙 집중식으로 관리할 수 있습니다. MVVM에서 Mediator 패턴을 사용하여 ViewModel 간의 통신을 구현할 수 있습니다.

다음은 Mediator 패턴을 사용하여 ViewModel 간 통신을 구현한 예제 코드입니다:

public interface IMediator
{
    void Register(string message, IReceiver receiver);
    void Send(string message, object data);
}

public class Mediator : IMediator
{
    private readonly Dictionary> _receivers = new();

    public void Register(string message, IReceiver receiver)
    {
        if (!_receivers.ContainsKey(message))
        {
            _receivers[message] = new List();
        }
        _receivers[message].Add(receiver);
    }

    public void Send(string message, object data)
    {
        if (_receivers.ContainsKey(message))
        {
            foreach (var receiver in _receivers[message])
            {
                receiver.Receive(message, data);
            }
        }
    }
}

public interface IReceiver
{
    void Receive(string message, object data);
}

public class FirstViewModel : ViewModelBase, IReceiver
{
    private readonly IMediator _mediator;

    public FirstViewModel(IMediator mediator)
    {
        _mediator = mediator;
        _mediator.Register("DoSomething", this);
    }

    public void DoAction()
    {
        // Action 수행 후 다른 ViewModel에게 알림
        _mediator.Send("DoSomething", null);
    }

    public void Receive(string message, object data)
    {
        // 메시지 처리
    }
}

public class SecondViewModel : ViewModelBase, IReceiver
{
    private readonly IMediator _mediator;

    public SecondViewModel(IMediator mediator)
    {
        _mediator = mediator;
        _mediator.Register("DoSomething", this);
    }

    public void Receive(string message, object data)
    {
        if (message == "DoSomething")
        {
            // 메시지 처리
        }
    }
}

위 코드에서 Mediator 클래스는 다양한 ViewModel을 등록하고, 특정 메시지를 수신하면 등록된 ViewModel에 알리는 역할을 합니다. 각 ViewModel은 Mediator로부터 메시지를 수신하기 위해 IReceiver 인터페이스를 구현해야 합니다. 이 구조는 ViewModel 간의 결합도를 낮추고, 각 ViewModel 간의 통신을 보다 명확하게 해줍니다.

3. 메시징 시스템과 Mediator 패턴 비교

메시징 시스템과 Mediator 패턴은 모두 ViewModel 간의 통신을 가능하게 해주지만, 각각의 접근 방식에는 장단점이 있습니다.

메시징 시스템의 장점:

  • 구현이 간단하고 직관적입니다.
  • 다양한 메시지를 통해 유연한 통신이 가능합니다.

단점:

  • 메시지가 너무 많이 생기면 관리가 어려워질 수 있습니다.
  • 메시지 처리 순서를 관리하기 어려울 수 있습니다.

Mediator 패턴의 장점:

  • 각 ViewModel 간의 의존성을 줄이고, 중재자를 통해 통신을 처리하여 관리가 용이합니다.
  • 메시지 처리 로직을 중앙 집중화하여 코드의 가독성을 높입니다.

단점:

  • 구현이 상대적으로 복잡할 수 있으며, 초기 설정에 더 많은 코드가 필요할 수 있습니다.
  • 하나의 Mediator가 모든 통신을 처리하므로, 단일 실패 지점이 될 수 있습니다.

4. 결론

MVVM 패턴에서 ViewModel 간의 통신은 애플리케이션의 복잡성을 관리하는 데 매우 중요합니다. 메시징 시스템과 Mediator 패턴은 각각의 장단점이 있으며, 애플리케이션의 요구사항에 따라 적절한 방법을 선택하여 사용할 수 있습니다. 이 두 가지 방법을 통해 ViewModel 간의 통신을 보다 효율적으로 구현하고, UI와 비즈니스 로직의 분리를 유지할 수 있습니다. 이를 통해 유지보수성과 확장성을 갖춘 WPF 애플리케이션을 개발할 수 있습니다.

이러한 기술들은 커다란 애플리케이션을 구축하는 데 있어 필수적으로 익혀야 할 부분입니다. 개발자는 상황에 따라 가장 적합한 방법을 선택하여 사용하고, 각 ViewModel의 lifecycle과 상태를 잘 관리하여 애플리케이션의 품질을 높여야 합니다.

앞으로 더 많은 WPF 및 MVVM 관련 주제를 다루며, 복잡한 애플리케이션에서의 개발 기술과 경험을 공유할 예정입니다.