Dependency Injection으로 생성자 인자 정리하기 — MVVM과 .NET Host
DI가 객체 생성을 어떻게 단순하게 만드는지, 그리고 MVVM 뷰모델의 길어지는 생성자를 .NET Generic Host로 어떻게 간결하게 유지하는지.
Dependency Injection(DI)은 객체의 생성을 용이하게 한다. 각 객체의 생성자 signature에 맞게 미리 등록된 객체를 찾아 전달하고, 등록된 객체를 찾을 수 없으면 빌드 에러를 발생시킨다.
객체 인스턴스를 만들 때마다 길고 많은 인자를 직접 전달할 필요가 없어, 코드의 가독성을 높이는 데도 도움을 준다.
MVVM에서 빛을 발하는 이유
앱에서 쓰이는 각종 서비스와 데이터베이스는 MVVM 패턴의 거의 모든 뷰모델(ViewModel)에서 사용될 가능성이 높다. 이는 자연스럽게 생성자의 인자 수를 길게 만든다. Hosting 등의 DI를 통해 이를 간결하게 만들 수 있다는 점이 큰 장점이다.
DI 없이 직접 생성하면 이런 식이 된다.
var vm = new MainViewModel(
new UserService(new HttpClient(), logger),
new SettingsService(config),
new AppDbContext(connectionString),
logger,
/* ... */);
서비스를 한 번 등록해 두면, 뷰모델은 필요한 것을 생성자에 선언하기만 하면 된다.
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
var host = Host.CreateDefaultBuilder()
.ConfigureServices((context, services) =>
{
services.AddSingleton<IUserService, UserService>();
services.AddSingleton<ISettingsService, SettingsService>();
services.AddDbContext<AppDbContext>();
services.AddTransient<MainViewModel>();
})
.Build();
// Host가 생성자 인자를 알아서 채워 넣는다
var vm = host.Services.GetRequiredService<MainViewModel>();
public class MainViewModel
{
public MainViewModel(
IUserService userService,
ISettingsService settingsService,
AppDbContext db)
{
// 등록된 인스턴스가 자동으로 주입된다
}
}
생성자 변경에 강하다
DI의 또 다른 이점은 생성자 인자를 바꿀 때 드러난다.
직접 생성자를 호출하는 경우, 인자가 하나 늘면 그 생성자가 쓰인 곳을 전부 찾아 수정해야 한다. DI에서는 Host service가 필요한 객체를 자동으로 전달하므로, 생성자 signature를 바꿔도 호출부를 손댈 필요가 없다. 등록되지 않은 의존성을 요구하면 런타임에 곧바로 드러나므로, 누락도 빠르게 잡힌다.
Enjoy Reading This Article?
Here are some more articles you might like to read next: