3. Android 에서 Dagger로 DI 적용하기
Clean Software/Dependency Injection

3. Android 에서 Dagger로 DI 적용하기

728x90
반응형

Application에 Dagger 컴포넌트(그래프) 만들기 @Component

Android에서 개발자는 앱이 실행되는 동안

Dagger 그래프 인스턴스가 계속 메모리에 있기를 원하기 때문에

일반적으로 Application 클래스에 Dagger 그래프를 만듭니다.

이렇게 하면 그래프는 앱 수명 주기 전체에 연결됩니다.

 

Dagger 그래프를 생성하는 인터페이스는 @Component로 어노테이션 하여 

ApplicationComponent 또는 ApplicationGraph로 호출할 수 있습니다.

 

일반적으로 다음 코드에서와 같이 Application 클래스에 컴포넌트의 인스턴스를 정의하고

Application 그래프가 필요할 때마다 인스턴스를 호출합니다.

// 애플리케이션 그래프의 정의
@Component
interface ApplicationComponent { ... }
class MyApplication: Application() {

    // 전체 앱에서 사용되는 애플리케이션 그래프에 대한 참조
    // appComponent는 수명 주기를 공유하기 위해 Application 클래스에 상주합니다.
    val appComponent = DaggerApplicationComponent.create()
}

 

만든 Dagger 컴포넌트를 통해 Activity에 종속항목 주입 @Inject

Activity 및 프래그먼트와 같은 특정 Android 프레임워크 클래스는

시스템에 의해 인스턴스화되기 때문에 Dagger가 이 클래스를 자동으로 생성할 수 없습니다.

즉, 클래스 생성자(생성자 삽입)에서 @Inject 어노테이션을 사용할 수 없습니다.

대신 필드 삽입을 사용해야 합니다.

 

onCreate() 메서드에서 수동으로 Activity에 필요한 종속 항목을 생성해도 되지만,

@Inject 어노테이션을 사용하여 필드 삽입 방법으로 
Dagger가 자동으로 종속 항목을 채우도록 구현해 봅시다.

Activity에 필요한 종속 항목인 ViewModel을 제공하기 위해

ApplicationComponent에 액세스해야 한다는 것을 Dagger에게 알리기 위해

LoginActivity(삽입을 요청하는 객체)를 매개변수로 갖는
inject()함수를 구현합니다.
@Component
interface ApplicationComponent {
    // 이는 LoginActivity가 삽입을 요청하므로 그래프가 LoginActivity가 요청하는 필드의 모든 종속성을 충족해야 함을 Dagger에 알려줍니다.
    fun inject(activity: LoginActivity)     // private이면 안됨
}
Activity에서 객체를 삽입하려면 
Application 클래스에 정의된 appComponent를 사용하고 
삽입할 객체를 매개변수로 갖는 inject() 메서드를 호출하여
삽입을 요청하는 Activity의 인스턴스를 전달합니다.
class LoginActivity: Activity() {
    // Dagger가 그래프에서 LoginViewModel의 인스턴스를 제공하기를 원합니다.
    @Inject lateinit var loginViewModel: LoginViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        // Dagger가 LoginActivity에서 @Inject 필드를 인스턴스화하도록 합니다.
        (applicationContext as MyApplication).appComponent.inject(this)
        // 이제 loginViewModel을 사용할 수 있습니다.

        super.onCreate(savedInstanceState)
    }
}
더보기

삽입을 요청하는 클래스가 여러 개 있다면 컴포넌트의 모든 클래스를 정확한 유형으로 명시적으로 선언해야 합니다. 예를 들어 삽입을 요청하는 LoginActivity  RegistrationActivity가 있다면 두 경우를 모두 포괄하는 일반 메서드 하나를 호출하는 대신 두 개의 inject() 메서드를 호출합니다. 일반 inject() 메서드는 제공해야 할 항목을 Dagger에 알리지 않습니다. 인터페이스의 함수는 임의의 이름을 가질 수 있지만 매개변수로 삽입할 객체를 받을 때 inject()로 호출하는 것은 Dagger의 규칙입니다.

 

Activity을 사용할 때 프래그먼트 복원 관련 문제를 방지하기 위해 super.onCreate()를 호출하기 전에 활동의 onCreate() 메서드에서 Dagger를 삽입합니다. super.onCreate()의 복원 단계 중에 활동은 활동 결합에 액세스하려고 할 수 있는 프래그먼트를 연결합니다.

