dagger의 서브그래프의 핵심 subcomponent

이전의 두개의 포스팅을 통해 의존성을 주입하는 여러가지 방법에 대해 알아봤고

 

dagger를 통해서 의존성을 주입하는 방법까지 알아보았다

 

이제 정말로 dagger의 강이 있다면 반은 건너왔다

 

 

여기서부터 고난이 시작될수도 있다

 

최대한 설명을 쉽게 풀어서 써보겠지만 얼만큼이나 전달이 될지 모르겠다

 

그렇지만 우리는 계속 앞으로 나아가야하기에

 

중요한 개념중의하나인 subcomponent를 알아보자

 

 

 

이전의 예제에서 로그인 플로우(LoginActivity에 의해서 관리되는)는 2개의 프래그먼트를 가지고 있다

 

상황에 따라 얼마든지 여러개의 프래그먼트를 사용할수 있다

 

로그인 플로우의 모든 프래그먼트에서 같은 LoginViewModel의 인스턴스를 사용하려고 한다


하지만 그렇다고 @Singleton 어노테이션을 LoginViewModel에서 사용하기는 영 깔끔하지 못하다

 

@Singleton 어노테이션을 붙이면 앱을 사용하는 동안 계속 같은 인스턴스를 전달받게 되는데

 

새로운 로그인 플로우가 시작될때는 다른데이터가 담겨있는 LoginViewModel의 인스턴스를 재활용하는것이 아니라

 

새로운 LoginViewModel을 받고 싶기 때문이다

 

 

 

 

즉 LoginViewModel은 다음과 같은 조건을 필요로 한다


1. LoginViewModel은 로그인 플로우가 끝나면 메모리에서 해제되어야 한다
2. LoginViewModel은 로그아웃이나 다른 상황에 따라 새로운 인스턴스를 사용해야할수도 있다

즉 LoginViewModel은 LoginActivity와 생애주기를 맞추면된다

 

이전 포스팅에서 dagger가 아닌 직접 의존성을 주입하는 방법을 알아보았을때

 

LoginContainer를 만들어서

 

LoginActivity가 onCreate될때 생성하고

 

onDestroy 할때 해지하는것을 해보았다

 

 

 

이제 dagger로 그때 만들었던 LoginContainer를 만드는것을 해볼것이다

 

새로운 component가 필요하다(subgraph라고도 표현할수 있겠다)

 

 

LoginComponent는 ApplicationComponent에 접근할수 있어야한다

 

ApplicationComponent는 많은 의존성을 제공할수 있는데

 

그중 하나가 UserRepository이고


LoginViewModel은 UserRepository에 의존적이기 때문이다


그래서 dagger subcomponent 기능을 사용하게 되는데

 

서브컴포넌트는 부모컴포넌트의 그래프를 상속받기 때문에


서브컴포넌트는 부모컴포넌트의 리소스들을 공유할수 있게 된다

그러므로 부모 컴포넌트에서 제공할수 있는 의존성을 subcomponent도 주입받을수 있다

 

 


@Component 어노테이션을 @Subcomponent로 바꿔주면된다

 

여기서 한가지 더 해야할것이 있다

 

@Comoponent 를 사용할때는 우리가 직접 해당 component의 인스턴스를 생성하는 Factory를 만들어줄필요는 없었는데(물론 그렇게도 할수 있다)

서브컴포넌트는 반드시 부모컴포넌트인 ApplicationComponent가 LoginComponent를 어떻게 만들면되는지 알도록 

 

해야하므로 Factory를 구현해야한다

 

 


그리고 LoginComponent가 ApplicationComponent의 서브컴포넌트인것을 알려줘야 한다

 

 


1. SubcomponentModule을 만들고 서브컴포넌트 클래스를 subcomponents 속성값으로 넣어준다

 

 

2. 만든 모듈을 ApplicationComponent에 추가한다

 

 


이제 더이상 ApplicationComponent는 LoginActivity에 의존성을 직접 주입할 필요가 없어졌다


LoginActivity에 대한 책임은 LoginComponent가 가지고 있다


3. loginComponent를 외부로 노출시켜서 다른곳에서 이것을 가져다쓸수 있게 한다

 

 




프로젝트를 빌드하면 ApplicationComponent와 LoginComponent를 사용할수 있는데

ApplciationComponent는 앱의 생명주기에 맞춰서 메모리에 존재한다

그렇다면 LoginComponent는 어떠한 생명주기를 갖는것이 적절할까

 



LoginActivity의 하위 프래그먼트들에서 같은 LoginViewModel의 인스턴스를 사용해야하고

