Android依存性注入:Hilt vs Koin 完全ガイドと面接質問集 2026
HiltとKoinの違いをコード例・パフォーマンスベンチマーク・面接頻出質問で徹底比較。Hilt 2.57、Koin 4.2対応の2026年最新ガイド。

Androidアプリケーション開発において、依存性注入(DI)はクラス間の結合度を下げ、テスト容易性を高めるための基本的な設計手法である。2026年現在、Androidエコシステムを支配するDIフレームワークは2つ存在する。Googleが公式に推奨するコンパイル時ソリューションHilt(バージョン2.57.1、Dagger上に構築)と、軽量なランタイムサービスロケーターであるKoin(バージョン4.2.1)である。どちらを選択するかは、ビルド時間、起動パフォーマンス、テスタビリティ、そしてチームのオンボーディング速度に直接影響する。
Hiltはコンパイル時に依存関係グラフ全体を検証し、バインディングが不足している場合はビルドを失敗させる。KoinはKotlin DSLを使用してランタイムに依存関係を解決するため、設定エラーは該当するコードパスが実行された時点で初めて検出される。この根本的な違いが、2つのフレームワーク間のすべてのトレードオフを決定づけている。
Hiltの内部動作メカニズム
HiltはAndroidのライフサイクルクラスにマッピングされたDaggerコンポーネントを生成する仕組みである。@HiltAndroidAppアノテーションがコンパイル時にコード生成をトリガーし、宣言されたすべてのバインディングに対してファクトリーとプロバイダーを生成する。Hilt 2.48以降、推奨されるアノテーションプロセッサとしてKSP(Kotlin Symbol Processing)がKAPTに取って代わり、アノテーション処理時間をおよそ半分に短縮した。
典型的なHiltのセットアップは、バインディングを宣言するモジュール、エントリポイント(Activity、Fragment、またはViewModel)、そして@HiltAndroidAppでアノテーションされたApplicationクラスの3つの要素で構成される。
@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はバージョンⅡ.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の2つの選択肢の中では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 インターフェイスのためのパフォーマンス。