WPF IoC Container 선택

지금까지 IoC Container를 쓰기 시작한 뒤로 쭉 Microsoft.Extensions.DependencyInjection을 사용했습니다.

하지만 이것을 WPF나 Windows Forms 써보신 분들을 아실텐데 AddScoped()를 활용하기가 힘듭니다. 이것은 애초에 Microsoft.Extensions.DependencyInjection가 aspnetcore를 염두하고 만들어졌기 때문이라고 알고 있습니다.

aspnetcore에서 AddScoped를 사용하면 web session 단위로 인스턴스를 관리할 수 있고, 그냥 쓰게 된다면 아래처럼 Scope를 잡아서 쓰게 될 것입니다.

using (IServiceScope scope = serviceProvider.CreateScope()) {
    var singletonService = scope.ServiceProvider.GetService<SingletonOperation>();  
    var scopedService = scope.ServiceProvider.GetService<ScopedOperation>();  
    var transientService = scope.ServiceProvider.GetService<TransientOperation>();  
} 

코드 출처: c# - Dependency injection using Services with Microsoft.Extensions.DependencyInjection library - Stack Overflow

사실 저렇게까지 써본적은 없어서 Windows Desktop Application 단에서 무슨 의미인가 싶기도 합니다.

하여,

혹시 WPF를 쓰실 때 Microsoft.Extensions.DependencyInjection 또는 Microsoft.Extensions.Hosting 을 말고 다른 IoC Container 를 쓰시는 분들 계실까요?

제가 이름이라도 들어본 IoC Container는 아래와 같습니다.

정도입니다.

AutoFac은 사실상 .NET에서 Microsoft.Extensions.DependencyInjection과 비빌 수 있는 가장 거대한 IoC Container라 믿음직스럽고 최근까지도 업데이트가 활발하게 이뤄지고 있습니다.

그 밖에는 DryIoC 는 Prism에서 주로 쓰는 것으로 알고 있고, Simple Injector는 DevExpress에서 Sample Project를 제공받을 때 주로 적용되어 알게 되었고, Ninject는 몇년 전에 반짝 떴던 것 같은데 지금은 업데이트가 안되는 듯하고, Splat은 ReactiveUI 전용이라 RxUI를 안쓰면 적용하기 어려울 것 같습니다.

혹시 WPF에서 사용하기에 적합하고 추천할만한 IoC Container 가 있다면 추천부탁드리겠습니다.


추가로 제가 안 써봐서 모르겠지만 Claude Sonnet 4는 아래와 같이 말해줍니다.

전체 IoC Container 비교표

컨테이너 성능 기능 범위 메모리 사용량 학습 곡선 특징
MS.Extensions.DI 보통 기본 낮음 쉬움 .NET 표준, Generic Host 통합
Autofac 보통 매우 높음 높음 보통 모듈화, 고급 기능이 풍부
DryIoC 매우 높음 높음 매우 낮음 보통 최고 성능, 조건부 등록
Splat 낮음 낮음 낮음 쉬움 ReactiveUI 전용
Ninject 낮음 높음 보통 쉬움 Fluent API, AOP 지원
Simple Injector 높음 높음 낮음 보통 진단 기능, 엄격한 설계
6개의 좋아요

WPF에서 Scope 의 개념 자체가 필요한가요?

웹앱은 기본적으로 요청이 들어와야 뭔가가 돌아가는 앱이라서, 의존성의 생명 주기를 요청 세션으로 한정하는 Scope가 의미가 있습니다.
즉, 요청 세션 동안에는 Singlton 인 것이죠.

그러나, 데스크탑 앱이나 프론트 앱은 세션 개념이 없어서, Scoped 생명 주기가 큰 의미가 없습니다.(제가 아는 한)

앱의 생명 주기(시작 ~ 종료) 동안 Singleton 이냐 Transient 냐의 구분만 중요하죠.

그리고, 아래 코드처럼, 임의의 Scope를 생성하는 것은 특별한 이유가 있지 않는 한 불필요한 복잡성입니다. 실제로, Scoped 로 등록되어 있지만 생명주기는 Transient 와 같(거나 짧)습니다. using 의 범위가 끝나면, Scope 도 사라지고, 생성된 모든 객체도 사라지기 때문입니다.

7개의 좋아요

저같은 경우에도 WPF개발에 DI 컨테이너로 Microsoft.Extensions.DependencyInjection을 사용하고 있고,
Transient만 가지고도 필요한 케이스를 커버 할 수 있어서 Scoped 생명주기는 사용하지 않습니다.

8개의 좋아요

