다음을 통해 공유


종속성 주입

참고 항목

이 전자책은 2017년 봄에 게시되었으며 그 이후로 업데이트되지 않았습니다. 이 책에는 귀중한 기본 많이 있지만 일부 자료는 구식입니다.

일반적으로 클래스 생성자는 개체를 인스턴스화할 때 호출되고 개체에 필요한 모든 값은 생성자에 인수로 전달됩니다. 이는 종속성 주입의 예이며, 특히 생성자 주입이라고 합니다. 개체에 필요한 종속성이 생성자에 주입됩니다.

종속성을 인터페이스 형식으로 지정하면 종속성 주입을 통해 이러한 형식에 종속된 코드에서 구체적인 형식을 분리할 수 있습니다. 일반적으로 인터페이스와 추상 형식 간의 등록 및 매핑 목록을 포함하는 컨테이너와 이러한 형식을 구현하거나 확장하는 구체적인 형식을 사용합니다.

속성 setter 삽입 및 메서드 호출 주입과 같은 다른 유형의 종속성 주입도 있지만 일반적으로 볼 수는 없습니다. 따라서 이 장에서는 종속성 주입 컨테이너를 사용하여 생성자 주입을 수행하는 데만 집중합니다.

종속성 주입 소개

종속성 주입은 IoC(Inversion of Control) 패턴의 특수 버전으로, 반전과 관련된 고려 사항은 필요한 종속성을 얻는 프로세스입니다. 종속성 주입을 사용하면 다른 클래스가 런타임에 개체에 종속성을 주입합니다. 다음 코드 예제에서는 종속성 주입을 사용할 때 ProfileViewModel 클래스를 구성하는 방법을 보여 줍니다.

public class ProfileViewModel : ViewModelBase  
{  
    private IOrderService _orderService;  

    public ProfileViewModel(IOrderService orderService)  
    {  
        _orderService = orderService;  
    }  
    ...  
}

ProfileViewModel 생성자는 다른 클래스에 IOrderService 의해 삽입된 인수로 인스턴스를 받습니다. 클래스의 ProfileViewModel 유일한 종속성은 인터페이스 형식에 있습니다. 따라서 클래스에는 ProfileViewModel 개체 인스턴스화를 담당하는 클래스에 대한 지식이 IOrderService 없습니다. 개체를 인스턴스화 IOrderService 하고 클래스에 ProfileViewModel 삽입하는 클래스를 종속성 주입 컨테이너라고 합니다.

종속성 주입 컨테이너는 클래스 인스턴스를 인스턴스화하고 컨테이너의 구성에 따라 수명을 관리하는 기능을 제공하여 개체 간의 결합을 줄입니다. 개체를 만드는 동안 컨테이너는 개체에 필요한 모든 종속성을 삽입합니다. 해당 종속성이 아직 만들어지지 않은 경우 컨테이너는 먼저 해당 종속성을 만들고 확인합니다.

참고 항목

팩터리를 사용하여 종속성 주입을 수동으로 구현할 수도 있습니다. 그러나 컨테이너를 사용하면 수명 관리 및 어셈블리 검색을 통한 등록과 같은 추가 기능이 제공됩니다.

종속성 주입 컨테이너를 사용하는 경우 다음과 같은 몇 가지 이점이 있습니다.

  • 컨테이너는 클래스가 종속성을 찾고 수명을 관리할 필요가 없습니다.
  • 컨테이너를 사용하면 클래스에 영향을 주지 않고 구현된 종속성을 매핑할 수 있습니다.
  • 컨테이너는 종속성을 모의로 만들 수 있도록 하여 테스트를 용이하게 합니다.
  • 컨테이너는 새 클래스를 앱에 쉽게 추가할 수 있도록 하여 유지 관리 가능성을 높입니다.

MVVM을 Xamarin.Forms 사용하는 앱의 컨텍스트에서 종속성 주입 컨테이너는 일반적으로 뷰 모델을 등록 및 확인하고 서비스를 등록하고 보기 모델에 삽입하는 데 사용됩니다.