프래그먼트를 사용할 때 프래그먼트의 onAttach() 메서드에서 Dagger를 삽입합니다. 이 경우 super.onAttach()를 호출하기 전이나 후에 삽입할 수 있습니다.

전체 그래프를 빌드하기 위해

나머지 종속 항목을 제공하는 방법을 Dagger에 알려야 합니다.
// @Inject는 Dagger에게 LoginViewModel 인스턴스 생성 방법을 알려줍니다.
class LoginViewModel @Inject constructor(
    private val userRepository: UserRepository
) { ... }
class UserRepository @Inject constructor(
    private val localDataSource: UserLocalDataSource,
    private val remoteDataSource: UserRemoteDataSource
) { ... }
class UserLocalDataSource @Inject constructor() { ... }
class UserRemoteDataSource @Inject constructor(
    private val loginService: LoginRetrofitService
) { ... }

모듈 include @Module

인스턴스화가 아닌 빌더를 통해 인스턴스를 생성하는 Retrofit 네트워킹 라이브러리를 사용할 경우

종속성을 어떻게 처리해야 하는지 살펴봅시다. 

UserRemoteDataSource에는 LoginRetrofitService 종속 항목이 있습니다.

그러나 LoginRetrofitService의 인스턴스를 생성하는 방법은 지금까지 해왔던 것과는 다릅니다. 그것은 클래스 인스턴스화가 아니며, Retrofit.Builder()를 호출하고 다양한 매개변수를 전달하여 로그인 서비스를 구성한 결과입니다.

 

@Inject 어노테이션 외에도
@Module어노테이션으로 만드는 모듈 클래스를 통해
클래스의 인스턴스를 제공하는 방법을 Dagger에 알리는 또 다른 방법이 있습니다.
@Provides 어노테이션을 사용하여 종속 항목을 정의할 수 있습니다.

 

모듈은 객체를 제공하는 방식에 관한 정보를 의미론적으로 캡슐화하는 방법입니다.

이 예에서는 네트워킹 관련 객체를 제공하는 로직을 그룹화하기 위해 NetworkModule라는 클래스 구현했습니다. 애플리케이션이 확장되면 여기서 OkHttpClient를 제공하는 방법이나 Gson 또는 Moshi를 구성하는 방법을 추가할 수도 있습니다.

// @Module은 이 클래스가 Dagger 모듈임을 Dagger에 알립니다.
@Module
class NetworkModule {

    // @Provides는 Dagger에게 이 함수가 반환하는 유형(예: LoginRetrofitService)의 인스턴스를 생성하는 방법을 알려줍니다.
    // 함수 매개변수는 이 유형의 종속성입니다.
    @Provides
    fun provideLoginRetrofitService(): LoginRetrofitService {
        // Dagger가 LoginRetrofitService 유형의 인스턴스를 제공해야 할 때마다 이 코드(@Provides 메서드 내부의 코드)가 실행됩니다.
        return Retrofit.Builder()
                .baseUrl("https://example.com")
                .build()
                .create(LoginService::class.java)
    }
}
더보기

 @Provides 메서드의 종속 항목은 이 메서드의 매개변수입니다. 이전 메서드의 경우 메서드에 매개변수가 없으므로 LoginRetrofitService에 종속 항목이 제공되지 않을 수 있습니다. OkHttpClient를 매개변수로 선언했다면 Dagger는 LoginRetrofitService의 종속 항목을 충족하기 위해 그래프로부터 OkHttpClient 인스턴스를 제공해야 합니다. 예를 들면 다음과 같습니다.

@Module
class NetworkModule {
    // LoginRetrofitService에 대한 가상 종속성
    @Provides
    fun provideLoginRetrofitService(
        okHttpClient: OkHttpClient
    ): LoginRetrofitService { ... }
}

 

Dagger 그래프가 이 모듈에 관해 알 수 있도록 하려면 다음과 같이 @Component 인터페이스에 모듈을 추가해야 합니다.

// @Component 어노테이션의 "modules" 속성은 그래프를 작성할 때 포함할 모듈을 Dagger에 알려줍니다.
@Component(modules = [NetworkModule::class])
interface ApplicationComponent {
    ...
}

 


중간 정리..

