[MVVM] 7.MVVM에서의 ViewModel 간 통신과 메시징 시스템, Event Aggregator와 Messenger를 활용한 데이터 흐름 관리

호환성과 유지보수성을 가진 애플리케이션 개발을 원한다면, MVVM(Model-View-ViewModel) 패턴은 컨디션, 데이터 바인딩 및 UI(사용자 인터페이스) 분리를 통해 이러한 목표를 달성하는 데 도움을 줄 수 있습니다. 이 글에서는 MVVM에서 ViewModel 간의 통신을 관리하는 메시징 시스템, 특히 Event Aggregator와 Messenger 패턴에 대해 자세히 살펴보겠습니다.

1. MVVM 패턴 개요

MVVM은 사용자 인터페이스와 비즈니스 로직을 분리하는 디자인 패턴으로, WPF 애플리케이션에서 널리 사용됩니다. 이 패턴은 응용 프로그램의 각 구성 요소를 유연하게 관리할 수 있게 해주며, 개인적인 책임을 결정하는 데 도움을 줍니다. 기본 구조는 다음과 같습니다:

  • Model: 애플리케이션의 데이터와 비즈니스 로직을 정의합니다.
  • View: 사용자 인터페이스(UI)를 구성하며, 사용자가 보고 조작할 수 있는 요소들로 구성됩니다.
  • ViewModel: 모델과 뷰를 연결하는 역할을 하며, UI에 필요한 데이터를 가져오고 사용자 상호작용을 처리합니다.

2. ViewModel 간 통신의 필요성

MVVM 패턴에서는 각 ViewModel이 독립적으로 동작하기 때문에, 서로 다른 ViewModel 간에 데이터를 전송해야 하는 경우가 생길 수 있습니다. 예를 들어, 한 ViewModel에서 데이터가 변경되면 다른 ViewModel이 해당 변경 사항을 반영할 필요가 있습니다. 이런 경우, ViewModel 간 통신을 위해서는 커플링을 최소화하면서도 효과적인 데이터 전송이 가능해야 합니다.

3. Event Aggregator와 Messenger 패턴

MVVM에서 ViewModel 간의 통신을 처리하는 주요 방법 중 두 가지는 Event Aggregator와 Messenger입니다. 이 두 패턴은 서로 다르게 작동하지만, 공통적으로 ViewModel 간의 느슨한 결합(loose coupling)을 지원합니다.

3.1 Event Aggregator

Event Aggregator는 여러 컴포넌트 간에 발생하는 이벤트를 처리하는 컴포넌트입니다. 이 패턴은 이벤트를 중앙 집중화하여 시스템 내에서 발생하는 모든 이벤트를 관리할 수 있도록 합니다.

장점

  • 다중 ViewModel 간의 느슨한 결합을 지원함으로써 테스트 용이성을 높입니다.
  • 모듈화된 애플리케이션 구성 요소 간의 통신을 중앙집중화합니다.

예제

using System;
using System.Collections.Generic;

public interface IEventAggregator
{
    void Subscribe(Action action);
    void Publish(T eventMessage);
}

public class EventAggregator : IEventAggregator
{
    private readonly Dictionary> _subscribers = new();

    public void Subscribe(Action action)
    {
        var key = typeof(T);
        if (!_subscribers.ContainsKey(key))
        {
            _subscribers[key] = new List();
        }
        _subscribers[key].Add(action);
    }

    public void Publish(T eventMessage)
    {
        var key = typeof(T);
        if (_subscribers.ContainsKey(key))
        {
            foreach (var action in _subscribers[key])
            {
                ((Action)action)(eventMessage);
            }
        }
    }
}

// ViewModel 예시
public class FirstViewModel
{
    private readonly IEventAggregator _eventAggregator;

    public FirstViewModel(IEventAggregator eventAggregator)
    {
        _eventAggregator = eventAggregator;
    }

    public void ChangeData()
    {
        // 데이터 변경
        _eventAggregator.Publish(new DataChangedEvent { Data = "New Data" });
    }
}

public class SecondViewModel
{
    public SecondViewModel(IEventAggregator eventAggregator)
    {
        eventAggregator.Subscribe(OnDataChanged);
    }

    private void OnDataChanged(DataChangedEvent eventData)
    {
        // 데이터 처리
        Console.WriteLine($"Received Data: {eventData.Data}");
    }
}

public class DataChangedEvent
{
    public string Data { get; set; }
}

3.2 Messenger 패턴

Messenger 패턴은 기본적으로 Event Aggregator와 유사하지만, Messenger는 특정 메시지를 특정 수신자에게 보내는 더 세분화된 방식입니다. 이를 통해 각 ViewModel은 자신이 원하는 특정 메시지만 수신할 수 있습니다.

장점

  • 좀 더 세밀하게 통신을 관리할 수 있습니다.
  • 메시지 타입을 정의함으로써 코드 가독성을 높입니다.

예제

using System;
using System.Windows;

public class Messenger
{
    public void Send(T message)
    {
        // 메시지를 전송하는 로직
        // 예를 들어, WeakEventPattern을 사용하여
    }

    public void Register(Action action)
    {
        // 특정 타입 등록 로직
    }
}

// ViewModel 예시
public class FirstViewModel
{
    public void ChangeData()
    {
        // 데이터 변경 및 메시지 전송
        Messenger.Default.Send(new DataUpdatedMessage { Text = "New Data" });
    }
}

public class SecondViewModel
{
    public SecondViewModel()
    {
        Messenger.Default.Register(OnDataUpdated);
    }

    private void OnDataUpdated(DataUpdatedMessage message)
    {
        MessageBox.Show(message.Text);
    }
}

public class DataUpdatedMessage
{
    public string Text { get; set; }
}

4. 실제 애플리케이션에서의 적용

복잡한 WPF 애플리케이션에서는 Event Aggregator와 Messenger 패턴을 적절히 결합하여 다양한 ViewModel 간의 통신을 원활히 관리할 수 있습니다. 이는 데이터 흐름을 관리하는데 필수적인 요소로 작용하며, 애플리케이션의 상태를 효율적으로 관리할 수 있게 합니다.

5. 결론

MVVM 아키텍처에서 ViewModel 간의 통신과 데이터 흐름 관리는 필수적입니다. Event Aggregator와 Messenger 패턴은 이러한 통신을 효과적으로 관리하는 도구입니다. 이러한 패턴을 통해 느슨한 결합을 유지하면서도, 데이터 변경 상황을 다른 ViewModel에 쉽게 전파할 수 있습니다. WPF 애플리케이션을 개발할 때 이러한 패턴의 중요성을 이해하고 활용하면, 더 나은 소프트웨어 아키텍처를 구축할 수 있을 것입니다.