의존성주입이란
생성자 또는 메서드 등을 통해 외부로부터 생성된 객체를 전달받는것입니다.
의존성주입의 특징
클래스간 결합도를 느슨하게 합니다.
인터페이스 기반으로 설계되며, 코드를 유연하게 합니다.
Stub 또는 Mock 객체를 상용하여 단위테스트를 하기가 더욱 쉽게하는데 그 목적이 있습니다.
예제
의존성주입이 없는 코드
class JSRepository{
private val db = SQLiteDatabase()
fun load(id:String){
//...
}
}
fun main(){
val repositoy = JSRepository()
repository.load("8092");
}
의존성주입이 있는 코드
class JSRepository(private val db:Databse){
fun load(id:String{
// ...
}
}
fun main(){
val db = SQLiteDatabse()
val repository = JSRepository(db)
repository.load("8092")
}
Koin
Koin 이란?
koin 공식 사이트 에서 코인을
A pragmatic lightweight dependency injection framework for Kotlin developers: no proxy, no code generation, no reflection.
라고 나와있습니다.
장점
러닝커브가 낮아 쉽고 빠르게 DI를 적용할 수 있습니다.
Kotlin 개발 환경에 도입하기 쉽습니다.
별도의 어노테이션을 사용하지 않기 때문에 컴파일 시간이 단축됩니다.
ViewModel 주입을 쉽게 할 수 있는 별도의 라이브러리를 제공합니다.
단점
Dagger2와 달리 런타임에서 에러가 날 수도 있습니다(단위 테스트를 통해 방지할 수는 있습니다).
Activity나 Fragment, Service 등이 아닌 곳에서 사용하기 위해선 생성자로 넘기거나 별도의 구현을 해야 합니다.
사용하기
1. gradle에 의존성 추가
build.gradle(Module) 파일
dependencies {
// for 코틀린 app
implementation "org.koin:koin-androidx-viewmodel:$koin_version"
// for 테스트
testImplementation "org.koin:koin-test:$koin_version"
}
build.gradle(Project) 파일
buildscript {
ext.koin_version = '버전 코드'
repositories {
jcenter()
}
}
gradle에 의존성 추가하고, jcenter() repositories를 등록하고, koin_version 변수를 선언합니다.
최신버전은 다음 링크을 참고한다.
2. 모듈 선언
module 키워드를 통해 주입 받고자 하는 객체를 모듈로 만들어 선언합니다.
간단한 동작을 하는 샘플 클래스를 만들어 봅시다.
SampleRepository 클래스와 이 클래스 객체를 파라미터로 받는 Controller, 그리고 ViewModel 클래스인 ViewModel을 만들어줍니다.
class Repository {
val firstData = "This is my first Data!"
}
class Controller(val repository: Repository) {
fun printSampleData() {
Log.d("Print sample data", repository.firstData)
}
}
class MainViewModel : ViewModel() {
private var _isLoading = MutableLiveData<Boolean>()
val isLoading: LiveData<Boolean> = _isLoading
}
3. 모듈 등록
module 키워드를 이용해 모듈로 선언하고 변수에 저장합니다.
class BaseApp : Application() {
override fun onCreate() {
super.onCreate()
startKoin{
androidContext(this@BaseApp)
modules(moduleList)
}
}
}
/**
* Repository 타입으로 선언되어 있으므로 이미 생성된 객체 중 Repository 타입에 알맞은 객체를 Koin이 주입해줍니다
**/
val appModule = module {
single { Repository() }
factory { Controller(get()) }
}
/**
* ViewModel의 경우 viewModel 키워드로 선언해야 합니다
**/
val viewModelModule = module {
viewModel { MainViewModel() }
}
val moduleList = listOf(appModule, viewModelModule)
* single : 앱이 실행되는 동안 계속 유지되는 싱글톤 객체를 생성합니다.
* factory : 요청할 때마다 매번 새로운 객체를 생성합니다.
* get() : 컴포넌트 내에서 알맞은 의존성을 주입 받습니다.
(2가지 방법: 1) 직접주입, 2) 생성자에 주입(Controller))
4. 의존성 주입받기
by inject()로 Koin에 등록된 객체를 lazy 하게 주입 받을 수 있습니다
/**
* MainActivity에서 각 클래스에 따른 인스턴스 객체를 일일이 생성해주었습니다.
* 하지만 Koin 코인을 활용하면서 DI 의존성 주입 디자인 패턴이 구성되었으며
* 프로그래머가 직접 의존 관계를 설정해주지 않더라도 자동으로 의존성 관계 문제가 해결됨
**/
class MainActivity : AppCompatActivity() {
// by inject()로 Koin에 등록된 객체를 lazy 하게 주입 받을 수 있습니다
val controller : Controller by inject()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
controller.printSampleData()
}
}
5. 테스트하기
/**
* JUnit 테스트 클래스에서 KoinTest를 상속받아 Koin 모듈을 주입 받을 수 있습니다.
* KoinTestRule을 통해 Koin context를 시작/중단할 수 있습니다.
*
*
*/
class UnitTest1 : KoinTest{
@get:Rule
val koinTestRule = KoinTestRule.create{
modules(appModule)
}
val controller : Controller by inject()
@Before
fun setUp(){
System.out.println("======= Before ======")
}
@Test
fun koinTest(){
assertEquals ("",)
}
}
Koin 의Koin에서 사용하는 DSL(Domain Specific Languag,도메인 특화 언어) 키워드
전체 코드 :
Hilt 공식문서 번역본
참고
www.youtube.com/watch?v=gkUCs6YWzEY&ab_channel=DroidKnights
drive.google.com/file/d/11YyGGxoIkzaWG14PE7vAjSrFW1MhGPEL/view
www.youtube.com/watch?v=B56oV3IHMxg&ab_channel=AndroidDevelopers
'Android > Android 더하기' 카테고리의 다른 글
MVVM 패턴 (0) | 2021.04.22 |
---|---|
[Android Library] OkHttp : Http OK?? OK!! (0) | 2021.04.19 |
[Android Library] Gson : Json을 Java 객체로 변환 (0) | 2021.04.19 |
REST API : HTTP 모범생 (0) | 2021.04.16 |
HTTP 원리 (0) | 2021.04.15 |