Dagger 그래프에 유형을 추가하는 권장 방법은 생성자 삽입을 사용하는 것입니다(즉, 클래스의 생성자에 @Inject 어노테이션 사용). 때로 이 방법은 불가능하며, Dagger 모듈을 사용해야 합니다. 예를 들어 Dagger가 계산 결과를 사용하여 객체의 인스턴스를 생성하는 방법을 결정하도록 하려는 때에는 Dagger 모듈을 사용해야 합니다. 동일한 유형의 인스턴스를 제공해야 할 때마다 Dagger는 @Provides 메서드 내에서 코드를 실행합니다.

다음은 예시의 Dagger 그래프가 현재 표시되는 모습입니다.

그래프의 진입점은 LoginActivity입니다. LoginActivity는 LoginViewModel을 삽입하기 때문에 Dagger는 LoginViewModel 및 종속 항목의 인스턴스를 반복적으로 제공하는 방법을 알고 있는 그래프를 빌드합니다. Dagger는 클래스 생성자의 @Inject 어노테이션으로 인해 이 실행 방법을 알고 있습니다.

Dagger가 생성한 ApplicationComponent 내에는 제공 방법을 알고 있는 모든 클래스의 인스턴스를 가져오는 팩토리 유형 메서드가 있습니다. 이 예에서 Dagger는 ApplicationComponent에 포함된 NetworkModule에 위임하여 LoginRetrofitService의 인스턴스를 얻습니다.

 

범위 지정 @Scope

Dagger 기본사항 페이지에서 범위는 컴포넌트에서 유형의 고유한 인스턴스을 갖는 방법으로 언급되어 있습니다. 즉 유형의 범위를 구성 요소의 수명 주기로 지정한다는 의미 입니다.

앱의 다른 기능에서 UserRepository를 사용하려고 하지만 필요할 때마다 새 객체를 생성하고 싶지 않을 수 있으므로 이 객체를 전체 앱에 고유한 인스턴스로 지정할 수 있습니다. 이는 LoginRetrofitService도 마찬가지입니다. 생성 비용이 많이 들 수 있으므로 이 객체의 고유한 인스턴스를 재사용할 수 있습니다. UserRemoteDataSource의 인스턴스 생성은 그렇게 비용이 많이 들지 않으므로 컴포넌트의 수명 주기로 객체 범위를 지정할 필요는 없습니다.

@Singleton은 javax.inject 패키지와 함께 제공되는 고유한 범위 어노테이션입니다. 이 어노테이션을 사용하여 ApplicationComponent 및 전체 애플리케이션에서 재사용하려는 객체에 어노테이션을 달 수 있습니다.

@Singleton
@Component(modules = [NetworkModule::class])
interface ApplicationComponent {
    fun inject(activity: LoginActivity)
}

@Singleton
class UserRepository @Inject constructor(
    private val localDataSource: UserLocalDataSource,
    private val remoteDataSource: UserRemoteDataSource
) { ... }

@Module
class NetworkModule {
    // Way to scope types inside a Dagger Module
    @Singleton
    @Provides
    fun provideLoginRetrofitService(): LoginRetrofitService { ... }
}

객체에 범위를 적용할 때 메모리 누수가 발생하지 않도록 주의하세요. 범위가 지정된 컴포넌트가 메모리에 있는 한 생성된 객체도 메모리에 있습니다. ApplicationComponent는 앱이 시작될 때(Application 클래스에서) 생성되므로 앱이 소멸되면 소멸됩니다. 따라서 UserRepository의 고유한 인스턴스는 애플리케이션이 소멸될 때까지 메모리에 항상 남아 있습니다.

 

하위 컴포넌트 만들기 (Login Component)

로그인 흐름(단일 LoginActivity로 관리)이 여러 프래그먼트로 구성되어 있다면 모든 프래그먼트에서 동일한 LoginViewModel 인스턴스를 재사용해야 합니다. @Singleton은 다음과 같은 이유로 LoginViewModel에 어노테이션을 지정하여 인스턴스를 재사용할 수 없습니다.

  1. 흐름이 완료된 후 LoginViewModel 인스턴스는 메모리에 지속됩니다.
  2. 로그인 흐름마다 다른 LoginViewModel 인스턴스를 원합니다. 예를 들어 사용자가 로그아웃하면 사용자가 처음 로그인했을 때와 동일한 인스턴스가 아닌 다른 LoginViewModel 인스턴스를 원합니다.

