Dagger Hilt

summerdewyes·2021년 12월 4일
0
post-thumbnail

Dagger Hilt가 뭐야?

Dagger Hilt는 의존성 주입을 위해 사용하는 Android Jetpack의 라이브러리로 자동으로 수명주기를 관리해요.

정리

결합도를 줄이고 좀 더 유연한 코드를 작성하기 위해 사용하는 Android Jetpack의 라이브러리에요.


Hilt 셋업을 위해 필수적으로 요구되는 과정

Hilt Application

  • Hilt를 사용하는 모든 앱에는 @HiltAndroidApp 어노테이션이 있는 Application 클래스가 존재해야 해요.
  • @HiltAndroidApp 은 컴파일 시 표준 컴포넌트 빌딩에 필요한 클래스들을 초기화해요.
@HiltAndroidApp
class BaseApplication: Application() { ... }

정리

Hilt를 사용하기 위해 필요한 클래스들을 초기화하기 위해서는 @HiltAndroidApp 어노테이션이 있는 Application 클래스가 필수에요.


Android 클래스에 의존성을 주입하는 방법

@AndroidEntryPoint

  • Hilt@AndroidEntryPoint 어노테이션이 있는 Android 클래스에 의존성을 주입할 수 있어요.
  • @AndroidEntryPoint를 이용하여 Android 클래스에 어노테이션을 달아주었다면, 해당 클래스에 종속된 Android 클래스에도 어노테이션을 추가해주어야해요.
  • @AndroidEntryPoint는 프로젝트의 Android 클래스에 대해 개별적인 Hilt 컴포넌트를 생성해요. 이러한 Hilt 컴포넌트는 상위 클래스로부터 의존성 주입을 받을 수 있어요.

Android 클래스용으로 생성된 컴포넌트

  • Hilt 컴포넌트는 해당 Android 클래스에 바인딩을 주입하는 역할을 해요.
  • HiltSingletonComponent로부터 바로 BroadcastReceiver를 주입하기 때문에 BroadcastReceiver에 대해서는 컴포넌트를 생성하지 않아요.

@Inject

  • 컴포넌트로부터 의존성 객체 주입을 요청하려면 @Inject를 사용해야해요.
  • Hilt에 의해 주입된 필드가 private일 경우에는 컴파일 에러가 발생하니 주의해야해요.
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {

      @Inject 
      lateinit var runDAO: RunDAO
      ...
}

정리

Android 클래스에 의존성을 주입하기 위해서는 해당 클래스마다 @AndroidEntryPoint 어노테이션을 달고, @Inject 어노테이션으로 객체 주입을 요청해야 해요.


컴포넌트에서 필요한 인스턴스를 제공하는 방법 (constructor injection)

Hilt binding

  • 바인딩은 인스턴스를 제공하는데에 필수적인 정보를 포함해요.
  • Hilt에 바인딩 정보를 제공하기 위해서 constructor injection을 사용해요
  • 예를 들어 아래 코드에서 MainViewModelmainRepository 의존성으로 지니므로, HiltmainRepository가 인스턴스를 어떻게 제공하는지에 대해 반드시 알고있어야 하는 거예요.
class MainViewModel @Inject constructor(
    val mainRepository: MainRepository
) { ... }

컴포넌트 생명주기 = 인스턴스 생명주기

  • Hilt생성된 컴포넌트 클래스의 인스턴스를 해당 Android 클래스의 생명주기에 따라 자동으로 생성하고 파괴해요.

컴포넌트 Scope

  • 기본적으로 Hilt의 모든 바인딩은 Scope가 지정되지 않으며, 앱에서 바인딩을 요청할 때마다 Hilt는 필요한 유형의 새로운 인스턴스를 만들어요.
  • Hilt의 바인딩을 특정 컴포넌트 Scope로 지정할 경우, 바인딩 범위가 지정된 컴포넌트의 인스턴스당 한 번만 Scope 바인딩을 생성하고 해당 바인딩에 대한 모든 요청은 동일한 인스턴스를 공유해요.

정리

인스턴스 정보를 제공하기 위해서는 constructor injection을 사용하는데요, Hilt는 Android 클래스의 생명주기에 따라 인스턴스를 자동으로 관리해줘요.


Hilt에 특정 타입의 인스턴스를 제공하는 방법 (constructor injection 사용 불가)

@Module

  • 인터페이스, 외부 라이브러리의 클래스 등 특정 타입이라서 constructor injection이 불가능 할 때, @Module 을 만들어 바인딩 정보를 Hilt에 제공할 수 있어요.
  • @InstallIn 어노테이션을 사용하여 어떤 컴포넌트에 모듈을 설치할지 반드시 정해주어야해요.
  • Hilt module에서 제공하는 의존성은 Hilt module을 설치하는 Android 클래스와 연결된 모든 컴포넌트에서 사용할 수 있어요.

컴포넌트 계층

  • 컴포넌트에 모듈을 생성하면 컴포넌트 계층에 따라 해당 컴포넌트 또는 하위 컴포넌트의 바인딩이 종속됨으로서 해당 컴포넌트의 바인딩에 접근할 수 있어요.

인터페이스 인스턴스 주입 (@Binds)

  • Hilt module 내의 @Binds 어노테이션을 이용하여 추상 함수를 만들어 바인딩 객체와 함께 Hilt를 제공할 수 있어요.
  • 함수의 리턴타입은 함수가 인스턴스를 제공하는 인터페이스를 Hilt에 알려줘요.
  • 함수의 파라미터는 Hilt가 인터페이스의 인스턴스를 필요로 할 때 어떤 implementation을 제공해야할지 Hilt에 알려줘요.

외부 라이브러리 클래스 인스턴스 주입 (@Provides)

  • Retrofit, Room 등 외부 라이브러리 클래스 인스턴스를 주입하기 위해서는 Hilt module 내부에 함수를 만들고 해당 함수를 @Provides 어노테이션으로 처리하여 타입 인스턴스를 제공하는 방법을 Hilt에 알릴 수 있어요.
  • 함수의 리턴타입은 함수가 인스턴스를 제공하는 타입을 Hilt에 알려줘요.
  • 함수의 파라미터는 타입의 dependencies를 Hilt에 알려줘요.
  • 함수의 바디는 타입의 인스턴스를 제공하는 방법을 Hilt에 알려줘요.
  • 타입의 인스턴스를 제공할 필요가 있을 때마다 Hilt는 함수의 바디를 실행한다.
@Module
@InstallIn(SingletonComponent::class)
object AppModule {

      @Singleton
      @Provides
      fun provideRunningDatabase(@ApplicationContext app: Context) =
          Room.databaseBuilder(app, RunningDatabase::class.java,
          RUNNING_DATABASE_NAME
      ).build()
    
      @Singleton
      @Provides
      fun provideRunDao(db: RunningDatabase) = db.getRunDao()
}

정리

constructor injection이 불가능할 때는 @Module을 만들어 @InstallIn 어노테이션으로 설치할 컴포넌트를 정하고 바인딩 정보를 제공해요.
인터페이스는 @Binds 어노테이션을, 외부 라이브러리 클래스는 @Provides 어노테이션을 사용해요.


참고&출처

Android: Hilt
Dagger Hilt로 안드로이드 의존성 주입 시작하기

0개의 댓글