많은 종속성 주입 컨테이너를 사용할 수 있으며, eShopOnContainers 모바일 앱은 TinyIoC를 사용하여 앱에서 보기 모델 및 서비스 클래스의 인스턴스화를 관리합니다. TinyIoC는 다양한 컨테이너를 평가한 후 선택되었으며, 잘 알려진 대부분의 컨테이너와 비교할 때 모바일 플랫폼에서 뛰어난 성능을 제공합니다. 느슨하게 결합된 앱을 쉽게 빌드할 수 있으며, 형식 매핑을 등록하고, 개체를 확인하고, 개체 수명을 관리하고, 종속 개체를 확인하는 개체 생성자에 삽입하는 메서드를 포함하여 종속성 주입 컨테이너에서 일반적으로 발견되는 모든 기능을 제공합니다. TinyIoC에 대한 자세한 내용은 github.com TinyIoC를 참조하세요.

TinyIoC에서 이 형식은 TinyIoCContainer 종속성 주입 컨테이너를 제공합니다. 그림 3-1은 개체를 인스턴스화 IOrderService 하고 클래스에 삽입하는 이 컨테이너를 사용할 때의 ProfileViewModel 종속성을 보여 줍니다.

Dependencies example when using dependency injection

그림 3-1: 종속성 주입을 사용하는 경우의 종속성

런타임에 컨테이너는 개체를 인스턴스화하기 전에 인스턴스화해야 하는 인터페이스의 IOrderService 구현을 ProfileViewModel 알고 있어야 합니다. 여기에는 다음이 포함됩니다.

  • 인터페이스를 구현하는 개체를 인스턴스화하는 방법을 결정하는 컨테이너입니다 IOrderService . 이것을 등록이라고 합니다.
  • 인터페이스를 구현하는 개체와 ProfileViewModel 개체를 IOrderService 인스턴스화하는 컨테이너입니다. 이것을 ‘확인’이라고 합니다.

결국 앱은 개체 사용을 ProfileViewModel 완료하고 가비지 수집에 사용할 수 있게 됩니다. 이 시점에서 다른 클래스가 동일한 인스턴스를 IOrderService 공유하지 않는 경우 가비지 수집기는 인스턴스를 삭제해야 합니다.

컨테이너에 구애받지 않은 코드를 작성합니다. 항상 컨테이너에 구애받지 않는 코드를 작성하여 사용 중인 특정 종속성 컨테이너에서 앱을 분리합니다.

등록

종속성을 개체에 주입하려면 먼저 종속성 유형을 컨테이너에 등록해야 합니다. 형식을 등록하려면 일반적으로 컨테이너에 인터페이스와 인터페이스를 구현하는 구체적인 형식을 전달해야 합니다.

코드를 통해 컨테이너에 형식 및 개체를 등록하는 방법에는 다음 두 가지가 있습니다.

  • 컨테이너에 형식 또는 매핑을 등록합니다. 필요한 경우 컨테이너는 지정된 형식의 인스턴스를 빌드합니다.
  • 컨테이너의 기존 개체를 싱글톤으로 등록합니다. 필요한 경우 컨테이너는 기존 개체에 대한 참조를 반환합니다.

종속성 주입 컨테이너가 항상 적합한 것은 아닙니다. 종속성 주입은 작은 앱에 적절하거나 유용하지 않을 수 있는 추가 복잡성 및 요구 사항을 발생합니다. 클래스에 종속성이 없거나 다른 형식에 대한 종속성이 없는 경우 컨테이너에 배치하는 것은 적절하지 않을 수 있습니다. 또한 형식에 필수적인 단일 종속성 집합이 클래스에 있고 변경될 가능성이 없으면 컨테이너에 배치하는 것이 부적절할 수 있습니다.

