Koin Library 사용하기(1편-기본편)
해당 문서는 Koin공식 문서를 기반으로 만들어졌습니다.
공식문서: https://insert-koin.io/
“Android개발자가 본 DI 란??”편에서 DI에 대한 기본 개념과 수동으로 DI를 하는법, 그리고 그에 따른 장단점에 대해 알아봤습니다. 사실 수동 DI에 대한 개념 없이 Library편에 접근하는것은 무리가 있으며, 오히려 “Android개발자가 본 DI 란??”편을 보고 Library편을 보는것이 시간도 절약되고 이해도가 더 높을것으로 생각됩니다.
상대적으로 쉬운 Koin이라는 라이브러리가 어떻게 동작하는지 알아보고 2편에는 Koin으로 MVVM적용하기를 해보도록 하겠습니다.
Koin
koin이라는 라이브러리가 생소할 수 있습니다. Koin은 kotlin이라는 안드로이드 공식 언어 개발자들이 개발한 DI 프레임워크이며 순수 코틀린으로만 제작되었습니다. 개인적으로 다른 프레임워크(Dagger같은..)와의 가장 큰 차이점은 경량화가 되어있고, 러닝커브다 낮다라는 장점이 있습니다.
A pragmatic lightweight dependency injection framework for Kotlin developers. Written in pure Kotlin using functional resolution only: no proxy, no code generation, no reflection!
Koin은 DSL이다.
제가 생각하는 가장 중요한 요소인것 같습니다. 시작부터 어려운 단어가 튀어 나옵니다. 그것은 바로 DSL…하지만 여러분 모두 알고있는 개념이니 안심하셔도 됩니다.
DSL(Domain Specific Language)
Koin은 도메인 특화 언어로써 SQL을 생각하면 이해가 쉬울지 모르겠습니다. SQL에서 특정 데이터를 갱신시키려면 update문을 써야만 하며, 특정 데이터를 조회하기 위해서는 select문을 써야 합나다. 또한 삭제는 delete를 써야하죠. select문으로는 delete를 할 수 없습니다. 이처럼 하나의 도메인당 역할이 주어져 있으며, 그에 맞는 도메인을 사용하면 된다라는 장점이 있습니다. module을 만들고 싶으면 modules(…)를 사용하면 됩니다. 마치 SQL create 처럼 말이죠.
Koin DSL키워드를 요약하면 아래와 같습니다.(물론 더 많습니다.)
startKoin{}
- 어플리케이션을 생성하고 괄호안에 있는 도메인들을 등록하고 Koin GlobalContext안에 등록합니다.koinApplication{}
- 어플리케이션을 생성하고 괄호안에 있는 도메인들을 등록합니다.modules{}
- 사용될 모듈을 정의합니다.single{}
- 싱글톤 패턴으로 인스턴스를 생성합니다.(get Instance)factory{}
- 새로운 인스턴스를 생성합니다.(new Class)get{}
- 구성요소들 간의 종속성을 자동으로 매핑시켜줍니다.viewmodel{}
- MVVM의 viewmodel전용으로 이용됩니다.androidLogger()
- 안드로이드 전용 로그를 작성합니다.logger()
- 로그를 작성합니다.properties()
- 주어진 맵을통하여 properties를 선언합니다.
중복된게 있다라고 느껴지는 이유는 android만을 위한 라이브리가 아니기 때문입니다. Android 전용이 있고, 그 외에 용이 있다는 말이죠. 우리는 안드로이드 개발자이기때문에 Android 전용만 골라서 쓰도록 하겠습니다. 왠지 전용이라고 하니까 특별해진 기분입니다.
제발 글로 설명하지말고 코드를 보여주세요. 저는 한글보다 코드읽는게 더 쉬워요.-개발자 이모씨
Gradle
gradle 세팅을 알아보겠습니다. 먼저 module수준의 gradle file에 koin-android를 추가해 주겠습니다. 버전은 업데이트가 진행중이므로 사용시점에 최신버전을 검색하여 적용하는것이 좋겠습니다.
koin은 공식문서에는 나와있지는 않지만, 제공되는 샘플코드 검토결과 최소 sdk버전을 21이상으로 설정해야 하는것으로 보입니다. 21버전이면 범용성은 상당히 괜찮은편 입니다.
Package 구성하기
“Android개발자가 본 DI 란??”에서 설명드렸었던 Car와 Engine의 DI를 자동으로 하는 방법으로 코드를 구현해보도록 하겠으며 패키지 구조는 아래와 같습니다.(기본 개념 이해를 돕기위하여 최대한 간단하게 구성해보았습니다.)
Car Engine 클래스 생성하기
Car는 Engine을 매개변수로 받습니다. 이때 의존성이 발생하는데 의존성 주입을 이때 이용할 수 있습니다. 수동으로 하던것을 어떻게 자동으로 하는지 알아보겠습니다.
클래스 선언은 여타 특별한 내용이 없는것을 바로 확인하실 수 있습니다.
Application에서 의존성 주입하기
Application에서 의존성을 주입하는 방법이 Koin라이브러리의 핵심이라고 할 수 있겠습니다. 코드는 아래와 같으며 설명은 코드를 보신 다음에 하도록 하겠습니다.
val appModule = module{} 로 사용할 모듈들 정의합니다. single로 Engine을 생성하고, factory로 Car를 생성합니다. 이때 특이한점은 Car의 인자값으로 get()를 이용한다는 것 입니다.
get()는 상기 Car Class에서 정의한 매개변수(Engine)를 찾아서 자동으로 매핑시켜 줍니다. 아주 편하죠? 이때 인자값이 다르거나, 매개변수 값이 다르면 컴파일 오류가 나기때문에 런타임 오류는 걱정하지 않으셔도 됩니다.
single은 싱글톤으로 객체를 생성하며, factory는 새객체를 생성합니다. 나눈 이유는 여러가지 도메인이 있다는것을 보여주기 위함이며 필요에 의해서 사용하면 되겠습니다. ex> repository는 single로 생성, viewmodel은 factory로 생성
이렇게 만들어진 appModule은 Application에서 startKoin{}을 통해서 주입시켜 줍니다. startKoin은 설명안해도 느낌 오시지 않나요? Koin을 사용하겠다 이런 뜻이며 사용시 필요한 내용들을 넣어주면 됩니다.(context, log, modules 등등)
MainActivity에서 사용하기
사전준비는 모두 마쳤으니 MainActivity에서 실제로 한번 사용해보도록 하겠습니다.
여러가지 상용구 코드(boilerplate)가 사라졌습니다. “Android개발자가 본 DI 란??”에서 인용하면 아래와 같은 코드죠.
by inject()를 통하여 제어역전이 되었으며,(우리는 val car 인스턴스가 언제 어떻게 생기는지 모르지만 사용할 수 있습니다.) 자동으로 의존성을 주입하는 코드가 완성되었습니다.
마무리
사족을 제거하고 아주 간단하게 구성한 내용이라 이게 필요한가? 라는 의문이 아직 남을 수 있습니다. 다음편에서는 MVVM에 Koin적용하기를 해보도록 하겠습니다.
같이보면 좋은 글입니다.
전체 소스코드는 깃허브에 올려두도록 하겠습니다.
TAG: Koin Library 사용하기(1편-세팅편)
이상 안드로이드 개발자 이종현이었습니다.
재밌게 읽으셨다면 👏🏻눌러 주시는 것도 잊지말아주세요~ 저에게 큰 힘이됩니다. :)
읽어주셔서 감사합니다.