11. IServiceProvider - Ioc(제어 반전)
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 미사용
더보기





✔️ 동작 시나리오
- IMessageService는 메시지를 반환하는 인터페이스
- 버튼 클릭 시, 메시지 박스에 “IoC를 사용한 메시지입니다” 출력
- (참고) 이 예는 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 적용
더보기






✔️ 동작 시나리오
- IMessageService는 메시지를 반환하는 인터페이스
- 버튼 클릭 시, 메시지 박스에 “IoC를 사용한 메시지입니다” 출력
- (참고) 이 예제는, 위 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