종속성 주입이 필요한 형식의 등록은 앱의 단일 메서드에서 수행되어야 하며, 앱이 해당 클래스 간의 종속성을 인식할 수 있도록 앱의 수명 주기 초기에 이 메서드를 호출해야 합니다. eShopOnContainers 모바일 앱에서 개체를 빌드 TinyIoCContainer 하고 해당 개체에 대한 참조를 보유하는 앱의 유일한 클래스인 클래스에 의해 ViewModelLocator 수행됩니다. 다음 코드 예제에서는 eShopOnContainers 모바일 앱이 클래스에서 ViewModelLocator 개체를 선언하는 TinyIoCContainer 방법을 보여 줍니다.

private static TinyIoCContainer _container;

형식은 생성자에 ViewModelLocator 등록됩니다. 이 작업은 먼저 다음 코드 예제에 설명된 인스턴스를 만들어 TinyIoCContainer 수행합니다.

_container = new TinyIoCContainer();

그런 다음 형식이 개체에 TinyIoCContainer 등록되고 다음 코드 예제에서는 가장 일반적인 형식 등록 형식을 보여 줍니다.

_container.Register<IRequestProvider, RequestProvider>();

여기에 표시된 메서드는 Register 인터페이스 형식을 구체적인 형식에 매핑합니다. 기본적으로 각 인터페이스 등록은 모든 종속 개체가 동일한 공유 인스턴스를 받도록 싱글톤으로 구성됩니다. 따라서 단일 RequestProvider 인스턴스만 컨테이너에 존재하며, 이 인스턴스는 통과 생성자를 삽입해야 하는 개체에서 IRequestProvider 공유됩니다.

다음 코드 예제와 같이 인터페이스 형식의 매핑 없이 구체적인 형식을 직접 등록할 수도 있습니다.

_container.Register<ProfileViewModel>();

기본적으로 각 구체적인 클래스 등록은 모든 종속 개체가 새 인스턴스를 받도록 다중 인스턴스로 구성됩니다. 따라서 ProfileViewModel 확인되면 새 인스턴스가 만들어지고 컨테이너가 필요한 종속성을 삽입합니다.

해결

형식을 등록한 후에는 종속성으로 확인하거나 주입할 수 있습니다. 형식이 확인되고 컨테이너가 새 인스턴스를 만들어야 하는 경우 인스턴스에 종속성을 삽입합니다.

일반적으로 형식이 확인되면 다음 세 가지 중 하나가 발생합니다.

  1. 형식이 등록되지 않은 경우 컨테이너는 예외를 throw합니다.
  2. 형식이 싱글톤으로 등록된 경우 컨테이너는 싱글톤 인스턴스를 반환합니다. 형식이 처음 호출되는 경우 컨테이너는 필요한 경우 형식을 만들고 기본 이에 대한 참조를 가져옵니다.
  3. 형식이 싱글톤으로 등록되지 않은 경우 컨테이너는 새 인스턴스를 반환하고 기본 참조를 얻지 않습니다.

다음 코드 예제에서는 이전에 TinyIoC에 RequestProvider 등록된 형식을 확인할 수 있는 방법을 보여 줍니다.

var requestProvider = _container.Resolve<IRequestProvider>();

이 예제에서 TinyIoC는 종속성과 함께 형식에 대한 구체적인 형식을 IRequestProvider 확인하라는 요청을 받습니다. 일반적으로 Resolve 메서드는 특정 형식의 인스턴스가 필요할 때 호출됩니다. 확인된 개체의 수명을 제어하는 방법에 대한 자세한 내용은 확인된 개체의 수명 관리를 참조 하세요.

다음 코드 예제에서는 eShopOnContainers 모바일 앱이 보기 모델 유형 및 해당 종속성을 인스턴스화하는 방법을 보여 있습니다.

var viewModel = _container.Resolve(viewModelType);