LoginViewModel의 범위를 LoginActivity의 수명 주기로 지정하려면 로그인 흐름의 새 컴포넌트(새 하위 그래프) 및 새 범위를 생성해야 합니다.

로그인 흐름과 관련된 그래프를 만들어 보겠습니다.

LoginComponent를 만들고 삽입을 구현해야 합니다.
이렇게 하면 ApplicationComponent 클래스에서 LoginActivity를 삽입하지 않아도 됩니다.
// @Subcomponent 주석은 Dagger에게 이 인터페이스가 Dagger 하위 구성요소임을 알립니다.
@Subcomponent
interface LoginComponent {

    // 이는 LoginActivity가 LoginComponent에서 주입을 요청하여 이 하위 구성 요소 그래프가 LoginActivity가 주입하는 필드의 모든 종속성을 충족해야 함을 Dagger에 알려줍니다.
    fun inject(loginActivity: LoginActivity)
}

LoginViewModel은 UserRepository에 종속되므로 LoginComponent는 ApplicationComponent의 객체에 액세스할 수 있어야 합니다. 새 컴포넌트가 다른 컴포넌트의 일부를 사용하도록 Dagger에 알리는 방법은 Dagger 하위 컴포넌트를 사용하는 것입니다. 새 컴포넌트는 공유 리소스가 포함된 컴포넌트의 하위 컴포넌트여야 합니다.

하위 컴포넌트는 상위 컴포넌트의 객체 그래프를 상속 및 확장하는 컴포넌트입니다. 따라서 상위 컴포넌트에 제공된 모든 객체는 하위 컴포넌트에도 제공됩니다. 이러한 방식으로 하위 컴포넌트의 객체는 상위 컴포넌트에서 제공하는 객체에 종속될 수 있습니다.

하위 컴포넌트의 인스턴스를 생성하려면 상위 컴포넌트의 인스턴스가 필요합니다. 따라서 상위 컴포넌트가 하위 컴포넌트에 제공하는 객체는 여전히 상위 컴포넌트로 범위가 지정됩니다.

다음 예에서는 LoginComponent를 ApplicationComponent의 하위 컴포넌트로 정의해야 합니다. 이렇게 하려면 LoginComponent에 @Subcomponent로 어노테이션을 지정합니다.

또한 ApplicationComponent가 LoginComponent의 인스턴스를 생성하는 방법을 알 수 있도록 LoginComponent 내에 하위 컴포넌트 팩토리를 정의해야 합니다.
@Subcomponent
interface LoginComponent {

    // 이 하위 컴포넌트의 인스턴스를 만드는 데 사용되는 팩토리
    @Subcomponent.Factory
    interface Factory {
        fun create(): LoginComponent
    }
    
    fun inject(loginActivity: LoginActivity)
}

 

다음은 LoginComponent가 ApplicationComponent의 하위 컴포넌트임을 Dagger에 알리기 위한 구현 방법입니다.

  1. 하위 컴포넌트의 클래스를 어노테이션 subcomponents 속성에 전달하는 새로운 Dagger 모듈(예: SubcomponentsModule)을 만듭니다.

// @Module 어노테이션의 "subcomponents" 속성은 이 모듈이 포함된 컴포넌트의 하위 컴포넌트가 무엇인지 Dagger에 알려줍니다.
@Module(subcomponents = LoginComponent::class)
class SubcomponentsModule {}

  2. 다음과 같이 새 모듈(즉, SubcomponentsModule)을 ApplicationComponent에 추가합니다.

객체 주입책임은 이제 LoginComponent에 속하기 때문에 ApplicationComponent는 LoginActivity를 더 이상 삽입할 필요가 없으므로 ApplicationComponent에서 inject() 메서드를 삭제할 수 있습니다. ApplicationComponent의 사용자는 LoginComponent 인스턴스를 생성하는 방법을 알아야 합니다. 상위 컴포넌트는 소비자가 상위 컴포넌트의 인스턴스에서 하위 구컴포넌트의 인스턴스를 만들 수 있도록 인터페이스에 메서드를 추가해야 합니다.

  3. 다음과 같이 인터페이스에서 LoginComponent 인스턴스를 생성하는 팩토리를 노출합니다.

