Developing Myself Everyday
Published 2026. 2. 9. 19:17
Koin 톺아보기 1편 Android/Kotlin

 

이번 게시글에서는 Koin에 대해 알아보고자 합니다.

 

 

Koin이란?


Koin은 Kotlin에 특화된 경량화된 의존성 주입 프레임워크입니다. 

 

koin은 다음과 같은 2가지의 의존성 주입 방식이 있습니다.

  1. Kotlin DSL
  2. Annotation 

2가지 방식의 기능 차이는 거의 존재하지 않기에 원하는 방식을 사용하여 의존성을 주입할 수 있습니다.

 

 

런타임 의존성 주입

koin은 기본적으로 런타임에 의존성을 주입해 줍니다. 

 

런타임의 장점은 유연하다는 것입니다. 다른 의존성 주입 라이브러리와 달리 상황에 따라 동적으로 의존성을 주입할 수 있습니다.

// 동적 모듈 로딩 (Hilt 불가)
if (featureEnabled) {
    loadKoinModules(premiumFeatureModule)
}

// 기능 비활성화 시
unloadKoinModules(premiumFeatureModule)

 

 

하지만, 런타임에 의존성을 주입하면 애플리케이션의 실행 중에 의존성 관련 오류가 발생할 수 있기에, koin은 `Koin Compiler Plugin`을 통해서 의존성 그래프 검증을 수행합니다.

 

Koin Compiler Plugin은 Kotlin 네이티브 컴파일러 플러그인(K2)로 , 다음과 같은 기능을 제공합니다. 

  • 생성자 의존성을 자동으로 감지합니다.
  • 컴파일 타입 분석을 제공합니다.
  • DSL과 Annotation 방식 모두에서 동작합니다. 
  • 별도의 파일을 만들지 않습니다.
  • KSP를 사용하지 않습니다.

 

Koin은 이러한 방식을 통해, 런타임 의존성 주입이 가지는 유연성과 컴파일 타임 의존성 검증이 제공하는 안정성을 모두 확보할 수 있습니다.

 

 

 

2가지 의존성 주입 스타일


Koin은 의존성 정의를 위한 두 가지 스타일을 지원하며, 기능 차이는 없습니다.

 

 

Kotlin DSL 스타일

val appModule = module {
    single<Database>()
    single<ApiClient>()
    single<UserRepository>()
    viewModel<UserViewModel>()
}

 

Annotation 스타일

@Singleton
class Database

@Singleton
class ApiClient

@Singleton
class UserRepository(
    private val database: Database,
    private val apiClient: ApiClient
)

@KoinViewModel
class UserViewModel(
    private val repository: UserRepository
) : ViewModel()

 

자세한 사용 방법에 대해서는 나중에 알아보겠습니다.

 

 

 

Koin의 핵심 기능


이제부터는 Koin의 핵심 기능들에 대해서 알아보겠습니다.

 

startKoin

Koin에는 컨테이너라는 개념이 존재합니다. 컨테이너는 의존성을 보관하고, 필요할 때 꺼내 주입해 주는 저장소입니다.

 

`startKoin`은 Koin 컨테이너를 초기화하고 애플리케이션에 맞게 설정할 수 있는 메인 진입점이 되는 메서드입니다. 이 함수는 컨테이너를 GlobalContext에 등록하여, 애플리케이션 전역에서 접근할 수 있도록 만듭니다.

startKoin {
    modules(appModule)
}

 

 

modules

Koin `module`은 의존성 주입 구성을 체계적으로 정리하기 위한 기본 구성 요소입니다.

 

`module`은 "의존성들을 모아둔 묶음 파일"이라고 보면 됩니다.  `module`은 서로 관련된 의존성들을 하나로 캡슐화하여, 기능이나 계층 단위로 의존성을 구성할 수 있도록 합니다.

val appModule = module {
    single<Database>()
    single<UserRepository>()
    viewModel<UserViewModel>()
}

 

 

이렇게 정의한 모듈은 `startKoin` 에서 등록할 수 있습니다. 한번에 여러 모듈을 등록하는 것 또한 가능합니다.

startKoin {
    modules(dataModule, viewModelModule)
}

 

 

includes

`includes`는 모듈을 구성할 때 권장되는 방식입니다. 다음과 같은 장점을 제공합니다.

  • 모듈 계층 구조: 부모-자식의 관계로 모듈을 구조화할 수 있음
  • 로딩 최적화: Koin이 포함된 모듈을 중복 제거해서 불필요한 등록을 막아줌
  • 깔끔한 시작 구성: 긴 모듈 목록 대신에 하나의 루트 모듈만 등록
  • 캡슐화: 내부 모듈을 공새 API 모듈 뒤에 숨길 수 있음

 

Koin은 모듈을 구성할 때, 모든 모듈을 나열하는 대신 `includes`를 사용해서 모듈 계층을 구성하는 것을 권장합니다.

val networkModule = module {
    single<ApiClient>()
}

val storageModule = module {
    single<Database>()
}

// 부모 모듈이 자식 모듈을 포함
val dataModule = module {
    includes(networkModule, storageModule)
    single<UserRepository>()
}

startKoin {
    modules(dataModule)
}

 

 

 

Definitions


`Definitions`은 Koin이 의존성을 생성하고 관리하는 방식을 정의합니다. 

 

`Definitions`의 타입은 다음과 같이 4가지가 존재합니다.

 

Single

앱 전반에서 재사용되는 하나의 인스턴스를 생성합니다.

// DSL
single<DatabaseHelper>()

// Annotation
@Singleton
class DatabaseHelper

 

Factory

요청할 떄마다 새로운 인스턴스를 생성합니다.

// DSL
factory<UserPresenter>()

// Annotation
@Factory
class UserPresenter(private val repository: UserRepository)

 

Scoped

스코프마다 하나의 인스턴스를 생성합니다.

// DSL
scope<MyActivity> {
    scoped<ActivityPresenter>()
}

// Annotation
@Scoped(MyActivityScope::class)
class ActivityPresenter

 

ViewModel

적절한 생명주기를 따르는 Android ViewModel을 생성합니다.

// DSL
viewModel<UserViewModel>()

// Annotation
@KoinViewModel
class UserViewModel(private val repository: UserRepository) : ViewModel()

 

 

 

Interface Binding


구현체가 아니라 인터페이스 타입으로 주입하기 위해서는 다음과 같이 바인딩을 정의합니다.

single<UserRepositoryImpl>() bind UserRepository::class

 

Annotation을 활용하면 자동으로 바인딩을 수행해 주기에 더 편리합니다.

@Singleton
class UserRepositoryImpl(
    private val database: Database
) : UserRepository

 

만약 명시적으로 바인딩을 정의하고 싶다면 다음과 같이 할 수 있습니다.

@Singleton
class UserRepositoryImpl(
    private val database: Database
) : UserRepository

 

 

 

1편 마무리


이번 게시글에서는 Koin에 대해서 기본적으로 알아보고, 몇 가지 Koin의 핵심 기능들에 대해 알아보았습니다.

 

분량이 너무 많아 다음 게시글에서 이어서 Koin의 나머지 핵심 기능들에 대해서 알아보고자 합니다.

 

 

 

 

Reference

 

What is Koin? | Koin

The Pragmatic Kotlin Dependency Injection Framework - Simple AND Powerful

insert-koin.io

 

Definitions | Koin

Definitions declare how Koin creates and manages your dependencies. This guide covers all definition types using both DSL and Annotations.

insert-koin.io

 

 

 

profile

Developing Myself Everyday

@배준형

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!