새로운 로그인 플로우가 시작되었을때는 다시금 LoginViewModel을 새로 생성하게 하기 위해서는

LoginActivity가 바로 LoginComponent의 알맞는 생명주기이다



그래서 우리가 applicationComponent를 application 클래스에 넣었던 것처럼

LoginComponent를 LoginActivity에 참조시켜보자

 

 


LoginComponent는 액티비티의 onCreate()때 생성된다

그리고 이것은 암묵적으로 액티비티가 종료될때 함께 종료될것이다


LoginComponent는 요청할때마다 반드시 같은 LoginViewModel 인스턴스를 제공해야한다

스코프 어노테이션을 LoginComponent와 LoginViewModel에 사용해서 

 

같은 LoginViewModel 인스턴스를 받을수 있도록 보장해야한다

하지만 @Singleton 어노테이션은 이미 부모 컴포넌트에서 사용했기때문에 

 

우리는 다른 이름의 스코프 어노테이션을 만들어야한다


이름을 @LoginScope라고 지어도 좋겠지만, 완벽한방법은 아니다

이런식으로 목적에 맞는 이름을 짓게 되면 향후에

@SignupScope, @SettingsScope와 비슷한 범위의 스코프를 계속해서 만들어야 하기 때문이다

비슷한 스코프 개념을 가지고 있는 다른기능들에서도 이 스코프를 사용하기 위해서

@ActivityScope라고 지어보자

 

 

자 이제 이렇게 함으로서 LoginViewModel을 쓰는 다른 프래그먼트들에도 inject를 할때 같은

LoginViewModel의 인스턴스가 주입되게 되었다

 


같은 @ActivityScope를 가졌기 때문에

dagger를 통해 LoginViewModel을 주입받을때

LoginActivity에서건 LoginUsernameFragment에서건, LoginPasswordFragment에서건

같은 LoginViewModel 인스턴스를 받게 된다

 

 

 

 

대거의 그래프는 이렇게 그려질것이며

하얀점은 unique한 인스턴스임을 나타낸다

 



그래프를 살펴보면

1. NetworkdModule은 ApplicationComponent에 포함되어있다
2. UserRepository는 ApplicationComponent에 남아있고 어디서든지 같은 인스턴스가 공유될것이다
3. LoginViewModel은 LoginComponent에 포함되어있다
LoginComponent에 의해서 주입될것이고 ApplicationComponent에 속해있지 않기 때문에 ApplciationComponent에 의존적이지는 않다

UserRepository는 LoginComponent에도 의존적이게 되었다


서브컴포넌트를 생성하는 것은 각기 어플리케이션의 다른 부분을 캡슐화하는데에 좋은 방법이다

그리고 이렇게 서브컴포넌트로 분리하였기 때문에 확장가능하고, 

 

시작시점에 너무 많은 메모리를 들고 있지 않아도 되므로 성능적인 측면에서도 좋다

 

 

 

@Subcomponent의 설명하는 거의 모든 예제가 mvvm 아키텍쳐의 viewmodel을 가정하여 설명되고 있다

 

물론 mvvm의 viewmodel 개념이 서브컴포넌트를 설명하기에 매우 적합하기도 하다.

 

 

하지만 현 시점에서는 

 

안드로이드가 AAC라고 불리는 안드로이드 아키텍쳐 컴포넌트로서

 

https://developer.android.com/topic/libraries/architecture/viewmodel?hl=ko

 

ViewModel 개요  |  Android 개발자  |  Android Developers

ViewModel을 사용하면 수명 주기를 인식하는 방식으로 UI 데이터를 관리할 수 있습니다.

developer.android.com

viewmodel 기능을 공개했다

 

클래스 수명 주기를 고려하여 UI 관련 데이터를 저장하고 관리할수 있는데 특화된 기능이라고 간단하게 설명할수 있는데

 

우리가 예제를 통해 만들었던 viewmodel의 역할처럼

 

UI를 위한 데이터를 담아두는 역할을 하는 ViewModel 클래스를 제공해준다

 

이 클래스를 통해 UI가 제거되거나 다시 생성되도 UI데이터가 손실되지 않고

 

다시 viewmodel을 통해 가져올수 있도록 설계가 되어있다

 

우리는 이 기능을 이용함으로서 굳이 dagger를 통해 직접 viewmodel의 수명주기를 관리하지 않아도 된다

 

 

하지만 꼭 viewmodel용이 아니더라도 서브컴포넌트는 dagger를 활용함에 있어서 

 

서브 그래프를 그린다는 중요한 개념중의 하나이므로 반드시 기억하고 넘어가도록 하자

| 1 | ··· | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | ··· | 1814 |