[Android] DI, Hilt

안세홍·2024년 11월 4일
post-thumbnail

저는 이번 블로그 포스팅은 그 동안의 피드백 부분을 가지고 다시 한번 정리하면서 기록해볼까 합니다.

사실 이해가 잘 되지 않았습니다.. (그래서 공부하면서 정리하겠다고 했습니다..)

그렇다면 의존성 주입이란 무엇일까..?

한 클래스는 종종 다른 클래스를 참조합니다. 예를 들면, Car라는 클래스는 Engine이라는 클래스를 참조하고 있습니다. 이렇게 클래스를 필요로하는 것을 의존성(dependency)이라고 합니다. (저도 이해할 수 있는) 좋은 예제가 있어서 들고 와봤습니다!

class Car {
    private val engine = Engine()
    fun start() {
        engine.start()
    }
}
fun main(args: Array) {
    val car = Car()
    car.start()
}

위처럼 코드를 작성하면 CarEngine 의 결합이 강해지고 재사용성이 떨어지게 됩니다. 아래는 의존성 주입을 이용해서 수정한 코드입니다.

class Car(private val engine: Engine) {
    fun start() {
        engine.start()
    }
}
fun main(args: Array) {
    val engine = Engine()
    val car = Car(engine)
    car.start()
}

위 코드는 Engine 객체를 main 에서 생성하고 Car 생성자에게 전달하게 됩니다.

이를 통해 재사용성이 좋아지고 테스트 작성이 용이해집니다.

간단하게 의존성 주입에 대해서 이해했으니

여기서 Hilt 란 무엇인가?

Hilt는 Android 앱 개발에 사용되는 의존성 주입(Dependency Injection, DI) 라이브러리입니다. 의존성 주입을 통해 객체 간의 결합도를 낮추고, 코드의 재사용성 및 유지보수성을 향상시킬 수 있습니다. Hilt는 Google에서 제공하며, Dagger를 기반으로 하고 있어서 Dagger의 강력한 기능을 좀 더 쉽게 사용할 수 있도록 도와줍니다.

주요 특징

  1. 자동화된 의존성 관리: Hilt는 컴파일 타임에 의존성을 처리하여, 실행 시간에 발생할 수 있는 오류를 최소화합니다.
  2. 표준화된 설정: Hilt를 사용하면 Android 애플리케이션의 표준적인 구조에 맞게 의존성을 설정할 수 있으며, 이는 앱 전체에서 일관된 방식으로 의존성을 관리할 수 있게 해줍니다.
  3. 쉬운 통합: Hilt는 Android Jetpack과 긴밀하게 통합되어 있어서, 생명주기나 다른 Jetpack 기능들과의 호환성을 자연스럽게 제공합니다.

사용 방법

Hilt를 사용하기 위해서는 먼저 의존성을 Gradle 파일에 추가하고, 애플리케이션 클래스에 @HiltAndroidApp 어노테이션을 적용해야 합니다. 이 어노테이션은 Hilt의 의존성 주입 기능을 앱 전체에 적용합니다. 그 다음으로, 필요한 곳에 @Inject 어노테이션을 사용하여 의존성을 주입받을 수 있습니다.

예를 들어, 액티비티, 프래그먼트, 뷰모델, 서비스 등에서 필요한 객체를 Hilt가 자동으로 주입해주도록 설정할 수 있습니다. 이 과정에서 개발자는 의존성을 생성하고 관리하는 복잡한 작업에서 벗어날 수 있어, 더욱 집중해서 애플리케이션의 비즈니스 로직을 개발할 수 있습니다.

종속 항목 추가

build.gradle.kts(Module.app)

plugins {
    ...
    alias(libs.plugins.kotlin.kapt)
    alias(libs.plugins.hilt)
}

android {
  ...
}

dependencies {
  // Hilt 의존성
  implementation(libs.hilt)
  kapt(libs.hiltCompiler)
}
kapt {
  correctErrorTypes = true
}

libs.versions.toml

[versions]
...
hilt = "2.48"
...

[plugins]
...
kotlin-kapt = { id = "org.jetbrains.kotlin.kapt" }
hilt = { id = "com.google.dagger.hilt.android", version = "2.48" }

Hilt 애플리케이션 클래스

AndSopt.kt

@HiltAndroidApp
class AndSopt : Application()

Android 클래스에 종속 항목 삽입

MainActivity.kt

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

예시 사용

PreferencesManager.kt

class PreferencesManager @Inject constructor(@ApplicationContext context: Context) {
    private val sharedPreferences: SharedPreferences =

SignUpViewModel.kt

@HiltViewModel
class SignUpViewModel @Inject constructor(
    private val userManager: UserManager,
    @ApplicationContext private val context: Context
) : ViewModel() { 
		...
		private fun validateEmail() {
        isEmailValid = userIdInput.isNotEmpty() && isValidEmail(userIdInput)
        signUpEmailDescription = when {
            userIdInput.isEmpty() -> context.getString(R.string.sign_up_email_default)
            userIdInput.length < 5 -> context.getString(R.string.sign_up_email_error1)
            !isEmailValid -> context.getString(R.string.sign_up_email_error2)
            else -> context.getString(R.string.sign_up_email_default)
        }
    } 
    ...
}

SignUpScreen.kt

@Composable
fun SignUpScreen(
    onNavigateToSignIn: () -> Unit,
    modifier: Modifier,
    viewModel: SignUpViewModel = hiltViewModel()
) { ... }

위의 SignUpViewModel 에서는 @Inject 생성자를 통해 UserManager 인스턴스와 애플리케이션 컨텍스트Context가 자동으로 주입됩니다. 이를 통해 SignUpViewModel 내에서는 userManagercontext를 직접 생성하거나 초기화할 필요 없이 바로 사용할 수 있습니다.

결론..

Hilt를 사용하여 PreferencesManager 클래스에서 @ApplicationContext 어노테이션을 통해 Context 를 주입받는 방법은 추가적인 모듈 설정 없이도 애플리케이션 전반의 Context를 자동으로 제공받을 수 있기 때문에 효율적입니다. 이로 인해 PreferencesManager와 같은 클래스에서 Context를 관리하기 위해 별도의 모듈을 제공할 필요가 없습니다. 이는 코드의 간결성을 높이며, 의존성 관리를 더욱 명확하게 해줍니다.

출처

https://developer.android.com/training/dependency-injection/hilt-android
https://developer.android.com/codelabs/android-hilt
https://lovestudycom.tistory.com/entry/Android-Hilt를-이용한-의존성-주입

profile
나만의 개발 일기

0개의 댓글