22.MVVM 패턴을 이용한 WPF 애플리케이션 구조화, WPF 프로젝트에서 MVVM 패턴 적용하기

1. 서론: WPF와 MVVM의 개요

Windows Presentation Foundation(WPF)은 데스크톱 응용 프로그램을 개발하기 위한 강력한 기술입니다. WPF의 주요 장점은 데이터 바인딩, 사용자 인터페이스의 동적 변화, 다양한 그래픽 등의 기능을 통해 보다 깨끗하고 관리하기 쉬운 코드를 작성할 수 있다는 것입니다.
그러나 이러한 장점이 있음에도 불구하고, 대규모 응용 프로그램에서 복잡한 UI와 비즈니스 로직이 겹쳐지면 코드가 복잡해지고 관리가 어려워질 수 있습니다.
이를 해결하기 위해 MVVM(Model-View-ViewModel) 패턴이 등장했습니다.

2. MVVM 패턴의 이해

MVVM은 세 가지 주요 구성 요소로 이루어져 있습니다:

  • Model: 애플리케이션의 데이터와 비즈니스 로직을 포함합니다. 일반적으로 데이터베이스와의 상호작용을 처리하는 클래스들로 구성됩니다.
  • View: 사용자 인터페이스(UI) 요소를 정의합니다. WPF에서는 XAML을 사용하여 뷰를 정의하고 UI와 사용자 상호작용을 처리합니다.
  • ViewModel: Model과 View를 연결하는 역할을 합니다. ViewModel은 데이터 상태를 관리하고, View와의 데이터 바인딩을 통해 UI를 업데이트합니다.

MVVM 패턴의 장점은 다음과 같습니다:

  1. 코드의 분리가 이루어져 유지보수와 테스트가 용이해진다.
  2. UI를 보다 직관적으로 설계할 수 있으며, 디자이너와 개발자 간의 협업이 쉬워진다.
  3. 데이터 바인딩을 통해 UI 업데이트가 자동으로 이루어진다.

3. WPF에서 MVVM 패턴 구현하기

3.1. 프로젝트 설정

Visual Studio를 열고 새로운 WPF Application 프로젝트를 생성합니다. 이를 통해 기본 WPF 설정이 성립됩니다. 이후 필요한 NuGet 패키지를 설치합니다. 예를 들어, MVVM 프레임워크인
MVVM Light Toolkit를 사용하여 ViewModel을 관리할 수 있습니다.

3.2. Model 클래스 정의

Model은 애플리케이션의 데이터 구조를 정의하는 클래스입니다. 예를 들어, 제품의 정보를 담는 Product 클래스를 정의해보겠습니다.


public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }
}
            

3.3. ViewModel 클래스 정의

ViewModel은 데이터와 UI의 상호작용을 담당합니다. ProductViewModel 클래스에서 Model의 Product를 바인딩할 수 있도록 구현합니다.


using System.Collections.ObjectModel;
using System.ComponentModel;

public class ProductViewModel : INotifyPropertyChanged
{
    private Product selectedProduct;
    public ObservableCollection Products { get; set; }

    public Product SelectedProduct
    {
        get { return selectedProduct; }
        set
        {
            selectedProduct = value;
            OnPropertyChanged("SelectedProduct");
        }
    }

    public ProductViewModel()
    {
        Products = new ObservableCollection
        {
            new Product { Id = 1, Name = "제품A", Price = 1000 },
            new Product { Id = 2, Name = "제품B", Price = 2000 }
        };
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}
            

3.4. View 정의

View는 XAML을 통해 UI를 정의합니다. 아래는 MVVM을 활용하여 바인딩하는 예제를 보여줍니다.



    
        
        
    

            

위의 코드에서 ComboBox는 Products 컬렉션을 바인딩하여 사용자가 제품을 선택하도록 하며, TextBlock은 선택된 제품의 가격을 표시합니다.

4. MVVM 패턴의 최적화 및 확장

MVVM 패턴은 간단한 애플리케이션에서부터 대규모 애플리케이션까지 유연하게 활용될 수 있습니다.
코드의 재사용성을 높이고, 테스트를 용이하게 하기 위해 추가적인 패턴이나 툴도 함께 고려해 볼 수 있습니다. 예를 들어, ICommand 인터페이스를 사용하여
뷰모델의 명령을 관리할 수 있습니다. 이러한 명령을 통해 클릭 이벤트나 기타 사용자 인터페이스 이벤트를 처리할 수 있습니다.

4.1. ICommand 인터페이스 사용하기


using System;
using System.Windows.Input;

public class RelayCommand : ICommand
{
    private readonly Action execute;
    private readonly Func canExecute;

    public RelayCommand(Action execute, Func canExecute = null)
    {
        this.execute = execute;
        this.canExecute = canExecute;
    }

    public bool CanExecute(object parameter) => canExecute?.Invoke(parameter) ?? true;

    public void Execute(object parameter) => execute(parameter);

    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }
}
            

RelayCommand를 통해 Button 클릭 이벤트를 처리할 수 있습니다. 뷰모델에서는 이를 다음과 같이 사용할 수 있습니다.


public ICommand AddProductCommand => new RelayCommand(AddProduct);

private void AddProduct(object obj)
{
    // 제품 추가 로직
}
            

5. 결론

MVVM 패턴은 WPF 애플리케이션에서 코드의 분리와 유지보수성을 높이는 매우 유용한 디자인 패턴입니다. Model, View, ViewModel의 명확한 책임 분리는 애플리케이션을
보다 효율적으로 관리할 수 있게 해줍니다. 예제와 같이 기본적인 MVVM 구조를 Implement 함으로써 전체적인 프로젝트 구조를 보다 명확히 하고,
새로운 기능을 추가하거나 수정할 때에도 유연하게 대처할 수 있습니다. WPF와 MVVM을 적절히 활용하여 스마트 팩토리와 같은 복잡한 애플리케이션에서도 적용할 수 있는 유연한 아키텍처를 갖출 수 있습니다.