Android 개발/Kotlin

Hilt Koin 비교, 6년차가 프로젝트마다 갈라 쓰는 실전 기준

stackD 2026. 10. 1. 18:00
반응형

 

@AndroidEntryPoint, @Module, @InstallIn, @Provides… 화면 하나에 어노테이션이 네다섯 개. 6년째 이걸 타이핑하다가 문득 손을 멈췄어요. 우리 앱, 정말 Dagger 그래프가 필요한 규모일까요?

 

이 질문에 답하려고 스펙표를 또 뒤지는 대신, 저는 프로젝트 성격별로 나눠 쓰는 기준을 정리해봤습니다. Hilt Koin 비교는 승패 판정이 아니라 "이럴 땐 이걸, 저럴 땐 저걸" 고르는 분기 문제라고 봅니다.

 

안드로이드 의존성 주입, 굳이 안 넣어도 되는 규모

일단 솔직하게 말씀드릴게요. 화면 서너 개짜리 프로토타입에 Dagger 그래프를 얹는 건 명백한 과잉입니다.

 

DI 프레임워크가 제값을 하는 시점은 따로 있어요. 스코프(화면·세션·앱 수명)가 뒤섞이고, 테스트할 때 가짜 객체로 갈아끼우는 일이 반복되기 시작할 때죠. 그 전까지는 생성자에 직접 넘겨주는 수동 주입으로 충분한 경우가 많습니다.

 

교체 비용도 대부분 과대평가되더라고요. 저도 예전에 사내 사이드 프로젝트에서 "힐트(Hilt) 무겁다"며 갈아엎을 뻔했는데, 막상 현 구조를 손보는 쪽이 훨씬 남는 장사였습니다. 프레임워크를 바꾸기 전에, 지금 쓰는 걸 제대로 조율하는 게 먼저라고 보시면 되겠습니다.

 

 

Hilt 빌드 느림, 진짜 범인은 kapt였습니다

힐트는 Dagger 기반이라 코드 생성으로 그래프 오류를 컴파일 시점에 잡아줍니다. 게다가 젯팩(Jetpack)의 ViewModel·WorkManager·Navigation 통합이 압도적이에요. 구글이 공식 추천하는 데는 다 이유가 있는 거죠.

 

근데 "힐트는 무겁다"의 진짜 범인은 힐트가 아니라 kapt 인 경우가 많습니다. kapt 는 Java stub 을 생성하는데, 이게 kotlinc 분석 비용의 약 3분의 1을 얹거든요. 비교하자면, 컴파일 한 번 할 때마다 짐을 30%씩 더 지고 뛰는 셈입니다.

 

Dagger 2.48부터는 KSP 를 지원해요. 아래 한 줄만 바꿔도 빌드 체감이 달라지는 경우가 있습니다.

 

// kapt(hilt-compiler) 대신 ↓
ksp("com.google.dagger:hilt-compiler:<version>")

 

