Koin을 사용한 KMP 의존성 주입
멀티플랫폼 설정에서 Koin으로 공유 모듈을 연결해 보세요.
Koin을 사용한 KMP 의존성 주입은(는) CoddyKit의 무료 Kotlin Academy 강의입니다. 이것은 4개 중 4번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Kotlin Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Kotlin Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
KMP에서 DI가 필요한 이유
의존성 주입은 구성 요소 생성과 사용을 분리합니다. KMP에서는 애노테이션 프로세서 없이 순수 Kotlin으로 작성되고 commonMain에서 작동하므로 Koin이 대표적인 DI 프레임워크로 사용됩니다.
// No annotation processing needed — Koin uses lambda DSL
// Add to build.gradle.kts:
// implementation("io.insert-koin:koin-core:3.5.0")
// androidMain: koin-android
// iosMain: no extra dep
fun main() { println("Koin works on all KMP targets") }Koin 모듈 DSL
module { } 블록에서 single, factory, scoped를 사용하여 바인딩을 정의합니다.
import org.koin.core.module.dsl.*
import org.koin.dsl.*
val appModule = module {
single { HttpClient() } // one instance
single<UserRepository> { RemoteUserRepository(get()) }
factory { GetUserUseCase(get()) } // new instance each time
}commonMain의 공유 모듈
commonMain에서 공유 Koin 모듈을 정의합니다. 플랫폼 모듈은 플랫폼별 바인딩으로 이를 확장합니다.
// commonMain/di/SharedModule.kt
import org.koin.dsl.module
fun sharedModule() = module {
single<UserRepository> { RemoteUserRepository(get()) }
single { GetUserUseCase(get()) }
single { UserViewModel(get()) }
}androidMain의 플랫폼 모듈
플랫폼 모듈은 실제 HTTP 엔진, 데이터베이스 드라이버, Android 전용 싱글턴을 제공합니다.
// androidMain/di/AndroidModule.kt
import io.ktor.client.engine.okhttp.*
import org.koin.dsl.module
fun androidModule() = module {
single { OkHttp.create() } // Ktor engine
single { createHttpClient(get()) }
includes(sharedModule())
}Android Application에서 startKoin 시작하기
Android Application.onCreate에서 startKoin { }을 호출합니다. androidContext(this)를 사용하여 컨텍스트를 사용할 수 있게 합니다.
// androidMain:
import org.koin.android.ext.koin.androidContext
import org.koin.core.context.startKoin
// In Application.onCreate():
startKoin {
androidContext(this@MyApp)
modules(androidModule())
}iOS에서 Koin 시작하기
iOS에서는 Swift의 AppDelegate 또는 App 구조체에서 KoinApplication.start()를 호출하고 공유 Koin 모듈을 전달합니다.
// iosMain/KoinInit.kt:
import org.koin.core.context.startKoin
fun initKoin() {
startKoin {
modules(iosModule())
}
}
// Swift: KoinInitKt.doInitKoin() in AppDelegate의존성 해결
commonMain의 ViewModel이나 유스 케이스에서는 모듈 내부에서 get()을 사용하거나 호출 지점에서 inject() / getKoin().get()을 사용합니다.
import org.koin.core.component.KoinComponent
import org.koin.core.component.inject
class UserViewModel : KoinComponent {
private val getUser: GetUserUseCase by inject()
fun load(id: String) = runBlocking { getUser(id) }
}ViewModel을 위한 Koin 범위
Android 모듈에서는 Android ViewModels에 viewModel { }을 사용하고, 공유 VM에는 플랫폼에 종속되지 않는 factory { }를 사용합니다.
// androidMain (with koin-android):
import org.koin.androidx.viewmodel.dsl.viewModel
val androidVmModule = module {
viewModel { UserViewModel(get()) }
}
// In Compose:
// val vm: UserViewModel = koinViewModel()Koin을 사용한 테스트
테스트 설정에서 startKoin을 사용하고, 실제 종속성을 가짜 구현으로 교체하는 테스트 모듈을 사용합니다.
import org.koin.core.context.startKoin
import org.koin.core.context.stopKoin
import org.koin.dsl.module
class UserViewModelTest {
@BeforeTest fun setup() {
startKoin { modules(module {
single<UserRepository> { FakeUserRepository() }
single { GetUserUseCase(get()) }
})}
}
@AfterTest fun teardown() = stopKoin()
}single, factory, scoped 비교
single: 앱 수명 동안 하나의 인스턴스를 사용합니다. factory: get()이 호출될 때마다 새 인스턴스를 생성합니다. scoped: Koin 범위마다 하나의 인스턴스를 사용합니다(예: 화면 범위).
import org.koin.dsl.module
val lifetimeModule = module {
single { Database() } // shared, one instance
factory { Analytics() } // new on each get()
scope<ScreenScope> {
scoped { ScreenViewModel() } // one per screen lifecycle
}
}Koin, 수동 DI, Hilt 비교
Koin: 멀티플랫폼을 지원하고 KSP/KAPT가 필요 없으며 런타임 DI를 사용합니다. Hilt: Android 전용이며 컴파일 시점에 애노테이션을 기반으로 처리합니다. 수동 DI: 프레임워크 오버헤드 없이 가장 높은 제어력을 제공합니다. KMP 프로젝트에서는 공유를 위해 Koin을 사용합니다.
fun main() {
// Koin : commonMain, runtime, lambda DSL
// Hilt : androidMain only, compile-time
// Manual: no framework, explicit wiring in factory/module files
println("Choose Koin for KMP; Hilt for Android-only projects")
}by inject()를 사용한 지연 주입
by inject()는 처음 접근할 때 의존성을 지연해서 해결합니다. KoinComponent를 구현하는 클래스에서 유용합니다.
import org.koin.core.component.KoinComponent
import org.koin.core.component.inject
class AppService : KoinComponent {
private val repo: UserRepository by inject() // resolved on first use
fun doWork() = println(repo.javaClass.simpleName)
}빠른 확인
get()이 호출될 때마다 새 인스턴스를 생성하는 Koin 범위는 무엇입니까?
정리
Koin은 애노테이션 처리 없이 람다 DSL을 사용하므로 KMP에 적합합니다. 공유 모듈은 commonMain에, 플랫폼 모듈은 플랫폼 소스 세트에 정의합니다. 싱글턴에는 single을, 새 인스턴스에는 factory를, 지연된 해결에는 by inject()를 사용합니다.
AI 튜터와 함께 Kotlin을(를) 배우세요 — 무료
브라우저에서 실제 코드를 작성하고 실행하며, 24/7 AI 튜터로부터 즉각적인 도움을 받고, 웹이나 앱에서 중단한 부분부터 계속 학습하세요.
- 코스
- 51
- 레슨
- 203
자주 묻는 질문
“Koin을 사용한 KMP 의존성 주입” 강의는 무료인가요?
네 — “Koin을 사용한 KMP 의존성 주입” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Kotlin Academy 강의 전체를 잠금 해제할 수 있습니다. Kotlin Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
“Koin을 사용한 KMP 의존성 주입”에서 뭘 배우나요?
멀티플랫폼 설정에서 Koin으로 공유 모듈을 연결해 보세요. 브라우저에서 직접 실행하는 실습 코드로 Kotlin Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
Kotlin Academy을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 Kotlin Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 4번째 강의입니다.
“Koin을 사용한 KMP 의존성 주입” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 Kotlin Academy 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 Kotlin Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- KMP 프로젝트 구조: commonMain, androidMain, iosMain
- 플랫폼 API를 위한 expect/actual 메커니즘
- 저장소 및 사용 사례 계층 공유하기
- Koin을 사용한 KMP 의존성 주입