1. 출처 및 참고자료

더보기
✔️ Microsoft Docs: MVVM Toolkit IoC

관련 네임스페이스:

using CommunityToolkit.Mvvm.DependencyInjection;

 

학습 목표

 

  • IoC를 사용한 구조와 사용하지 않은 구조를 단계별 비교한다.
  • Service, ViewModel, App.xaml.cs, MainWindow.xaml을 모두 작성한다.
  • 최종적으로 WPF MVVM 프로젝트에서 IoC가 왜 중요한지 체험한다.

 

 

2. 기능명: Ioc.Default, IServiceProvider

더보기

✔️ Inversion of Control (제어의 역전)란?

  • 객체의 생성과 관계 설정을 개발자가 직접 하지 않고, IoC 컨테이너가 대신 처리
  • IoC를 통해, 객체 생성을 프레임워크에 위임하여 의존성을 제거
  • MVVM에서의 적용: ViewModel에서 Service를 직접 생성하지 않고, 생성자 주입(Dependency Injection)을 통해 주입받음

 

✔️ 작동 방식

  • MVVM Toolkit은 내부적으로 간단한 IoC 컨테이너를 제공합니다.
  • Ioc.Default.ConfigureServices(...) 메서드를 통해 서비스 및 ViewModel을 등록합니다.
  • 등록된 인스턴스는 **Ioc.Default.GetService<T>() 또는 Ioc.Default.GetRequiredService<T>()로 가져옵니다.
  • App.xaml.cs의 Startup 시점에 등록하고, 전역에서 주입받을 수 있습니다.

 

✔️ 왜 필요한가?

MVVM 구조에서 ViewModel 간 또는 ViewModel → Service 간의 의존성 관계가 생기기 마련입니다. 이를 생성자에서 직접 생성하면 유지보수와 테스트가 어려워지므로 IoC 컨테이너를 통해 객체 생성 및 생명주기 관리를 분리합니다.

 

 

🟢 장점

  • 의존성 분리 → 테스트 용이
  • 싱글턴/스코프/트랜지언트 객체 제어 가능
  • 생성자 주입 및 속성 주입 모두 지원
  • 경량이며 설정이 간편함

 

🔴 단점

 

  • Microsoft.Extensions.DependencyInjection 보다 기능이 제한적
  • DI 패턴에 익숙하지 않으면 초기 이해가 어려움

 

 

 


 


3. 예제1 - IoC 미사용

더보기

✔️ 동작 시나리오

  1. IMessageService는 메시지를 반환하는 인터페이스
  2. 버튼 클릭 시, 메시지 박스에 “IoC를 사용한 메시지입니다” 출력
  3. (참고) 이 예는 IoC 없이 ViewModel 내부에서 서비스 객체를 직접 생성하는 방식을 설명하며,
    강한 결합의 단점과 테스트 어려움을 학습자가 명확히 이해할 수 있도록 구성되었습니다.

 

 


📁 프로젝트 구조

IocDemo/
├── Services/
│   └── IMessageService.cs
│   └── MessageService.cs
├── ViewModels/
│   └── MainViewModel.cs
├── App.xaml.cs
├── MainWindow.xaml
└── MainWindow.xaml.cs

 

 

 

 

✔️  서비스 만들기

public interface IMessageService
{
    string GetMessage();
}
public class MessageService : IMessageService
{
    public string GetMessage()
    {
        return "IoC 없이 직접 생성된 메시지입니다.";
    }
}

 

 

 

 

 ✔️ ViewModel 클래스 만들기 (MainViewModel.cs)

public partial class MainViewModel
{
    private IMessageService _messageService;

    public MainViewModel()
    {
        // 직접 인스턴스 생성 → 강한 결합 (테스트 및 변경시 아래 코드를 직접 수정해야 함)
        _messageService = new MessageService();
    }

    [RelayCommand]
    private void ShowMessage()
    {
        MessageBox.Show(_messageService.GetMessage());
    }
}

 

 

 


✔️ MainWindow 구성

