일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- 암호학
- pandas
- AWS
- Hilt
- Gradle
- Compose
- boj
- Kotlin
- 코드포스
- MiTweet
- 프로그래머스
- Coroutines
- android
- architecture
- MyVoca
- activity
- androidStudio
- relay
- 코루틴
- textfield
- 백준
- GitHub
- ProGuard
- Coroutine
- livedata
- TEST
- Rxjava
- Codeforces
- Python
- 쿠링
- Today
- Total
이동식 저장소
[Hilt] 1. 의존성 주입이란? 본문
이 글은 Google의 (Dependency injection in Android | Android Developers) 공식 문서를 참고하여 작성되었습니다.
의존성 주입(Dependency Injection, DI)는 프로그래밍에서 널리 사용되는 테크닉이다. DI를 적용하면 더 좋은 아키텍쳐를 만드는 데 도움이 된다. 좋은 아키텍쳐란 다음과 같다.
- 코드의 재사용성이 높음
- 리팩토링이 쉬움
- 코드를 테스트하기 쉬움
그래서 DI가 뭡니까?
객체 지향적 설계에서 하나의 클래스가 다른 클래스를 참조하는 일은 흔하다. 예를 들어 Car
클래스의 정의에는 Engine
클래스가 포함될 수 있다. 이러한 필요 관계를 의존성이라고 말한다. 이 경우에는 Car
가 Engine
에 의존한다고 말한다.
클래스가 의존하는 객체를 얻는 방법은 세 가지가 있다.
- 클래스가 직접 객체를 만든다. 위의 예시로 따지자면
Car
클래스의 생성자에서 자체적으로Engine
객체를 만드는 것이다. - 어딘가에서 가져온다. Android에서
Context.getSystemService()
로 가져오는 방식 등이 해당된다. - 매개변수로 받는다. 위의 예시로 따지자면
Engine
을Car
클래스의 생성자 매개변수로 넘기거나,set
메소드를 이용하여 객체를 얻을 수 있다.
3번 방법이 바로 DI이다. 외부로부터 의존성(dependency) 있는 객체를 제공받는(injection) 개념이다.
1번 방법을 코드로 구현해 보면 다음과 같다.
class Car {
private val engine = Engine()
fun start() {
engine.start()
}
}
fun main(args: Array) {
val car = Car()
car.start()
}
Car
클래스에서 Engine
객체를 자체적으로 만들고 있다. 이런 방법은 문제가 있을 수 있다.
Car
와Engine
이 강하게 결합되었다.Car
는 오직Engine
타입만을 사용할 수 있으며,ElectricEngine
이나GasEngine
을 사용할 수 없다. 다른 엔진을 사용하고 싶다면 해당 엔진을 사용하는 클래스를 새로 정의해야 한다. 아니면Car
를 전부 리팩토링하거나.Car
를 테스트하기 어렵다.Car
가Engine
에 강하게 결합되었기 때문에Car
를 테스트하려면Engine
까지 함께 테스트해야 하는 문제가 생긴다. 이게 무슨 뜻인지 나중에 알게 될 것이다.
DI를 적용한 구현은 다음과 같다.
class Car(private val engine: Engine) {
fun start() {
engine.start()
}
}
fun main(args: Array) {
val engine = Engine()
val car = Car(engine)
car.start()
}
Car
의 생성자 매개변수로 Engine
을 받고 있다. 이렇게 하면 뭐가 좋을까?
Car
의 재사용성이 높아진다. 이제Car
에Engine
의 다른 구현체(ElectricEngine
,GasEngine
,DieselEngine
등)를 전달하여 사용할 수 있다. 인터페이스만 잘 구현해 놓으면 되는 것이다!Car
를 테스트하기 쉬워진다. 테스트용Engine
을 여러 개 구현하여 다양한 상황에서Car
를 테스트할 수 있다.
우와!
위의 예시에서는 Engine
객체를 코드로 직접 생성하여 넘겨주었다. 당장은 괜찮지만, 프로젝트가 커지면 Engine
객체를 만들기가 어려워질 수도 있다. Engine
을 만들기 위해 Piston
, Cylinder
등의 부품이 필요해질 수 있기 때문이다. 또는 Car
를 만들기 위해 필요한 의존성이 많아질 수도 있다. 이러면 boilerplate 코드가 너무 길어지고, 의존성을 수동으로 관리하다 보면 실수할 수도 있다.
당연히 이런 문제점을 누군가가 이미 해결해 놓았다. 자동으로 의존성을 주입해 주는 라이브러리가 개발되어 널리 사용되고 있다. 라이브러리를 크게 두 가지로 나누면
- 실행 시간에 의존성을 연결하는 동적 라이브러리와
- 컴파일 시간에 의존성을 체크하는 정적 라이브러리
가 존재한다. 정적 라이브러리 중 유명한 것으로 Google의 Dagger가 있다. 안드로이드에서는 Dagger 기반의 Hilt를 사용할 수 있다.
Hilt
Hilt는 Android에서 DI를 적용할 때 사용할 수 있는 Jetpack 라이브러리이다. Hilt는 Dagger를 기반으로 개발되어, 타입 정확성, 런타임 성능, 확장성과 Android Studio 지원 등의 이점을 누릴 수 있다.
다음 글에서 Hilt를 직접 사용해 보자.
'Primary > Android' 카테고리의 다른 글
Widget에서 Room 데이터베이스에 접근하는 방법 (0) | 2021.05.06 |
---|---|
[Hilt] 2. Dependency Injection with Hilt (5) | 2021.04.29 |
[Android] Cannot invoke setValue on a background thread (0) | 2021.03.14 |
[Android] Transformations.map이 동작하지 않을 때 (0) | 2021.02.17 |
[Android Kotlin Fundamentals] Lifecycle (2) | 2021.02.03 |