Hilt에 대해 알아보자.

이영훈·2022년 8월 1일
0

Hilt?

→ Android에서 DI를 위한 라이브러리이다. Android의 Activity, Fragment 등 주요 component 들에서 사용할 의존성 객체를 관리해준다. Android 용으로 만들어서 선배 DI 라이브러리인 Dagger보다 훨씬 쓰기 쉽다.

DI?

→ 의존성 주입(Dependency Injection)! 특정 a 클래스의 객체가 필요할 때 사용처에서 직접 생성하는 것 보다 전달 받는것이 테스트에도 용이하고 보일러 플레이트 코드를 줄일 수 있고 객체 생성에 필요한 조건이 변경됐을 때 편하게 대응이 가능하다.

Hilt가 Dagger를 기반으로 만들어졌고, 더 편하고, 요즘(2022.07.28 기준) Android 씬에서 DI가 아주 핫한 디자인 패턴이며 hilt가 Android DI에 필수적인 라이브러리이다.

대충 이정도만 짚고 넘어가자.

시작!


일단 dependency 추가 먼저 해주자


// gradle(project)
buildscript {
    dependencies {
        classpath 'com.google.dagger:hilt-android-gradle-plugin:2.42'
    }
}

// gradle(app)
plugins {
    id 'dagger.hilt.android.plugin'
    id 'kotlin-kapt'
}
dependencies {
    implementation "com.google.dagger:hilt-android:2.42"
    kapt "com.google.dagger:hilt-android-compiler:2.42"
}

@HiltAndroidApp 추가

@HiltAndroidApp
class MyApplication : MultiDexApplication() {...}

@HiltAndroidApp 어노테이션이 모든 작업의 시작점이다. Hilt를 사용하는 모든 앱은 이 어노테이션을 추가한 Application class를 정의해야 한다. @HiltAndroidApp이 Application의 생명주기를 참고하여 컴파일 타임 때 필요한 클래스들을 초기화 해주고 의존성 객체를 제공한다.

시작이 반이니 벌써 절반 했다.

@AndroidEntryPoint

이제 의존성을 주입 받아 보쟈. Hilt는 Application, Activity, Fragment, Service, View, BroadcastReceiver, ViewModel 컴포넌트들에 의존성 주입을 도와준다.

Application Class와 마찬가지로 클래스 상단에 어노테이션을 추가해주자.

@AndroidEntryPoint
class MainActivity : AppCompatActivity() {...}

프래그먼트에 지정하면 프래그먼트가 띄워진 액티비티에도 달아주어야 한다.

Module

의존성 주입 방식에 2가지 경우가 있다.
참고: https://f2janyway.github.io/android/hilt/

  1. constructor inject할 수 있는 클래스

    -> 내가 구현한 클래스

  2. constructor inject할 수 없는 클래스

    -> 인터페이스 or abstract class 구현체(@Module 사용)
    -> 내가 구현할 수 없는 클래스(3rd party library)(@Module 사용)

constructor inject 가능??


class DateFormatter @Inject constructor() {
    ...
}

class의 constructor에 @Inject 붙여준다, 초간단

constructor inject 불가능??

인스턴스 주입을 위한 모듈을 만들어보자!

@Module
@InstallIn(SingletonComponent::class)
object NetworkModule {

    @Singleton
    @Provides
    fun provideOkHttpClient(): OkHttpClient {...}

어쩌고 저쩌고 구글링 해보면 죄다 Dagger의 개념과 함께 설명하느라 말을 너무 어렵게 한다.(내 기준 ㅎ)

Dagger를 알면 좋겠지만 나중에 하는것으로 하고… 쉽게쉽게 알아보자

@Module은 컴포넌트에 의존성을 제공하는 역할을 한다. 모듈 클래스 내에 선언되는 메서드에 @Provides 를 붙여 컴파일 타임에 의존성을 제공하는 프로바이더를 생성한다. (긍까 간단히 Hilt에게 해당 의존성을 주입하는 방법을 알려준다.)

더 간단히!! @Module은 의존성을 제공하는 클래스에 붙이고, @Provides는 의존성을 제공하는 메소드에 붙인다!

@Provides 는 외부 라이브러리 처럼 클래스를 직접 소유하지 않아서 인스턴스 생성 방법을 모르는 경우 지정해준다.

@Binds → Abstract인 경우 사용

@Installin은 간단히 해당 모듈을 Hilt 표준 컴포넌트들 중 어떤 컴포넌트에 설치할 것인지 결정한다.

간단히!! 해당 모듈에 접근할 수 있는 범위를 지정한다! 컴포넌트들은 밑에 정리.

Component 계층

Dagger에서는 컴포넌트를 직접 정의했어야 하나 보다. Hilt는 제공해주는 위의 컴포넌트들을 편하게 쓰면 된다~

모듈의 Installin에서 지정한 컴포넌트의 스코프와 모듈 내에서 제공되는 인스턴스들의 scope는 동일해야한다. (ex @Installin(ActivitiyComponent.class) 로 설정했으면 해당 모듈의 메소드들의 scope도 다 @ActivityScoped 로 지정해줘야 함.)

따로 scope를 지정하지 않으면 주입이 일어날 때 마다 인스턴스를 생성하고, GC에 의해 삭제됨.

scope를 달아주면 해당 scope에 맞게 create, destroy됨.

이제 의존성 주입을 받자!

@AndroidEntryPoint
class ChangePasswordFragment : Fragment() {
    private lateinit var binding: FragmentChangePasswordBinding
    
    @Inject
    lateinit var userRepository: UserRepository

@AndroidEntryPoint 를 붙인 곳에서 @Inject 를 통해 의존성 주입 받는다, 초간단

@HiltViewModel

Dagger에서는 기존에 ViewModelProvider를 이용해 직접 뷰모델 inject를 위해 multi 어쩌고 저쩌고를 활용해 직접 구현해줬어야 했는데 이 과정을 @HiltViewModel 이 자동으로 자~알 어디다가 만들어주고 뷰모델 사용처에서 viewModels 확장 함수를 통해 간단히 뷰모델의 의존성을 주입 받을 수 있다.

더 자세한 디테일들은 알아서 찾아보시길……….

마치며..

Hilt에 대해 더 자세히 이해하기 위해서는 Dagger를 이해하는것이 필요하겠지만 (공부하기 시렁)

일단은 이정도만 이해해도 Hilt를 사용하는데에는 지장 없을 듯 싶다.

Component와 Scope를 정할 때 신경을 쓰는것이 중요하다고 생각된다.

끝!

profile
And dev

2개의 댓글

comment-user-thumbnail
2022년 8월 8일

간단하게 잘 정리하셨네요! 나중에는 적용기도 보여주세요!!

1개의 답글