해당 포스팅은 개인적으로 C# WPF를 공부하면서 익힌 내용을 기억에 남기기 위한 작업의 일환으로 작성된 글로서
일부 내용에 오류가 있을 수도 있으니 참고하시기 바랍니다.
C#WPF에서 MVVM패턴으로
프로그래밍 할때 Dependency Injection(DI)의
개념과 역할에 대해
알아보자.
내용 요약
MVVM (Model-View-ViewModel) 패턴은 WPF (Windows Presentation Foundation) 애플리케이션에서 UI와 비즈니스 로직을 분리하는 데 사용되는 아키텍처 패턴이다. 이 패턴은 코드의 재사용성과 테스트 용이성을 높이며, UI의 상태와 동작을 관리하는 ViewModel을 중심으로 구성된다. Dependency Injection (DI)은 이러한 MVVM 패턴을 구현할 때 매우 유용한 기법으로, 객체 간의 의존성을 관리하고, 코드의 결합도를 낮추는 데 도움을 준다.
목차
1.MVVM 패턴이란?
2.Dependency Injection 이란?
3.MVVM 패턴에서 Dependency Injection의 역할
4.WPF MVVM에서 DI 구현 예제
5.Dependency Injection 사용 시 주의할 점
1. MVVM 패턴이란?
MVVM(Model-View-ViewModel) 패턴은 WPF(Windows Presentation Foundation) 애플리케이션에서 자주 사용되는 아키텍처 패턴으로, 코드의 가독성과 유지보수성을 높이기 위해 설계되었다. MVVM은 세 가지 주요 컴포넌트로 구성된다.
• Model: 애플리케이션의 데이터와 비즈니스 로직을 나타냄.
• View: 사용자 인터페이스(UI) 요소를 담당하며, 데이터 바인딩(Data Binding)을 통해 ViewModel과 상호작용한다.
• ViewModel: View와 Model 간의 중개 역할을 하며, View에 필요한 데이터를 제공하고 명령(Command)을 처리한다.
MVVM 패턴을 따를 때, View와 ViewModel은 느슨하게 결합되어야 하며, 이는 테스트 가능성과 확장성을 높이는 데 기여한다. 여기서 Dependency Injection(DI)은 ViewModel과 Model, 서비스 간의 의존성을 효과적으로 관리하는 데 중요한 역할을 한다.
2. Dependency Injection이란?
**Dependency Injection(DI)**는 객체 간의 의존성을 외부에서 주입하는 설계 패턴이다. 객체가 스스로 필요한 의존성을 생성하거나 관리하지 않고, 외부에서 주입받음으로써 코드의 유연성과 테스트 용이성을 높인다.
Dependency Injection의 핵심 개념
1. 의존성(Dependency): 한 클래스가 다른 클래스의 기능을 사용하려면 해당 클래스에 의존해야 한다. 예를 들어, ViewModel이 데이터 저장소를 사용해야 한다면, 이 저장소(Repository)가 ViewModel의 의존성이다.
2. 주입(Injection): 의존성을 직접 생성하지 않고 외부에서 필요한 객체를 주입한다.
3. 느슨한 결합(Loose Coupling): DI를 통해 클래스 간의 결합도를 낮추고, 변경 사항이 최소화되도록 설계한다.
DI의 종류
DI는 객체를 주입하는 방식에 따라 세 가지 유형으로 나뉜다.
• 생성자 주입(Constructor Injection): 의존성을 생성자의 매개변수로 전달.
• 속성 주입(Property Injection): 의존성을 객체의 속성을 통해 전달.
• 메서드 주입(Method Injection): 의존성을 메서드 호출 시 전달.
3. MVVM 패턴에서 Dependency Injection의 역할
WPF에서 MVVM 패턴을 사용할 때 Dependency Injection은 다음과 같은 역할을 한다:
1. ViewModel 생성 및 관리
• DI는 ViewModel의 의존성을 주입하고 객체 생성을 관리한다.
• 이를 통해 ViewModel의 독립성을 유지하며, 단위 테스트가 용이해진다.
2. 서비스 및 데이터 액세스 계층의 주입
• 데이터 액세스 계층(예: Repository 패턴) 또는 서비스 클래스(예: API 호출)를 ViewModel에 주입하여 분리된 로직을 재사용할 수 있다.
3. 전역 상태 관리
• DI 컨테이너를 사용하면 애플리케이션 전체에서 공유해야 하는 전역 서비스(예: 설정, 인증 상태)를 관리할 수 있다.
4. WPF MVVM에서 DI 구현 예제
다음은 DI를 사용하여 MVVM 패턴을 구현하는 간단한 예제이다.
(1) 프로젝트 설정
1. NuGet 패키지 설치
• Microsoft.Extensions.DependencyInjection 패키지를 설치하여 DI 컨테이너를 사용한다.
(2) Model 정의
public class DataModel
{
public string GetData() => "Hello, Dependency Injection!";
}
(3) Service Interface 정의
public interface IDataService
{
string FetchData();
}
public class DataService : IDataService
{
private readonly DataModel _dataModel;
public DataService(DataModel dataModel)
{
_dataModel = dataModel;
}
public string FetchData() => _dataModel.GetData();
}
(4) ViewModel 정의
using System.ComponentModel;
public class MainViewModel : INotifyPropertyChanged
{
private readonly IDataService _dataService;
private string _displayData;
public string DisplayData
{
get => _displayData;
set
{
_displayData = value;
OnPropertyChanged(nameof(DisplayData));
}
}
public MainViewModel(IDataService dataService)
{
_dataService = dataService;
LoadData();
}
private void LoadData()
{
DisplayData = _dataService.FetchData();
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
(5) DI(의존성 주입) 컨테이너 설정
using Microsoft.Extensions.DependencyInjection;
public partial class App : Application
{
public static ServiceProvider ServiceProvider { get; private set; }
protected override void OnStartup(StartupEventArgs e)
{
var services = new ServiceCollection();
// DI 등록
services.AddSingleton<DataModel>();
services.AddSingleton<IDataService, DataService>();
services.AddSingleton<MainViewModel>();
ServiceProvider = services.BuildServiceProvider();
var mainWindow = new MainWindow
{
DataContext = ServiceProvider.GetRequiredService<MainViewModel>()
};
mainWindow.Show();
base.OnStartup(e);
}
}
(6) View (XAML) 정의
<Window x:Class="WpfApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Dependency Injection Example" Height="200" Width="400">
<Grid>
<TextBlock Text="{Binding DisplayData}" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="20"/>
</Grid>
</Window>
5. Dependency Injection 사용 시 주의할 점
1. 과도한 의존성 주입
• 너무 많은 의존성을 주입하면 코드가 복잡해지고 관리가 어려워질 수 있으므로 필요한 최소한의 의존성만 주입하도록 설계해야 한다.
2. 서비스 수명 주기 관리
• DI 컨테이너를 사용할 때 객체의 수명 주기(Transient, Scoped, Singleton)를 신중히 선택해야 한다. WPF에서는 대부분 Singleton이 적합하지만, 특정 경우에는 Transient가 유용할 수 있다.
3. DI 컨테이너에 과도한 의존
• DI 컨테이너에 모든 것을 등록하려다 보면 의존성 주입의 장점이 감소할 수 있으니 중요한 의존성만 컨테이너에 등록해야 한다.
4. 유닛 테스트와 DI
• DI는 유닛 테스트를 쉽게 만들어주지만, Mock 객체를 올바르게 사용하지 않으면 테스트가 복잡해질 수 있다. 인터페이스 기반 설계와 Mocking 라이브러리(예: Moq)를 활용하자.
5. 초기 설정 복잡성
• DI를 도입하면 초기 설정이 복잡해질 수 있으므로, 프로젝트 초기 단계에서 DI를 도입할지 여부를 신중히 결정하자.
결론
WPF에서 MVVM 패턴을 사용할 때 Dependency Injection은 클래스 간의 결합도를 낮추고, 테스트 가능성과 유지보수성을 높이는 강력한 도구이다. DI는 ViewModel, Model, 서비스 계층 간의 의존성을 명확히 관리하고, 전역 상태를 효율적으로 다룰 수 있도록 돕는다. 하지만 과도한 의존성 주입을 피하고 서비스 수명 주기를 신중히 설계하여 복잡성을 최소화하는 것이 중요하다.
'프로그래밍 > C# (WPF)' 카테고리의 다른 글
C# WPF에서 MVVM패턴으로 프로그래밍 할 때, View와 ViewModel간 DataContext 설정하는 방법에 대해 (1) | 2024.11.27 |
---|---|
C# WPF에서 MVVM패턴을 사용할 때 OnPropertyChanged에 대하여 (0) | 2024.11.26 |
C# WPF MVVM패턴을 사용할 때 ObservableCollection에 대하여 (0) | 2024.11.24 |
C# WPF MVVM패턴에서 ICommand 인터페이스에 대하여 (2) | 2024.11.23 |
C# WPF에서 MVVM 패턴을 사용할 때 INotifyPropertyChanged 인터페이스에 대하여 (0) | 2024.11.22 |