// SubcomponentsModule을 포함하여 ApplicationComponent에 LoginComponent가 하위 컴포넌트임을 알립니다.
@Singleton
@Component(modules = [NetworkModule::class, SubcomponentsModule::class])
interface ApplicationComponent {
      // 이 함수는 소비자가 LoginComponent의 새 인스턴스를 얻는 데 사용할 수 있도록 LoginComponent Factory를 그래프 외부에 노출합니다.
      fun loginComponent(): LoginComponent.Factory
}

 

하위 컴포넌트에 범위 할당

프로젝트를 빌드하면 ApplicationComponent  LoginComponent의 인스턴스를 모두 생성할 수 있습니다. 애플리케이션이 메모리에 있는 한 동일한 그래프 인스턴스를 사용하려고 하므로 ApplicationComponent는 애플리케이션의 수명 주기에 연결됩니다.

LoginComponent의 수명 주기는 무엇인가요? LoginComponent가 필요한 이유 중 하나는 로그인 관련 프래그먼트 간에 동일한 LoginViewModel 인스턴스를 공유해야 하기 때문입니다. 그러나 새 로그인 흐름이 있을 때마다 다른 LoginViewModel 인스턴스도 원합니다. LoginActivity는 LoginComponent의 적절한 전체 기간입니다. 모든 새 활동에는 LoginComponent의 새 인스턴스와 이 LoginComponent 인스턴스를 사용할 수 있는 프래그먼트가 필요합니다.

LoginComponent는 LoginActivity 수명 주기에 연결되어 있으므로 Application 클래스의 applicationComponent 참조를 유지한 것과 동일한 방식으로 활동의 컴포넌트 참조를 유지해야 합니다. 그렇게 하면 프래그먼트가 참조에 액세스할 수 있습니다.

 

Dagger에서 loginComponent 변수를 제공할 것으로 예상되지 않으므로 이 변수에는 @Inject로 어노테이션이 지정되지 않습니다.

ApplicationComponent를 사용하여 LoginComponent 참조를 가져온 후 다음과 같이 LoginActivity를 삽입할 수 있습니다.

class LoginActivity: Activity() {
    
    // 로그인 그래프에 대한 참조
    lateinit var loginComponent: LoginComponent

    // 로그인 그래프에서 삽입해야 하는 필드
    @Inject lateinit var loginViewModel: LoginViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        // 애플리케이션 그래프를 이용한 로그인 그래프 생성
        loginComponent = (applicationContext as MyDaggerApplication)
                            .appComponent.loginComponent().create()

        // Dagger가 LoginActivity에서 @Inject 필드를 인스턴스화하도록 합니다.
        loginComponent.inject(this)

        // 이제 loginViewModel을 사용할 수 있습니다.

        super.onCreate(savedInstanceState)
    }
}

LoginComponent는 활동의 onCreate() 메서드에서 생성되며 활동이 폐기되면 암시적으로 폐기됩니다.

LoginComponent는 요청될 때마다 항상 동일한 LoginViewModel 인스턴스를 제공해야 합니다. 이렇게 하려면 맞춤 어노테이션 범위를 생성하고 LoginComponent와 LoginViewModel에 모두 그 범위로 어노테이션을 지정해야 합니다. @Singleton어노테이션은 상위 컴포넌트에서 이미 사용하고 있으며 객체를 애플리케이션 싱글톤(전체 앱의 고유 인스턴스)으로 만들었기 때문에 사용할 수 없습니다. 따라서 다른 어노테이션 범위를 생성해야 합니다.

이 경우 이 범위를 @LoginScope로 호출했을 수 있지만 이는 권장되지 않습니다. 범위 어노테이션의 이름은 이행하는 목적에 관해 명시적이어서는 안 됩니다. 대신 어노테이션 RegistrationComponent  SettingsComponent와 같은 동위 컴포넌트에 의해 재사용될 수 있으므로 범위 어노테이션은 전체 기간에 따라 이름을 지정해야 합니다. 이러한 이유로 @LoginScope 대신 @ActivityScope로 호출해야 합니다.

// Definition of a custom scope called ActivityScope
@Scope
@Retention(value = AnnotationRetention.RUNTIME)
annotation class ActivityScope

// Classes annotated with @ActivityScope are scoped to the graph and the same
// instance of that type is provided every time the type is requested.
@ActivityScope
@Subcomponent
interface LoginComponent { ... }

// A unique instance of LoginViewModel is provided in Components
// annotated with @ActivityScope
@ActivityScope
class LoginViewModel @Inject constructor(
    private val userRepository: UserRepository
) { ... }