이 예제에서 TinyIoC는 요청된 뷰 모델에 대한 뷰 모델 유형을 확인하라는 메시지가 표시되고 컨테이너는 모든 종속성도 확인합니다. 형식을 ProfileViewModel 확인할 때 확인할 종속성은 개체 및 개체입니다 ISettingsServiceIOrderService . 인터페이스 등록은 클래스 및 OrderService 클래스를 등록할 SettingsService 때 사용되었으므로 TinyIoC는 클래스 및 OrderService 클래스에 대한 SettingsService 싱글톤 인스턴스를 반환한 다음 클래스의 ProfileViewModel 생성자에 전달합니다. eShopOnContainers 모바일 앱이 보기 모델을 생성하고 뷰에 연결하는 방법에 대한 자세한 내용은 보기 모델 로케이터를 사용하여 보기 모델 자동 만들기를 참조하세요.

참고 항목

컨테이너를 사용하여 형식을 등록하고 확인하는 경우, 특히 앱의 각 페이지 탐색에 대한 종속성을 다시 생성하는 경우 컨테이너의 리플렉션 사용으로 인해 성능비용이 발생합니다. 종속성이 많거나 깊은 경우에는 생성 비용이 많이 증가할 수 있습니다.

확인된 개체의 수명 관리

구체적인 클래스 등록을 사용하여 형식을 등록한 후 TinyIoC의 기본 동작은 형식이 확인될 때마다 또는 종속성 메커니즘이 인스턴스를 다른 클래스에 삽입할 때마다 등록된 형식의 새 인스턴스를 만드는 것입니다. 이 시나리오에서는 컨테이너에 확인된 개체에 대한 참조가 없습니다. 그러나 인터페이스 등록을 사용하여 형식을 등록할 때 TinyIoC의 기본 동작은 개체의 수명을 싱글톤으로 관리하는 것입니다. 따라서 인스턴스는 컨테이너가 범위에 있는 동안 범위에 다시 기본 컨테이너가 범위를 벗어나고 가비지 수집되거나 코드가 컨테이너를 명시적으로 삭제할 때 삭제됩니다.

흐름 AsSingletonAsMultiInstance API 메서드를 사용하여 기본 TinyIoC 등록 동작을 재정의할 수 있습니다. 예를 들어 메서드를 AsSingleton 메서드와 함께 Register 사용하면 컨테이너가 메서드를 호출할 때 형식의 싱글톤 인스턴스를 만들거나 반환할 Resolve 수 있습니다. 다음 코드 예제에서는 TinyIoC가 클래스의 싱글톤 인스턴스를 만들도록 지시하는 방법을 보여 줍니다 LoginViewModel .

_container.Register<LoginViewModel>().AsSingleton();

형식이 LoginViewModel 처음 확인되면 컨테이너는 새 LoginViewModel 개체를 만들고 해당 개체에 대한 참조를 기본. 이후의 LoginViewModel해결 방법에서 컨테이너는 이전에 만든 개체에 대한 참조를 LoginViewModel 반환합니다.

참고 항목

단일 항목으로 등록된 형식은 컨테이너가 삭제될 때 삭제됩니다.

요약

종속성 주입을 사용하면 이러한 형식에 종속된 코드에서 구체적인 형식을 분리할 수 있습니다. 일반적으로 인터페이스와 추상 형식 간의 등록 및 매핑 목록을 포함하는 컨테이너와 이러한 형식을 구현하거나 확장하는 구체적인 형식을 사용합니다.

TinyIoC는 잘 알려진 대부분의 컨테이너와 비교할 때 모바일 플랫폼에서 뛰어난 성능을 제공하는 경량 컨테이너입니다. 느슨하게 결합된 앱을 쉽게 빌드할 수 있으며, 형식 매핑을 등록하고, 개체를 확인하고, 개체 수명을 관리하고, 종속 개체를 확인하는 개체 생성자에 삽입하는 메서드를 포함하여 종속성 주입 컨테이너에서 일반적으로 발견되는 모든 기능을 제공합니다.