public MainWindow()
{
    InitializeComponent();
    DataContext = new MainViewModel(); // ❌ ViewModel도 직접 생성
}
    Title="IoC 데모" Height="200" Width="300">
<StackPanel Margin="20">
    <Button Content="메시지 보기"
        Command="{Binding ShowMessageCommand}" />
</StackPanel>

 

 

✔️ 결과

  • 항목

 

 

 

 

✔️ 소스코드

  • 아래 IoC 사용 소스코드 파일 사용

 

 

 

 


4. 예제2 - IoC 적용

더보기

✔️ 동작 시나리오

  1. IMessageService는 메시지를 반환하는 인터페이스
  2. 버튼 클릭 시, 메시지 박스에 “IoC를 사용한 메시지입니다” 출력
  3. (참고) 이 예제는, 위 IoC 없이 ViewModel 내부에서 서비스 객체를 직접 생성하는 방식과 비교를 목적으로 합니다.

 

 

 

 

✔️ 패키지 설치

Install-Package CommunityToolkit.Mvvm
Install-Package Microsoft.Extensions.DependencyInjection

 

 

 


📁 프로젝트 구조

IocDemo/
├── Services/
│   └── IMessageService.cs
│   └── MessageService.cs
├── ViewModels/
│   └── MainViewModel.cs
├── App.xaml.cs
├── MainWindow.xaml
└── MainWindow.xaml.cs

 

 

 

 

✔️  서비스 만들기

public interface IMessageService
{
    string GetMessage();
}
public class MessageService : IMessageService
{
    public string GetMessage()
    {
        return "IoC를 통해 생성된 메시지입니다.";
    }
}

 

 

 

 

 ✔️ ViewModel 클래스 만들기 (MainViewModel.cs)

public partial class MainViewModel : ObservableObject
{
    private readonly IMessageService _messageService;

    public MainViewModel(IMessageService messageService)
    {
        _messageService = messageService;
    }

    [RelayCommand]
    private void ShowMessage()
    {
        MessageBox.Show(_messageService.GetMessage());
    }
}

 

 

 


✔️ MainWindow 구성

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            // ViewModel 주입
            DataContext = Ioc.Default.GetRequiredService<MainViewModel>(); 
        }
    }
    Title="IoC 데모" Height="200" Width="300">
<StackPanel Margin="20">
    <Button Content="메시지 보기"
        Command="{Binding ShowMessageCommand}" />
</StackPanel>

 

 

 


✔️ App.xaml.cs 구성

// App.xaml.cs
// 이 파일은 WPF 애플리케이션의 진입점으로, 애플리케이션이 시작될 때 IoC 설정을 초기화합니다.
// CommunityToolkit.Mvvm 패키지의 Ioc.Default를 활용하여 의존성 주입(DI)을 구성합니다.

using CommunityToolkit.Mvvm.DependencyInjection; // MVVM Toolkit에서 제공하는 IoC 컨테이너
using Microsoft.Extensions.DependencyInjection;   // 서비스 등록을 위한 .NET 확장 메서드 제공

public partial class App : Application
{
    // 애플리케이션이 시작될 때 호출되는 메서드
    protected override void OnStartup(StartupEventArgs e)
    {
        // IoC 컨테이너 구성 (의존성 주입 설정)
        // ServiceCollection은 DI를 위한 서비스들을 등록하는 컨테이너입니다.
        Ioc.Default.ConfigureServices(
            new ServiceCollection()

                // 서비스 등록: IMessageService를 요청하면 MessageService 인스턴스를 반환
                .AddSingleton<IMessageService, MessageService>()

                // 뷰모델 등록: MainViewModel도 싱글턴으로 등록하여 어디서든 공유 가능
                .AddSingleton<MainViewModel>()

                // 등록된 서비스들을 기반으로 ServiceProvider 인스턴스를 구성
                .BuildServiceProvider()
        );

        // 반드시 base.OnStartup을 호출하여 WPF 애플리케이션이 정상적으로 시작되도록 함
        base.OnStartup(e);
    }
}

 

 

 

✔️ 결과

  • 항목

 

 

 

 

✔️ 소스코드

WPF_ToolKit11.zip
0.09MB