네 그래서 필요없다는 의미로 쓰기 어렵다고 말씀드린 것입니다.
그렇기에 응용 어플리케이션에서 더 적합한 IoC Container가 있는지 여쭤본 글입니다.

말씀하신대로 WPF에서는 Scope와 Singleton이 같기에 저도 Singleton만 사용합니다.

6개의 좋아요

데스크톱 앱을 개발하면서 닷넷 플랫폼 확장(Microsoft.Extensions.DependencyInjection) 외의 IoC 컨테이너를 선택해본 적이 없었던 것 같습니다. Generic Host에 완벽히 통합되고, DI를 달성하기 위한 기본 기능 구현에 충실해 불필요한 러닝 커브도 없습니다.

닷넷 플랫폼 확장을 사용하면서 아쉬울 만한 부분이라면 기본 기능을 넘어선 고급 기능이 필요할 때일 텐데, 닷넷 플랫폼 확장은 확장이 용이하게 설계되어 있기 때문에 대체하지 않고 확장할 수 있는 라이브러리를 적용하면 됩니다. 대표적으로 Scrutor가 있습니다.

닷넷 플랫폼 확장에서 제공하는 DI를 사용하면서 한계가 느껴졌다면, 이러한 닷넷 플랫폼 확장의 확장을 사용해 보는 것도 좋을 것 같습니다.

5개의 좋아요

제 경우는 회사 업무에서는 내부적으로 개발한 컨테이너를 사용합니다만, 회사 밖에서의 개인 프로젝트에서는 Microsoft.Extensions.DependencyInjection를 주로 사용합니다. 뭐랄까 심플해서 좋은 것 같아요. :sweat_smile:

그리고 회사에서 주로 MDI(Multiple-Document Interface) 기반 WPF 응용프로그램을 만들기 때문에, 하나의 Document를 기준으로 Scope를 생성해서 사용하고 있습니다. 해당 Document 안에서만 공유되어야 하는 서비스들이 있어서요…

또 다른 케이스로는, 적절한 예인지는 모르겠지만 SQL Server Management Studio처럼 여러 세션을 관리해야 하는 경우에 Scope를 활용하고 있습니다.

다만 Navigation 기반 응용프로그램일 때는 Scope를 쓸 일이 별로 없었던 것 같습니다. :grinning:

7개의 좋아요

10년 전에 NInejct를 DI용도로만 쓰는 형태로 진행했었습니다. WPF 였기 때문에 성능상의 큰 이점 및 문제는 보이지 않았습니다.
WPF의 개발 패턴에서는 수많은 객체들이 실시간으로 동적 호출되는 상황은 그렇게 많지 않기 때문에 아마도 성능상의 이점을 확인하시기 위해서는 WPF가 아닌 서버류로 확인 하셔야 할것입니다.

4개의 좋아요

WPF에서 DependencyInjection을 사용했을 때 아쉬운 부분에 대해, 시나리오 예를 들어 말씀해주시면 도움되는 답변을 누군가 댓글로 남기지 않을까요? 참고로 .NET 8에서 Key를 사용하는 방식도 추가되었습니다.

3개의 좋아요

제가 질문드렸던 의도는 아쉽다기보단 거슬린다는 맥락이었습니다.
현재 WPF를 주업으로 삼고 있는 저에게 Microsoft.Extensions.DependencyInjection은 AddScoped를 쓰지 못하기에 없어도 되는 기능인 것이죠.

사실 베가본드님께서 좋은 경험공유를 해주셨다고 생각합니다. 하지만 자주있는 경우는 아니고 저는 아직 접한적이 없습니다. 그래서 차라리 AddScoped가 아닌 다른 Windows Desktop Application의 특징을 살린 라이프사이클 옵션이 추가로 존재할 수 있는 Ioc Container가 있으면 좋지 않을까 했던 것입니다.

더불어 닷넷 히어로분들 의견 감사드립니다.

4개의 좋아요

Multi-Window나 Multi-Page 앱을 타겟팅해서 Scoped를 기반으로 Window나 Page에 한정된 수명 범위를 만들 수는 있을 것 같은데, 그러한 경우 DI 라이브러리 자체에서 해결하기 보다는 UI 프레임워크에 종속된 Window, Page 등의 컨트롤을 참조하거나 확장함으로써 이루어질 수밖에 없고, 그러다 보면 개발 방향성이 새로운 IoC 컨테이너 라이브러리가 아닌 UI 프레임워크의 DI 확장형 라이브러리로 향할 수밖에 없을 것 같다는 생각이 드네요.

3개의 좋아요