ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Hilt 관련 리펙토링 기록 (@binds @Provides 차이 , UsecaseModule)
    Android & Kotlin 2023. 1. 8. 15:39

    구조설명 (클린 아키텍처)

    1. 클린아키텍처 구조에서 Hilt 를 통해 의존성 주입을 사용하고 있었다.
    2. 이때 Repository (Interface) 의 주입을 위해 RepoisotyModule 을 만들어 사용했고 @Provides 를 사용해왔었다.
    3. 그리고 Usecase 에서 Ropository 와 ErrorHandler 에 의존했고 이에 따라 각각 UsecaseModule, NetowrkModule 을 정의해주어 사용했다.

    class GetSomeUseCase(
        private val repository: Repository,
        private val errorHandler: ErrorHandler
    ) : BaseUseCase() {...}
    
    
        @ErrorHandler
        @Provides
        @Singleton
        fun provideErrorHandler(
            @HttpClient http: OkHttpClient,
            appStorage: AppStorage
        ): ErrorHandler =
            NetErrorHandlerImpl(
                http.retrofit(appStorage.getBackBaseUrl())
            )
    
    
        @Provides
        @ViewModelScoped
        fun provideGetSomeUseCase(
            repo: Repository,
            @ErrorHandler errorHandler: ErrorHandler
        ) = CheckUsedAddressUseCase(repo, errorHandler)
    
        @Provides
        @Singleton
        fun provideRepository(
            apiSevice: Apiservice
        ): Repository =
            RepositoryImpl(apiSevice)

     

     

     

    @provides 와 @Binds 차이

    외부적으로 기능적 차이를 보이지 않지만 사용법에 차이에서 비록한 차이가 존재한다.

     

    1. @Binds / @povides 를 통한 주입 방법 정의 차이

    @Module
    @InstallIn(SingletonComponent::class)
    abstract class RepositoryModule {
    
        @Binds
        @Singleton
        abstract fun bindRepository(
            repository: RepositoryImpl
        ): Repository
    
    
    @Module  
    @InstallIn(SingletonComponent::class)  
    object RepositoryModule {
    
    
    @Provides
    @Singleton
    fun provideRepository(
        apiSevice: ApiService
    ): Repository =
        RepositoryImpl(apiSevice)

     

    2. 객체 주입시 사용 방법의 차이

    • @binds 의 경우 @Inject constructor 를 붙여줌으로써 해당 부분에서의 의존성 주입을 명시해주고 @provids 의 경우 그렇지 않고 모듈에서 찾아 주입해주게된다.

    이런 제약으로 인해 @binds 는 서드파티 라이브러리에 대한 의존성 주입이 불가하기에 해당 경우엔 @provids 를 사용할 수 밖에 없다.

     

    또 아래와 같이 usecaseModule 의 필요성 유무를 결정 짓기도하다. usecase 에서 인터페이스인 Repo 를 의존할 경우 @provids 의 경우 @Inject 키워드를 붙이기 않기때문에 모듈을 반드시 필요로 하지만 @binds 의 경우 @Inject 를 통해 usecase 모듈을 생성을 하지 않아도 된다.

     

    그렇다면 @Provids 로 주입 객체를 정의하고 @Inject constructor 를 붙여준다면 usecaseModule 없이 동작할 수 있을까?

    실험결과 이것 또한 가능 했다.

    
    class GetSomeUseCase @Inject constructor(
    private val Repository: Repository,
    @ErrorHandler private val errorHandler: ErrorHandler
    ) : BaseUseCase() {
    fun execute() =
    Repository.getSomeUseCase()
    .toNetResult(errorHandler)
    }

    (@binds 를 통한 객체 생성후 주입의 경우 usecaseModule 불필요)

    @Provides
    @ViewModelScoped
    fun provideGetSomeUseCase(
        repo: Repository,
        @ErrorHandler errorHandler: ErrorHandler
    ) =
        GetSomeUseCase(repo, errorHandler)
    
    
    
    class GetSomeUseCase(
    private val Repository: Repository,
    private val errorHandler: ErrorHandler
    
    ) : BaseUseCase() {

    (@provids 의 경우 @Inject Constutor 없을 경우 usecaseModule 필요)

    댓글

Designed by Tistory.