Android

Hilt

YOONJELLY 2023. 12. 5. 14:46

 

옥수환 - Hilt와 함께 하는 안드로이드 의존성 주입을 보고 작성했습니다.


 

의존성 주입

생성자 또는 메서드 등을 통해 외부로부터 생성된 객체를 전달받는 것


 

의존성 주입의 특징

- 클래스 간 결합도를 느슨하게 함

- 인터페이스 기반으로 설계, 코드를 유연하게 함

- Stub 또는 Mock 객체를 사용하여 단위테스트를 하기가 더욱 쉬워짐


 

안드로이드에서 의존성 주입 어려운 이유?

- Android 클래스가 Framework에 의해 인스턴스화 됨 ( -> 클래스들 내부에 개발자가 직접 생성자를 만들거나 생성자의 매개변수를 전달할 수 있는 방법이 없음)


 

의존성 주입 프레임워크의 궁극적인 목표

- 정확한 사용방법을 제안

- 쉬운 설정 방법

- 중요한 것들에 집중할 수 있도록 함


 

Hilt

애플리케이션에서 DI를 사용하는 표준적인 방법을 제공

Hilt의 목표

- Dagger 사용의 단순화

- 표준화된 컴포넌트 세트와 스코프로 설정과 가독성/이해도 쉽게 만들기

- 쉬운 방법으로 다양한 빌드 타입에 대해 다른 바인딩 제공


 

Hilt 프로젝트 설정 for Kotlin

 

// 안드로이드 Gradle 모듈 build.gradle 파일

apply plugin: 'com.android.application'
apply plugin: 'dagger.hilt.android.plugin'

android {...}

dependencies {
	implementation 'com.google.dagger:hilt-android:<VERSION>'
    kapt 'com.google.dagger:hilt-android-compiler:<VERSION>'
}

 

Hilt Gradle Plugin 설정

// 프로젝트 최상위 build.gradle 파일
buildscript {
	repositories {
    	mavenCentral()
    }
    dependencies {
    	classpath 'com.google.dagger:hilt-android-grale-plugin:<version>'
	}
}

 

버전은 Hilt 공식 홈페이지에서 확인할 수 있습니다.


 

Hilt의 특징

- Dagger2 기반의 라이브러리

- 표준화된 Dagger2 사용법을 제시

- 보일러플레이트 코드 감소

- 프로젝트 설정 간소화

- 쉬운 모듈 탐색과 통합

- 개선된 테스트 환경


 

주요 Hilt Annotation

- @HiltAndroidApp

- @AndroidEntryPoint

- @InstallIn

- @EntryPoint


 

@HiltAndroidApp 없이 컴포넌트 생성하기

class MemoApplication : Application() {

	override fun onCreate() {
    	super.onCreate()
        val component = DaggerMemoComponent.builder()
        	...
        	.build()
    	component.inject(this)
    }
}

 

 

@HiltAndroidApp을 통해 컴포넌트 생성하기

@HiltAndroidApp
class MemoApplication : Application() {
	
    override fun onCreate() {
    	super.onCreate() // 의존성 주입은 여기서 이뤄짐 (bytecode 변환)
    }
}

 


 

@AndroidEntryPoint를 지원하는 타입

- Activity

- Fragment

- View

- Service

- BroadcastReceiver


 

Bytecode transformation


 

Hilt Module

@InstallIn : Hilt가 생성하는 DI 컨테이너에 어떤 모듈을 사용할 지 가리킴

- 하위 컴포넌트는 상위 컴포넌트의 의존성에 엑세스할 수 있으므로, 양 컴포넌트에 모두 주입하고 싶을 경우 상위 컴포넌트에 어노테이션을 달면 됨.

- @Module 클래스에 @InstallIn이 없으면 컴파일 에러

 

@EntryPoint

- Hilt가 지원하지 않는 클래스에서 의존성이 필요한 경우 사용

(예 : Contentprovider, DFM, Dagger를 사용하지 않는 3rd-party 라이브러리 등)

- @EntryPoint는 인터페이스에서만 사용

- @InstallIn이 반드시 함께 있어야 함 (컴포넌트를 선언해주고 사용)

- EntryPoints 클래스의 정적 메서드를 통해 그래프에 접근

 


 

Custom Component

표준 Hilt 컴포넌트 이외에 새로운 컴포넌트를 만드는 것

커스텀 컴포넌트를 사용하면 복잡하고 이해하기 어려워지기 때문에 꼭 필요한 경우에만 사용

 

사용하는 Annotation

- @DefineComponent

- @DefineComponent.Builder

 

제약 조건

- 반드시 ApplicationComponent의 하위 계층의 컴포넌트로 만들어야 함

- 표준 컴포넌트 계층 사이에 추가할 수 없음