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

사실 이해가 잘 되지 않았습니다.. (그래서 공부하면서 정리하겠다고 했습니다..)
한 클래스는 종종 다른 클래스를 참조합니다. 예를 들면, Car라는 클래스는 Engine이라는 클래스를 참조하고 있습니다. 이렇게 클래스를 필요로하는 것을 의존성(dependency)이라고 합니다. (저도 이해할 수 있는) 좋은 예제가 있어서 들고 와봤습니다!
class Car {
private val engine = Engine()
fun start() {
engine.start()
}
}
fun main(args: Array) {
val car = Car()
car.start()
}
위처럼 코드를 작성하면 Car 와 Engine 의 결합이 강해지고 재사용성이 떨어지게 됩니다. 아래는 의존성 주입을 이용해서 수정한 코드입니다.
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는 Android 앱 개발에 사용되는 의존성 주입(Dependency Injection, DI) 라이브러리입니다. 의존성 주입을 통해 객체 간의 결합도를 낮추고, 코드의 재사용성 및 유지보수성을 향상시킬 수 있습니다. Hilt는 Google에서 제공하며, Dagger를 기반으로 하고 있어서 Dagger의 강력한 기능을 좀 더 쉽게 사용할 수 있도록 도와줍니다.
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" }
AndSopt.kt
@HiltAndroidApp
class AndSopt : Application()
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 내에서는 userManager와 context를 직접 생성하거나 초기화할 필요 없이 바로 사용할 수 있습니다.
결론..
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를-이용한-의존성-주입