의존성 주입이란?
안드로이드에서 의존성 주입(Dependency Injection)은 객체 지향 프로그래밍(OOP)에서 사용되는 디자인 패턴 중 하나입니다.
의존성 주입은 객체가 필요로 하는 다른 객체를 직접 생성하는 대신에, 이를 외부에서 전달받는 방식으로 구현됩니다. 이는 객체 간의 결합도(Coupling)를 낮추고, 유지보수와 테스트 용이성을 증가시키는 데 도움이 됩니다.
안드로이드 앱에서 의존성 주입을 사용하면, 앱의 여러 컴포넌트(Activity, Fragment, Service, ViewModel 등)에서 공통적으로 사용되는 객체(예: 데이터베이스, 네트워크 등)를 한 곳에서 관리하고, 이를 각각의 컴포넌트에서 사용할 수 있습니다. 이를 통해 코드의 중복을 줄이고, 유지보수와 테스트 용이성을 증가시킬 수 있습니다.
의존성 주입을 구현하는 방법으로는, Dagger와 같은 서드파티 라이브러리를 사용하는 방법과, 직접 의존성 주입을 구현하는 방법이 있습니다. Dagger는 코드를 자동으로 생성해주기 때문에 간편하지만, 학습 곡선이 높을 수 있습니다. 반면 직접 구현하는 경우 코드가 간결해지고, 의존성 주입의 동작 방식을 이해하는 데 도움이 됩니다.
Dagger
Dagger는 안드로이드 앱에서 의존성 주입을 구현하는 데 사용되는 서드파티 라이브러리입니다. Dagger는 구글에서 개발한 Java 및 안드로이드용 의존성 주입 프레임워크 중 하나로, 코드를 자동으로 생성하여 앱의 의존성 관리를 용이하게 해줍니다.
Dagger는 컴파일 타임에 코드를 생성하여 의존성을 주입하는 방식을 사용합니다. 이를 통해 런타임에서 발생할 수 있는 오류를 컴파일 타임에 미리 방지할 수 있습니다. 또한 Dagger는 생성된 코드를 기반으로 런타임 시 객체를 생성하므로, 객체 생성에 필요한 리소스를 최소화하여 성능을 향상시킬 수 있습니다.
Dagger는 앱의 컴포넌트(Activity, Fragment, Service 등)들 간의 의존성을 관리하기 위해 주로 사용됩니다. 이를 통해 각 컴포넌트에서 공통적으로 사용하는 객체(예: 데이터베이스, 네트워크 등)를 한 곳에서 관리하고, 이를 각각의 컴포넌트에서 사용할 수 있습니다. 이는 코드의 중복을 줄이고, 유지보수와 테스트 용이성을 증가시키는 데 도움이 됩니다.
Dagger는 Dagger 1, Dagger 2, Dagger Hilt 등 다양한 버전이 있으며, 각 버전마다 사용법이 조금씩 다를 수 있습니다. 최근 안드로이드에서는 Dagger Hilt를 권장하고 있으며, 새로운 프로젝트에서는 Dagger Hilt를 사용하는 것이 좋습니다.
Hilt를 이용한 의존성 주입
Dagger Hilt는 구글에서 개발한 안드로이드 앱에서 의존성 주입을 구현하기 위한 서드파티 라이브러리입니다. Dagger Hilt는 Dagger 2를 기반으로 하며, 보다 간편하게 의존성 주입을 구현할 수 있도록 지원합니다.
Dagger Hilt를 사용하기 위해서는 먼저 프로젝트에 Hilt 관련 의존성을 추가해야 합니다. 이를 위해 build.gradle 파일에 아래와 같이 의존성을 추가합니다.
dependencies {
implementation 'com.google.dagger:hilt-android:2.38.1'
kapt 'com.google.dagger:hilt-android-compiler:2.38.1'
}
Dagger Hilt는 주로 앱의 컴포넌트(Activity, Fragment, Service, ViewModel 등)에서 사용되며, 이를 위해 Hilt에서는 다양한 어노테이션을 제공합니다. 예를 들어, @AndroidEntryPoint 어노테이션은 해당 컴포넌트에 대한 의존성 주입을 활성화시키기 위해 사용됩니다.
@AndroidEntryPoint
class MyFragment : Fragment() {
// 의존성 주입을 받을 필드
@Inject lateinit var myDependency: MyDependency
// ...
}
위 코드에서 MyFragment 클래스에 @AndroidEntryPoint 어노테이션을 추가하여 의존성 주입을 활성화시킵니다. 그리고 myDependency 필드에 @Inject 어노테이션을 추가하여 해당 필드에 대한 의존성 주입을 요청합니다.
Dagger Hilt는 컴포넌트들 간의 의존성 관리를 용이하게 하기 위해 다양한 기능을 제공합니다. 예를 들어, @Singleton 어노테이션을 사용하여 해당 객체가 앱 전체에서 하나만 생성되도록 설정할 수 있습니다. 또한, @Provides 어노테이션을 사용하여 의존성을 제공하는 메서드를 정의할 수 있습니다.
@Module
@InstallIn(SingletonComponent::class)
object AppModule {
@Provides
@Singleton
fun provideMyDependency(): MyDependency {
return MyDependencyImpl()
}
}
위 코드에서 @Module 어노테이션을 사용하여 의존성을 제공하는 모듈을 정의하고, @Provides 어노테이션을 사용하여 MyDependency 객체를 제공하는 메서드를 정의합니다. 그리고 @Singleton 어노테이션을 사용하여 해당 객체가 앱 전체에서 하나만 생성되도록 설정합니다. 이렇게 정의한 모듈은 @InstallIn 어노테이션을 사용하여 컴포넌트에 설치됩니다.
Dagger Hilt는 컴포넌트 간의 의존성 관리를 위해 @Component 어노테이션을 사용합니다. @Component 어노테이션을 사용하여 컴포넌트를 정의하고, 해당 컴포넌트에 의존성을 제공하는 모듈을 설정합니다.
@Singleton
@Component(modules = [AppModule::class])
interface AppComponent {
fun inject(activity: MainActivity)
}
위 코드에서 @Component 어노테이션을 사용하여 AppComponent 인터페이스를 정의하고, AppModule 모듈을 설정합니다. 또한, inject 메서드를 정의하여 해당 메서드를 통해 MainActivity 클래스에 대한 의존성 주입을 할 수 있도록 설정합니다.
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
// 의존성 주입을 받을 필드
@Inject lateinit var myDependency: MyDependency
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// 의존성 주입을 요청
(applicationContext as MyApplication).appComponent.inject(this)
}
}
위 코드에서 MainActivity 클래스에 @AndroidEntryPoint 어노테이션을 추가하여 해당 컴포넌트에 대한 의존성 주입을 활성화시킵니다. 그리고 onCreate 메서드에서 MyApplication 클래스에서 정의한 appComponent 인스턴스를 통해 MainActivity 클래스에 대한 의존성 주입을 요청합니다.
Dagger Hilt는 이 외에도 다양한 기능을 제공하며, 앱의 규모가 커질수록 의존성 관리를 보다 쉽게 구현할 수 있도록 도와줍니다.
결론
- 클래스 재사용 가능 및 종속 항목 분리: 종속 항목 구현을 쉽게 교체할 수 있습니다. 컨트롤 반전으로 인해 코드 재사용이 개선되었으며 클래스가 더 이상 종속 항목 생성 방법을 제어하지 않지만 대신 모든 구성에서 작동합니다.
- 리팩터링 편의성: 종속 항목은 API 노출 영역의 검증 가능한 요소가 되므로 구현 세부정보로 숨겨지지 않고 객체 생성 시간 또는 컴파일 시간에 확인할 수 있습니다.
- 테스트 편의성: 클래스는 종속 항목을 관리하지 않으므로 테스트 시 다양한 구현을 전달하여 다양한 모든 사례를 테스트할 수 있습니다.
'Android > Study' 카테고리의 다른 글
[Android] Retrofit (0) | 2023.05.06 |
---|---|
[Android] MVI 패턴이란? (0) | 2023.05.04 |
[Android] Coroutine(코루틴) 간단 정리 (0) | 2023.04.27 |
[Android] 모듈을 기반으로하는 클린 아키텍처를 셋팅 (0) | 2023.02.22 |
[Android] Intent 란? (0) | 2023.02.03 |