이전엔 DI로 Hilt를 사용했었는데, 좀 더 심화해서 Dagger2를 파보려구 한다.
Hilt는 Dagger2를 쉽게 사용하기 위해 만들어진 것이기 때문에, 다양성과 성능면에서 Dagger가 더 앞서고 Hilt는 에러가 생긴 경험이 많다는 얘기를 듣고 Dagger2를 공부해둘 필요가 있다고 느꼈다.
Injection 주입을 하기 위한 가장 기본적인 요소인 컨테이너가 있는데,
이 컨테이너는 외부에서 클래스의 인스턴스를 생성하는 공간이다.
이러한 컨테이너를 Component라고 부른다.
모듈은 클래스의 인스턴스들을 모아둔 공간인데, Component에 의존성을 제공한다.
Hilt에서와 같이 컴포넌트를 모듈단위로 관리하게된다.
프로바이더는 인스턴스를 제공(Provide)하는 역할을 한다.
interface UserRepository {
fun getUserInfo(): String
}
class UserRepositoryImpl : UserRepository {
override fun getUserInfo(): String = "User info from repository"
}
유저의 정보를 제공하는 레포지토리를 간략화해서 만들었다.
@Module
class AppModule {
@Provides
fun provideUserRepository(): UserRepository = UserRepositoryImpl()
}
이제 레포 지토리들을 모아둔 모듈을 구성한다.
모듈에서 Dagger2에게 의존성 객체를 생성하는 방법을 알려주고 @Provides를 이용해 실제 인스턴스 생성 로직을 구현한다.
provideUserRepository 메서드는 UserRepository의 구현체인 UserRepositoryImpl의 인스턴스를 생성해 반환한다.
Hilt와 차이점이 여기서 바로 컴퍼넌트를 넣어주지 않는다.
class UserManager @Inject constructor(
private val userRepository: UserRepository
) {
fun getUserInfo(): String = userRepository.getUserInfo()
}
레포지토리를 받는 유즈 케이스를 정의해주고
@Component(modules = [AppModule::class])
interface AppComponent {
fun getUserManager(): UserManager
}
유즈 케이스를 인터페이스로 묶어주고 여기서 Component를 설정해준다.
AppComponent는 AppModule을 포함하며, getUserManager 메서드를 통해 UserManager의 인스턴스를 제공한다.
fun main() {
val appComponent: AppComponent = DaggerAppComponent.create()
val userManager: UserManager = appComponent.getUserManager()
println(userManager.getUserInfo())
}
메인에선 AppComponent를 생성하고 이를통해 UserManager의 인스턴스를 얻는다.
Hilt와의 차이점이 보이는데
모듈위에서 컴포넌트를 정해준 Hilt랑 달리, 직접 컴포넌트를 정의하고 관리해야 한다.
AppComponent와 같은 컴포넌트 인터페이스를 작성하고, 필요한 모듈을 modules 속성에 등록하는 등의 작업을 직접 수행해야하기 때문에 좀 복잡해졌다.
확실히 Hilt와 비교해 좀 복잡해지고 있는 듯하다...
천천히 익혀가야지