나는 hilt로 마이그레이션했습니다.
의존성 주입 구조의 난장판을 정리하고, 보일러플레이트를 줄이고, 팀 온보딩을 쉽게 만들기 위해 도입했습니다.
그리고 공정하게 말하자면 실제로 그 모든 역할을 해주긴했습니다.
하지만 그다음에 나는 뭔가 이상한점을 발견했습니다.
내 앱에 콜드 스타트가 눈에 띄게,, 전혀 콜드하지 않았습니다.
그냥 대놓고 느렸어요.
그래서 코드를 확인했고,
백엔드를 탓했고,
안드로이드 스튜디오를 재시작했습니다. (확실하게 하게위해 2번이나요)
그리고 모든 개발자가 꺼리는 행동을 했습니다. 프로파일러를 열었습니다.
결과는 이랬습니다.
Hilt는 자기 역할을 잘 하고 있었습니다.
제가 명령한 모든 것들을 전부 초기화하고 있었거든요.
불행하게도 너무 많은 것을 시킨 사람이 바로 저였다는 점이었습니다.
문제: 즉시 주입으로 인한 사망
실제로 벌어진 일은 이렇습니다.
저는 네트워크 클라이언트, 레포지토리, Room DB 접근 객체, 애널리틱스 로거 같은 여러 의존성들을 전부 @SingletoneComponent로 옮겼습니다.
왜냐면 대부분 튜토리얼이 그렇게하니까요.
제가 깨닫지못했던 점은,
Hilt가 싱글톤을 앱 실행시점에 즉시 생성한다는 것이었습니다.
스플래시 화면에 애니메이션이 제대로 유연하게 한 번 움직이기도 전에 말이죠
결국 제 Application.onCreate()는 점점 병목 지점이 되어가고있었습니다.
해결 방법: 짧은 패닉 이후
문제가 수성 역행 때문도 아니고, 어딘가에서 날뛰는 컴포즈 재구성 떄문이 아니라는 걸 받아들이고 나서야
저는 자리에 앉아서 리팩토링을 시작했습니다.
아래는 실제로 동작했던 방법입니다.
1. 무거운 의존성에는 Provider<T> 또는 @Lazy를 사용해라
만약 즉시 필요하지 않은 것이라면,
당장 주입을 하지마세요
@Inject lateinit var heavyService: Provider<MyHeavyService>
이렇게 하면 get()을 호출하는 순간에만 실제로 객체가 생성됩니다.
앱 실행 시점에 세상 전체를 한꺼번에 초기화할 필요가 없습니다.
2. 모든 것을 SingletonComponent에 주입하지마라
이건 저를 깨워주는 계기였습니다.
저는 기능단위로만 쓰이는 로직까지 전부 전역스코프에 주입하고 있었습니다.
이말에 의미는 곳 온보딩 플로우에서만 쓰이는 것들 조차 앱 시작 시점에 생성되고 있었다는 뜻이었죠.
그래서 대신 다음과 같이 바꾸기 시작했습니다.
- ViewModels에는 ActivityRetainedComponent
- 화면 단위 로직에는 ActivityComponent 또는 FragmentComponent
스코프를 조금 더 의미있게 했습니다.
그 결과 콜드 스타트 속도는 거의 즉각적으로 빨라졌습니다.
3. 꼭 필요하지않다면 최대한 지연시켜라
정말로 크래시 리포팅, 리모트 컨피그, 애널리틱스, A/B 테스트 그리고 서너개의 SDK가 앱 실행 후 0.5초 안에
전부 돌아가고 있어야하나요?
저는 그렇지 않았습니다.
그래서 그런 것들은 전부 지연초기화를 사용하는
코루틴 백그라운드로 밀어냈습니다.
CoroutineScope(Dispatchers.Default).launch {
Analytics.init()
RemoteConfig.sync()
OtherStuff.wakeUp()
}
사용자는 즉시 UI를 보게 됩니다.
무거운 작업은 뒤에서 조용히 실행됩니다.
서로 윈윈입니다.
4. @Provides 메서드는 최대한 깔끔하게 유지하라
제 @Provides 메서드는 어느새 자기만의 비즈니스 로직을 가진 작은 팩토리 처럼 변해있었습니다.
솔직히 말해서, 자랑스러울 만한 상태는 아니었죠.
그래서 복잡한 초기화 로직은 헬퍼 클래스나 설정 빌더로 옮기고
hilt binding은 가볍고 예측가능하게 유지했습니다.
만약 @Provdes 블록이 몇 줄을 넘기거나,
.build()가 3번씩 등장한다면
아마도 너무 많은 일을하고있는것입니다.
5. 추측하지말고, 측정하라
프로파일러는 거짓말하지 않습니다.
저는 onCreate가 얼마나 걸리는지 확인하기 위해 로그 마커를 추가했고,
안드로이드 스튜디오의 프로파일러를 통해
어떤 것들이 너무 이른시점이 초기화되고 있는지를 확인했습니다.
데이터가 손에 들어오자 리팩토링 방향은 명확해졌고,
팀에 설명하고 설득하는 것도 훨씬 수월해졌습니다
배운점들
- Hilt가 문제인건아닙니다. @SingletoneComponent를 과도하게 사용하고, 너무 많은 것들을 너무 이른시점에 주입한게 문제였죠
- 중요하지 않은 의존성을 지연시키는 것만으로도 앱 시작 성능은 크게 개선될 수 있습니다.
- 올바른 스코프 설계는 좋은 아키텍처일 뿐만 아니라 좋은 UX기도 합니다.
- 지연 주입은 훌륭한 친구입니다. 프로파일러도 마찬가지이고요.
Hilt로 마이그레이션을 계획중이거나, 이미 사용하고 있다면
이 글을 하나의 리마인더로 받아들여주세요
강력한 도구 일 수록 신중한 사용이 필요합니다.
그리고 힐트로 깔끔하게 정리한뒤에 앱이 더 느려진거같다면
문제가 있는건 앱이 아니라 앱에 시작전략일지도몰라요.
'영어 데일리' 카테고리의 다른 글
| MVI 보일러플레이트는 이제 작별, 코드를 대신 작성해주는 BuildKt MVI 라이브러리 소개 (1) | 2026.01.06 |
|---|---|
| 보일러플레이트 코드를 그만작성하세요: 매일 사용하는 컴포즈 헬퍼 유틸리티 (1) | 2026.01.05 |
| RemoteCompose: 컴포즈에서 서버 주도 UI를 위한 또 다른 패러다임 (0) | 2025.12.02 |
| Bosch 안드로이드 개발자 인터뷰 경험 (0) | 2025.12.01 |
| 불필요한 Recompositions 줄이기: Compose를 위한 실용적인 최적화 기법 3가지 (0) | 2025.11.25 |