버리기 전에 이 스위치부터 눌러보시길 권합니다. 다만 KSP2 환경의 Dagger/Hilt 비호환 이슈(google/dagger #4303)는 Dagger 2.54에서 해결됐으니, 그 이전 버전 조합에서만 주의해서 올리시면 돼요.

 

 

Koin 컴파일타임 안전성, 이제 옛날 프레임입니다

"힐트는 안전, 코인(Koin)은 배포 후 터진다." 저도 오래 이렇게 알고 있었어요. 순수 코틀린 DSL 에 런타임에 의존성을 해석하니까, 잘못 등록하면 실행 중에 MissingKoinDefinitionException 이 나거든요.

 

근데 이 프레임, 2023년까지만 유효했던 얘기입니다. Koin Annotations(KSP 기반)와 Koin Compiler Plugin 1.0.0 이 매 빌드마다 의존성을 컴파일 시점에 검증해줘요. 예전에 테스트 코드에 넣던 checkModules() 는 코인 4.0부터 deprecated 됐고, 지금은 verify() 나 컴파일러 플러그인 쪽으로 옮기는 게 권장됩니다.

 

물론 과신은 금물이에요. @Single(createdAtStart=true) 가 조용히 누락되는 케이스(koin #2425)도 보고된 적이 있는데, 이건 이후 패치에서 수정됐습니다. 다만 verify() 가 못 잡는 설정도 일부 있다고 하니, 프로덕션 전면 신뢰는 조금 이르다고 생각해요. 그래도 "코인은 런타임 위험"이라는 낡은 인상은 이제 갱신하실 필요가 있어요.

 

KMP 의존성 주입은 Koin이 사실상 기본입니다

여기서 선택이 확 갈립니다. 힐트는 Dagger 기반이라 안드로이드 전용이에요. iOS 팀이 "DI 설정 공유하자"고 하면 힐트는 그 대화에 낄 수가 없습니다.

 

멀티모듈 의존성 주입에서 코틀린 멀티플랫폼(KMP) 공용 모듈까지 커버해야 한다면, 코인이 정식 지원이라 사실상 기본값이 됩니다. 라이브러리나 SDK 를 만들 때도 마찬가지예요. 힐트를 라이브러리에 넣으면 그걸 가져다 쓰는 앱에까지 Dagger 그래프를 강요하게 되는데, 코인은 격리성이 좋아서 이런 부담이 덜하거든요.

 

그래서 제가 말하는 "갈라 쓰기"는 한 코드베이스에 둘을 섞자는 게 아닙니다. 그건 유지보수 지옥이에요. 프로젝트·모듈 경계에서 나누자는 거죠.

 

  1. 순수 안드로이드 앱 → 힐트 (젯팩 통합·컴파일 안전성)
  2. KMP 공용 모듈 → 코인 (안드로이드 밖으로 나가야 하니까)
  3. 배포용 라이브러리·SDK → 코인 (소비 앱에 그래프 강요 안 함)

 

 

안드로이드 DI 프레임워크 2026, 마지막 분기는 팀입니다

기술 스펙만큼 중요한 게 조직 구조입니다.

 

힐트의 컴파일타임 강제성은 주니어가 많은 대규모 팀에 가드레일이 돼요. 실수를 빌드가 막아주니까요. 반대로 코인의 유연함은 소규모 시니어 팀의 생산성을 살립니다. 어노테이션 프로세싱 없이 빠르게 붙였다 뗐다 할 수 있으니까요.

 

버전 조합도 참고로 정리해두면, 코인은 4.1을 거쳐 지금은 4.2 라인(현재 4.2.1)이 최신 궤도예요. Annotations·Compiler Plugin·코틀린은 서로 버전을 맞춰줘야 해서 릴리즈 노트를 꼭 대조하시는 게 좋겠습니다.

 

성능 얘기도 빠질 수 없는데요. "힐트가 시작 시간 15~20% 빠르다"는 수치가 돌아다니지만, 이건 단일 블로그 벤치마크라 표본 신뢰도가 제한적입니다. 대부분의 앱에서는 체감조차 안 되는 차이일 가능성이 커요. 성능을 1순위 결정 요인으로 두지는 마시길 권합니다.

 

 

결국 바꾸지 않을 때를 아는 게 판단력

정리하자면 결정 축은 네 개예요. KMP 를 하느냐, 젯팩에 얼마나 기대느냐, 팀 규모와 주니어 비율은 어떤가, 빌드 시간에 얼마나 예민한가.

 

힐트가 무겁게 느껴진다면 프레임워크를 버리기 전에 kapt 부터 의심하시고, 코인이 런타임에 터질까 무섭다면 그 인상을 최신 버전으로 한번 갱신해보셔야 합니다. 이 두 가지만 짚어도 "굳이 이주해야 하나"라는 고민의 절반은 정리되는 셈이죠.

 

6년을 굴려보고 제가 얻은 결론은 좀 싱거워요. 개발자의 무기는 프레임워크를 얼마나 아느냐가 아니라, 언제 바꾸지 않을지를 아는 판단력이더라고요. 지금 쓰는 그 DI, 정말 갈아엎어야 하는 문제인지 아니면 kapt 한 줄 문제인지 — 오늘 우리 앱은 그중 어느 쪽에 서 있을까요?

 

반응형
LIST