Android 의존성 주입: Hilt vs Koin 완전 가이드 및 면접 질문 2026
Hilt와 Koin을 코드 예제, 성능 벤치마크, 면접 질문으로 철저히 비교합니다. Hilt 2.57, Koin 4.2 기반 2026년 최신 가이드.

Android 애플리케이션 개발에서 의존성 주입(DI)은 클래스 간 결합도를 낮추고 테스트 용이성을 높이는 핵심 설계 기법입니다. 2026년 현재 Android 생태계를 지배하는 DI 프레임워크는 두 가지가 있습니다. Google이 공식 추천하는 컴파일 타임 솔루션 Hilt(버전 2.57.1, Dagger 기반)와 경량 런타임 서비스 로케이터인 Koin(버전 4.2.1)입니다. 어떤 것을 선택하느냐에 따라 빌드 시간, 시작 성능, 테스트 가능성, 그리고 팀의 온보딩 속도가 직접적으로 달라집니다.
Hilt는 컴파일 시점에 전체 의존성 그래프를 검증하며, 바인딩이 누락되면 빌드를 실패시킵니다. Koin은 Kotlin DSL을 사용하여 런타임에 의존성을 해결하므로, 구성 오류는 해당 코드 경로가 실행될 때만 감지됩니다. 이 근본적인 차이가 두 프레임워크 간의 모든 트레이드오프를 결정합니다.
Hilt의 내부 동작 원리
Hilt는 Android 라이프사이클 클래스에 매핑된 Dagger 컴포넌트를 생성합니다. @HiltAndroidApp 어노테이션이 컴파일 타임에 코드 생성을 트리거하여, 선언된 모든 바인딩에 대해 팩토리와 프로바이더를 생성합니다. Hilt 2.48부터 KSP(Kotlin Symbol Processing)가 KAPT를 대체하여 권장 어노테이션 프로세서가 되었으며, 어노테이션 처리 시간을 약 절반으로 단축했습니다.
일반적인 Hilt 설정은 세 가지 요소로 구성됩니다: 바인딩을 선언하는 모듈, 진입점(Activity, Fragment 또는 ViewModel), 그리고 @HiltAndroidApp으로 어노테이션된 Application 클래스입니다.
@Module
@InstallIn(SingletonComponent::class)
object AppModule {
@Provides
@Singleton
fun provideRetrofit(): Retrofit {
return Retrofit.Builder()
.baseUrl("https://api.example.com/")
.addConverterFactory(GsonConverterFactory.create())
.build()
}
@Provides
@Singleton
fun provideUserRepository(
retrofit: Retrofit
): UserRepository {
return UserRepositoryImpl(retrofit.create(UserApi::class.java))
}
}@HiltViewModel
class UserViewModel @Inject constructor(
private val userRepository: UserRepository
) : ViewModel() {
private val _users = MutableStateFlow<List<User>>(emptyList())
val users: StateFlow<List<User>> = _users.asStateFlow()
fun loadUsers() {
viewModelScope.launch {
_users.value = userRepository.getUsers()
}
}
}컴파일러는 앱이 실행되기 전에 UserRepository에 유효한 프로바이더가 존재하는지 검증합니다. 바인딩 누락은 런타임 크래시가 아닌 빌드 오류로 나타납니다.
Koin 설정과 Kotlin DSL 접근 방식
Koin은 Hilt와 정반대의 접근 방식을 취합니다. 코드 생성도 어노테이션 처리도 전혀 없습니다. 의존성은 Kotlin DSL을 사용하여 순수 Kotlin으로 선언되며, 프레임워크는 글로벌 서비스 레지스트리를 통해 런타임에 해결합니다. Koin 4.2에서는 시작 시 병렬 로딩을 위한 지연 모듈과 스코프 해결을 최적화하는 새로운 CoreResolverV2 엔진이 도입되었습니다.
val appModule = module {
// Singleton Retrofit instance
single<Retrofit> {
Retrofit.Builder()
.baseUrl("https://api.example.com/")
.addConverterFactory(GsonConverterFactory.create())
.build()
}
// Singleton repository bound to its interface
single<UserRepository> {
UserRepositoryImpl(get<Retrofit>().create(UserApi::class.java))
}
// ViewModel with injected repository
viewModel { UserViewModel(get()) }
}class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
startKoin {
androidContext(this@MyApplication)
modules(appModule)
}
}
}DSL은 자연스럽게 읽히는 코드를 제공하며, Gradle 설정에 어노테이션 처리 플러그인을 추가할 필요가 없습니다. 트레이드오프로, get() 해결의 오타는 해당 주입 지점이 실행되는 런타임에서만 발견됩니다.
성능 벤치마크: 빌드 시간 vs 런타임 비용
성능 관련 질문은 거의 모든 Android 면접에서 다루어집니다. 의견보다 구체적인 수치가 중요합니다.
| 지표 | Hilt 2.57 (KSP) | Koin 4.2 | |--------|-----------------|----------| | 클린 빌드 오버헤드 | +8-15초 (KSP 코드 생성) | ~0초 (코드 생성 없음) | | 증분 빌드 오버헤드 | +2-4초 | ~0초 | | 앱 시작 (50개 바인딩) | ~0ms (사전 생성 코드) | ~5-15ms (그래프 해결) | | 앱 시작 (500개 바인딩) | ~0ms | ~30-80ms | | APK 크기 영향 | +200-400 KB (생성 코드) | +100 KB (런타임 라이브러리) | | 바인딩 누락 감지 | 컴파일 오류 | 런타임 크래시 |
100개 미만의 바인딩을 가진 프로젝트에서는 Koin의 런타임 오버헤드가 체감되지 않는 수준입니다. 300개 바인딩을 초과하면 시작 비용이 측정 가능해지지만, Koin 4.2의 지연 모듈이 모듈 로딩 병렬화를 통해 이 문제를 완화합니다.
Hilt 처리를 KAPT에서 KSP로 전환하면 어노테이션 처리 시간이 40-60% 단축됩니다. KAPT로 Hilt를 사용하는 프로젝트는 즉시 KSP로 마이그레이션해야 합니다. Hilt는 버전 2.48부터 KSP를 지원하고 있습니다.
각 프레임워크의 테스트 전략
테스트 가능성은 아키텍처 차이가 실무에서 두드러지게 나타나는 영역입니다. Hilt는 @TestInstallIn을 제공하여 컴파일 타임에 프로덕션 모듈을 테스트 더블로 교체할 수 있습니다. Koin은 loadKoinModules()를 제공하여 런타임에 정의를 오버라이드합니다.
// Hilt test module — replaces AppModule bindings in tests
@Module
@TestInstallIn(
components = [SingletonComponent::class],
replaces = [AppModule::class]
)
object FakeAppModule {
@Provides
@Singleton
fun provideUserRepository(): UserRepository {
return FakeUserRepository() // In-memory test double
}
}// Koin test — override at runtime
class UserViewModelTest : KoinTest {
@Before
fun setUp() {
startKoin {
modules(
module {
single<UserRepository> { FakeUserRepository() }
viewModel { UserViewModel(get()) }
}
)
}
}
@Test
fun `loads users from repository`() {
val viewModel: UserViewModel = get()
viewModel.loadUsers()
assertEquals(3, viewModel.users.value.size)
}
@After
fun tearDown() {
stopKoin()
}
}Hilt 테스트는 잘못 구성된 테스트 모듈을 컴파일 타임에 감지합니다. Koin 테스트는 신중한 라이프사이클 관리(startKoin/stopKoin)가 필요하지만, 부분적인 모듈 오버라이드에서 더 높은 유연성을 제공합니다.
Android 면접 준비가 되셨나요?
인터랙티브 시뮬레이터, flashcards, 기술 테스트로 연습하세요.
멀티 모듈 아키텍처: 기능 간 DI 확장
대규모 Android 프로젝트는 기능을 Gradle 모듈로 분리합니다. DI 프레임워크는 모듈 경계를 깔끔하게 지원해야 합니다.
Hilt에서는 각 기능 모듈이 @InstallIn으로 어노테이션된 자체 @Module을 선언합니다. Hilt는 컴파일 타임에 모든 모듈을 단일 컴포넌트 계층으로 병합합니다. MVVM 아키텍처는 Hilt의 스코프 컴포넌트와 자연스럽게 결합됩니다.
@Module
@InstallIn(ViewModelComponent::class)
object PaymentModule {
@Provides
fun providePaymentGateway(
retrofit: Retrofit // Provided by :app module
): PaymentGateway {
return StripePaymentGateway(retrofit.create(PaymentApi::class.java))
}
}Koin에서는 기능 모듈이 module {} 선언을 내보내고, 앱 모듈이 시작 시 모두 로드합니다. Koin 4.2의 지연 모듈을 통해 기능 모듈의 로딩을 최초 접근 시점까지 지연시킬 수 있습니다.
val paymentModule = module {
factory<PaymentGateway> {
StripePaymentGateway(get<Retrofit>().create(PaymentApi::class.java))
}
}
// app/MyApplication.kt — loads all feature modules
startKoin {
modules(appModule, paymentModule, analyticsModule)
}Hilt는 컴포넌트 스코프를 통해 의존성 가시성을 강제합니다. Koin은 규약에 의존하므로, 어떤 모듈이든 다른 모듈의 정의에 접근할 수 있어 유연성을 제공하지만 암묵적 결합이 발생할 수 있습니다.
Kotlin Multiplatform 지원
Koin은 Kotlin Multiplatform(KMP)을 네이티브로 지원합니다. 동일한 module {} DSL이 Android, iOS, Desktop, Web 타겟에서 동작합니다. Hilt는 Android 전용이며, Android 고유의 라이프사이클 컴포넌트와 Dagger 어노테이션 프로세서에 의존합니다.
여러 플랫폼을 타겟으로 하는 프로젝트에서 Hilt와 Koin 중에서는 Koin이 유일한 실행 가능한 옵션입니다. 공유 비즈니스 로직 모듈에서 의존성을 한 번 선언하면 모든 타겟에 주입할 수 있습니다.
Android DI 관련 주요 면접 질문
다음 질문들은 Android 기술 면접에서 정기적으로 출제됩니다. 각 답변은 간결하게 정리하되, 면접관이 기대하는 핵심 포인트에 초점을 맞추고 있습니다.
Q: 컴파일 타임 의존성 주입과 런타임 의존성 주입의 차이는 무엇입니까?
컴파일 타임 DI(Hilt/Dagger)는 빌드 중에 주입 코드를 생성합니다. 컴파일러가 전체 의존성 그래프를 검증하여 바인딩 누락을 런타임 전에 감지합니다. 런타임 DI(Koin)는 서비스 레지스트리 패턴을 사용하여 의존성이 처음 요청될 때 해결합니다. 컴파일 타임 DI는 빠른 시작을 제공하지만 빌드가 느리고, 런타임 DI는 빌드 오버헤드가 없지만 오류 감지가 지연됩니다.
Q: Hilt 컴포넌트 스코프에는 어떤 것들이 있으며 Android 라이프사이클과 어떻게 매핑됩니까?
SingletonComponent는 전체 애플리케이션 수명 동안 존재합니다. ActivityRetainedComponent는 구성 변경에서도 유지됩니다. ViewModelComponent는 ViewModel의 라이프사이클에 스코프됩니다. ActivityComponent, FragmentComponent, ViewComponent는 각각 대응하는 Android 라이프사이클 소유자를 따릅니다. 커스텀 스코프로 이 계층을 확장하는 것도 가능합니다.
Q: Koin은 Jetpack Compose에서 ViewModel 주입을 어떻게 처리합니까?
Koin은 가장 가까운 ViewModelStoreOwner에 스코프된 ViewModel을 생성하거나 가져오는 Composable 함수로 koinViewModel()을 제공합니다. Koin 4.2부터 Jetpack Compose 네비게이션 사용 시 ViewModel을 네비게이션 그래프 엔트리에 스코프하는 koinNavViewModel()을 사용할 수 있습니다.
Q: Hilt보다 Koin이 더 나은 선택이 되는 경우는 언제입니까?
Koin은 KMP 프로젝트(Hilt는 Android 전용), 빌드 시간이 시작 시간보다 중요한 중소 규모 앱, 어노테이션 기반 구성보다 명시적인 Kotlin DSL을 선호하는 팀에 더 적합합니다. 프로토타이핑과 PoC(개념 증명) 프로젝트도 Koin의 최소한의 설정에서 이점을 얻습니다.
Koin을 "의존성 주입 프레임워크"라고 부르는 것은 기술적으로 부정확합니다. Koin은 서비스 로케이터이며, 의존성은 생성자 주입을 통해 푸시되는 것이 아니라 get()을 통해 풀링됩니다. 이 구분에 익숙한 면접관은 후보자가 이 점을 인지하고 있기를 기대합니다. Hilt/Dagger는 생성된 생성자 호출을 통해 진정한 의존성 주입을 수행합니다.
판단 프레임워크: Hilt와 Koin 선택 기준
| 요소 | Hilt | Koin |
|--------|------|------|
| 그래프 검증 | 컴파일 타임 | 런타임 |
| 빌드 시간 영향 | 큼 (KSP 코드 생성) | 없음 |
| 시작 비용 | 거의 제로 | 그래프 크기에 비례 |
| 학습 곡선 | 가파름 (Dagger 개념) | 완만 (순수 Kotlin DSL) |
| KMP 지원 | 없음 | 있음 |
| Jetpack 통합 | 깊음 (Google 공식) | 양호 (커뮤니티) |
| 팀 확장성 | 강함 (강제된 스코프) | 유연 (규약 기반) |
| 테스트 | @TestInstallIn (컴파일 안전) | loadKoinModules (런타임) |
어떤 프레임워크도 보편적으로 우월하지 않습니다. 선택은 프로젝트 규모, 팀 경험, 그리고 플랫폼 타겟에 따라 달라집니다.
연습을 시작하세요!
면접 시뮬레이터와 기술 테스트로 지식을 테스트하세요.
결론
- Hilt 2.57과 KSP 조합은 컴파일 타임 그래프 검증과 거의 제로에 가까운 시작 비용을 제공하여, 엄격한 안정성 요구사항을 가진 대규모 단일 플랫폼 Android 프로젝트에 강력한 선택지가 됩니다
- Koin 4.2는 지연 모듈과
CoreResolverV2로 시작 성능 격차를 줄이면서도 제로 빌드 오버헤드와 완전한 KMP 호환성을 유지합니다 - 두 프레임워크 모두 멀티 모듈 아키텍처를 지원하지만, Hilt는 컴파일 타임에 스코프 경계를 강제하는 반면 Koin은 팀 규약에 의존합니다
- Android 면접 준비에서 컴파일 타임과 런타임 트레이드오프를 이해하고, 각 프레임워크가 적합한 상황을 명확히 설명할 수 있는 것이 기본 기대치입니다
- 프레임워크 간 마이그레이션은 간단하지 않으므로, 초기 선택 시 프로젝트의 장기적인 플랫폼 전략과 확장 방향을 고려해야 합니다
연습을 시작하세요!
면접 시뮬레이터와 기술 테스트로 지식을 테스트하세요.
태그
공유
관련 기사

Kotlin 2.3 Android 면접 완벽 가이드: 이름 기반 구조 분해, KMP, 핵심 질문 정리 2026
2026년 Android 개발자 면접에서 출제되는 Kotlin 2.3 신기능을 상세히 분석합니다. 이름 기반 구조 분해, Kotlin Multiplatform, 컨텍스트 파라미터, Flow와 코루틴 코드 예제를 포함합니다.

Jetpack Compose 면접 질문 20선 (2026년)
Jetpack Compose 면접에서 자주 출제되는 20가지 질문을 해설합니다. 리컴포지션, 상태 관리, 사이드 이펙트, 내비게이션, 성능 최적화, 아키텍처 패턴을 포괄적으로 다룹니다.

Jetpack Compose: 고급 애니메이션 단계별 가이드
Compose 고급 애니메이션 완벽 가이드: 전환, AnimatedVisibility, Animatable, 제스처, 부드러운 Android 인터페이스를 위한 성능.