Guice에서 Injector를 직접 주입해도 될까?
카테고리
프로그래밍/소프트웨어 개발
서브카테고리
개발 툴
대상자
백엔드 개발자, DI 프레임워크 사용자 (중간 난이도)
핵심 요약
- Injector 직접 주입 시 성능 저하 발생:
injector.getInstance()
호출 시마다 의존성 그래프 순회로 오버헤드 발생 - JIT binding의 락 경합 문제:
jitBindingData
에 lock 걸림으로써 병목 현상 유발 - 대안: 직접 의존성 주입 권장:
@Assisted T
사용 시 child injector 재사용 가능, 6500% 성능 개선 가능
섹션별 세부 요약
1. Guice 의존성 주입 기초 개념
- Binding 정의: Module에 명시적 바인딩(explicit binding)을 통해 의존성 해결
- JIT binding 조건:
@Inject
어노테이션 없이 non-private 기본 생성자 존재 시 - 성능 문제: JIT binding 시
jitBindingData
에 lock 걸림으로써 병목 현상 발생
2. Injector 주입의 성능 문제 분석
- Factory와 AssistedInject 사용 시: child injector 생성 시마다 parent injector에 lock 걸림
- Provider
사용 시 :provider.get()
호출 시마다 동적 의존성 해결 필요 - Injector 자체 주입 시:
injector.getInstance()
호출 시마다 의존성 그래프 순회로 오버헤드 발생
3. 실험 결과 및 성능 비교
- Injector 주입 vs 직접 주입:
- ConsumerWithInjector
: 10.98ms (100,000회 실행)
- ConsumerWithDirectInjection
: 5.66ms (100,000회 실행)
- getInstance() 호출 횟수와 성능 관계:
- 1회 호출: 5.66ms
- 3회 호출: 14.51ms (선형 증가 확인)
4. 성능 저하 근본 원인 분석
- Injector 생성 시 JIT binding: 처음 생성 시
getJustInTimeBinding()
호출 - 의존성 그래프 순회 오버헤드:
InternalFactory
생성 및ConstructorInjector
호출 - Reflection 사용 시 추가 지연: 생성자 주입 시 private 생성자 사용 시 반영
결론
- Injector 직접 주입은 피해야 함:
injector.getInstance()
호출 시마다 의존성 그래프 순회로 성능 저하 - 대안: 직접 의존성 주입 또는 @Assisted 사용:
@Assisted T
로 의존성 주입 시 child injector 재사용 가능 - 성능 개선 예시:
@Assisted
사용 시 약 6500% 성능 향상 가능 (Guice 공식 문서 기준)