이제 LoginViewModel이 필요한 두 개의 프래그먼트가 있다면 두 프래그먼트 모두 동일한 인스턴스와 함께 제공됩니다. 예를 들어 LoginUsernameFragment  LoginPasswordFragment가 있다면 둘 다 LoginComponent에 의해 삽입되어야 합니다.

@ActivityScope
@Subcomponent
interface LoginComponent {

    @Subcomponent.Factory
    interface Factory {
        fun create(): LoginComponent
    }

    // All LoginActivity, LoginUsernameFragment and LoginPasswordFragment
    // request injection from LoginComponent. The graph needs to satisfy
    // all the dependencies of the fields those classes are injecting
    fun inject(loginActivity: LoginActivity)
    fun inject(usernameFragment: LoginUsernameFragment)
    fun inject(passwordFragment: LoginPasswordFragment)
}

컴포넌트 LoginActivity 객체에 존재하는 컴포넌트의 인스턴스에 액세스합니다. LoginUserNameFragment의 예시 코드는 다음 코드 스니펫에 나와 있습니다.

class LoginUsernameFragment: Fragment() {

    // Fields that need to be injected by the login graph
    @Inject lateinit var loginViewModel: LoginViewModel

    override fun onAttach(context: Context) {
        super.onAttach(context)

        // Obtaining the login graph from LoginActivity and instantiate
        // the @Inject fields with objects from the graph
        (activity as LoginActivity).loginComponent.inject(this)

        // Now you can access loginViewModel here and onCreateView too
        // (shared instance with the Activity and the other Fragment)
    }
}

그리고 LoginPasswordFragment의 예시 코드는 다음 코드 스니펫에 나와 있습니다.

class LoginPasswordFragment: Fragment() {

    // Fields that need to be injected by the login graph
    @Inject lateinit var loginViewModel: LoginViewModel

    override fun onAttach(context: Context) {
        super.onAttach(context)

        (activity as LoginActivity).loginComponent.inject(this)

        // Now you can access loginViewModel here and onCreateView too
        // (shared instance with the Activity and the other Fragment)
    }
}

그림 3은 Dagger 그래프가 새 하위 컴포넌트와 함께 어떻게 표시되는지 보여줍니다. 흰색 점이 있는 클래스(UserRepository, LoginRetrofitService  LoginViewModel)는 고유한 인스턴스의 범위가 각각의 컴포넌트로 지정된 클래스입니다.

그래프의 요소를 분석해 보겠습니다.

  1. NetworkModule(따라서 LoginRetrofitService)은 컴포넌트에서 지정되었기 때문에 ApplicationComponent에 포함됩니다.
  2. UserRepository는 ApplicationComponent로 범위가 지정되었으므로 ApplicationComponent에 남아 있습니다. 프로젝트가 커지면 다른 기능(예: 등록)에서 동일한 인스턴스를 공유하려고 합니다.
  3. UserRepository는 ApplicationComponent의 일부이므로 UserRepository의 인스턴스를 제공할 수 있으려면 종속 항목(즉, UserLocalDataSource  UserRemoteDataSource)도 이 컴포넌트에 있어야 합니다.
  4. LoginViewModel은 LoginComponent에서 삽입한 클래스에만 필요하므로 LoginComponent에 포함되어 있습니다. ApplicationComponent의 종속 항목은 LoginViewModel이 필요하지 않으므로 LoginViewModel은 ApplicationComponent에 포함되어 있지 않습니다.
  5. 마찬가지로 UserRepository의 범위를 ApplicationComponent로 지정하지 않았다면 Dagger는 UserRepository 및 종속 항목을 LoginComponent의 일부로 자동으로 포함합니다. 이 컴포넌트가 현재 UserRepository가 사용되는 유일한 위치이기 때문입니다.

객체의 범위를 다양한 수명 주기로 지정하는 것 외에도 하위 컴포넌트를 생성하는 것은 애플리케이션의 다양한 요소를 서로 캡슐화하는 좋은 방법입니다.

앱의 흐름에 따라 다양한 Dagger 하위 그래프를 생성하도록 앱을 구성하면 메모리 및 시작 시간 측면에서 더욱 성능이 뛰어나고 확장성이 탁월한 애플리케이션을 만들 수 있습니다.

728x90
반응형