Dagger2를 알아보자 – 기본편
Dagger2를 알아보자 – Scope 
Dagger2를 알아보자 – Injection의 종류
Dagger2를 알아보자 – Qualifier
Dagger2를 알아보자 – Binding
Dagger2를 알아보자 – Multibinding
Dagger2를 알아보자 – SubComponent (You’re here)
Dagger2를 알아보자 – Android(준비중)
Dagger2를 알아보자 – Testing(준비중)
Dagger2를 알아보자 – Dynamic Feature에 적용하기(준비중)


Subcomponent

하위 컴포넌트(Subcomponent)는 상위 컴포넌트(Component)의 그래프를 상속하고 확장하는 컴포넌트 입니다. 

특징

  • 그래프를 분할하여 캡슐화 합니다.
  • 상위 컴포넌트를 상속하므로 하위 컴포넌트는 상위 컴포넌트의 객체에 의존할 수 있습니다.
  • 하위 컴포넌트는 상위 컴포넌트와 생명주기를 다르게 가져갈 수 있습니다.
  • 하위 컴포넌트는 또 다른 하위 컴포넌트를 가질 수 있습니다.
    예) ApplicationComponent -> ActivitySubcomponent-> FragmentSubcomponent

Subcomponent를 활용하여 Starbucks 만들기

많은 Dagger2 예제들이 커피머신을 구현하는 예제를 사용합니다. 저는 커피머신 대신 스타벅스라는 앱을 만들어 보겠습니다. (창의성 매우 부족)

먼저 우리가 이미 알고 있는 스타벅스를 상기해보겠습니다. 스타벅스라는 카페가 있고, 그곳에서 일하는 점원이 있습니다. 스타벅스에서는 점원을 파트너(Partner)라고 칭하더군요. 스타벅스를 가서 파트너에게 음료를 주문하면 파트너가 음료를 만들어 줍니다. 파트너는 여러명이 될 수 있고, 같은 파트너가 만든 동일한 메뉴의 음료여도 주문할때마다 서로 다른 음료(다른 인스턴스)가 되어 나와야 합니다. 스타벅스를 방문한 손님 A와 손님 B가 아메리카노를 똑같이 주문했다고 한잔의 아메리카노를 나눠마실순 없으니까요.

자 이제 Starbucks 클래스를 만들어 보도록 하겠습니다

스타벅스 건물을 하나 지은 셈이지요. 스타벅스를 운영하려면 재료가 필요하겠죠.

재료를 제공해주는 모듈을 하나 만들었습니다. 커피콩과 물, 우유를 공급해주는 모듈입니다. 같은 커피콩을 재탕해서 에스프레소는 만드는 일이 없어야하므로 스코프는 지정하지 않습니다. 

Note : Scope가 없으면 요청시 매번 다른 객체를 제공하게 됩니다. 자세한 내용은 Scope편을 참조해주세요.

이 재료를 가지고 음료를 만들게 되겠죠? 

Drink interface를 구현한 음료 Class들을 미리 만들어 두겠습니다.

이제 IngredientModule을 연결할 StarbucksComponent를 만들어보겠습니다.

@Singleton 스코프인 StarbucksComponent를 만들었고, 멤버인젝션을 위한 inject(…)메소드도 만들었습니다. 

이제 아래의 코드를 통해 의존성 주입을 실행해보겠습니다.

재료가 준비되었지만 음료를 만들어줄 파트너가 없으므로 파트너를 고용(?)해보겠습니다.
StarbucksComponent가 상위 컴포넌트가 되고, Partner의 컴포넌트 하위 컴포넌트가 될것입니다.

Partner 컴포넌트를 먼저 만들어보겠습니다

기본적인 구조는 Component와 동일합니다. Scope가 있고, Module을 가집니다. 다른점은 @Subcomponent애노테이션을 사용해야하며, 반드시 명시적으로 @Subcomponent.Builder 또는 @Subcomponent.Factory 구현해야 한다는 점입니다.

PartnerModule.class는 다음과 같이 구현했습니다.

파트너의 ID는 파트너를 고용한 후 해고시킬때까지(?) 동일한 값이여야되므로, @PartnerScope를 붙여 동일한 인스턴스에 의존합니다.

아메리카노, 에스프레소, 라테는 멀티바인딩을 활용했으며, 매번 다른 음료객체를 만들어야하므로 스코프를 지정하지 않았습니다. 

Note: PartnerModule내의 프로비젼 메소드 인자를 살펴보면 Espresso, Water, Milk등을 주입받고 있지만 PartnerComponent 해당 객체를 제공하지 않고 있습니다. 위 객채를 제공받을 수 있는 이유는 상위 컴포넌트인 StarbucksComponent의 오브젝트 그래프내에 해당 객체들이 있기 때문입니다. 

음료객체를 만들기 위한 파트너의 코드는 다음과 같습니다.

생성자에서는 PartnerComponent.Builder를 주입받아 파트너에게 멤버인젝션을 하고, 주입받은 menuMap에서는 음료 클래스를 클래스키로 받아 매번 새로운 음료를 PartnerModule 모듈로부터 제공받습니다.

이제 상위 컴포넌트(StarbucksComponent)와 하위 컴포넌트(PartnerCompent) 연관성을 정의할 차례입니다.하위컴포넌트의 정의는 상위컴포넌트의 모듈에 선언합니다.

먼저 상위 컴포넌트의 모듈로 StarbucksModule을 추가하고 이 모듈에 하위 컴포넌트를 연관짓겠습니다.

모듈 애노테이션의 subcomponents에 PartnerComponent.class를 적용합니다.
이로써 상위-하위 컴포넌트 관계가 형성이 된것입니다.

이를통해 Starbucks모듈내에 Partner객체를 제공하는 프로비젼 메소드의 파라미터로 PartnerComponent.Builder를 받을 수 있게 되었습니다.

이제 다시 Starbucks 클래스로 돌아가보겠습니다.

파트너를 생성 할 Provider<Partner>를 주입받습니다. Provider는 매번 객체를 요청할때 새로운 객체를 제공해줍니다. Provider<Partner>를 통해 두명의 파트너를 만들었습니다.(partner1, partner2)

두 파트너의 Id를 비교하여 동일한 인스턴스인지 확인합니다.

이후 한명의 파트너를 통해 아메리카노를 10잔 요청한 결과가 어떤지 확인해보겠습니다.

10잔의 아메리카노가 생성되는것을 확인할 수 있습니다.

위 예제는 github에서 확인가능합니다.

Buy me a coffeeBuy me a coffee

답글 남기기

이메일은 공개되지 않습니다.