학습일지

[Spring] IoC, DI, Autowired

Merge Log 2025. 9. 15. 11:36

IoC, DI 가 무엇인가?

IoC, DI 는 객체지향의 SOLID 원칙 그리고 GoF 의 디자인 패턴과 같은 설계 원칙 및 디자인 패턴

  • 더 자세히는 IoC 는 설계 원칙, DI 는 디자인 패턴을 의미한다
  • 어떤 객체가 사용하는 의존 객체를 직접 만들어 사용하는 것이 아닌, 주입 받아 사용하는 방법을 말한다

Spring IoC 컨테이너

  • BeanFactory()
  • 애플리케이션 컴포넌트의 중앙 저장소 역할
  • 빈 설정 소스로부터 빈 정의를 읽고, 빈을 구성 및 제공한다

Autowired

  • 해당 기능을 사용하면 스프링이 자동으로 의존성을 주입한다
  • required 옵션이 true 라면 의존성이 무조건 필수이기 때문에 의존성 없이 빈을 생성할 수 없다
  • 사용할 수 있는 위치는 아래 세가지
    • 생성자
    • 세터(Setter)
    • 필드
  • 같은 타입의 빈이 여러개일 경우
    • @Primary 를 통해 같은 타입의 빈이 존재할때 먼저 선택할 빈을 설정할 수 있다
    • @Qualifier 를 통해 빈의 이름(Bean ID)으로 선택하여 주입할 수 있다
    • 혹은 Collection 형태로 해당 타입의 모든 빈을 주입받을 수 있다
  • 동작 원리는 BeanPostProcessor 를 통해 동작 → 빈 라이프사이클 인터페이스의 구현체에 의해 동작
    • bean Instance 를 만든 이후 초기화 라이프사이클을 동작한다 (Initialization Lifecycle)
    • 초기화 라이프사이클 이전/이후에 부가적인 동작을 할 수 있는 또다른 라이프사이클 콜백이 있고 그에 해당하는 것이 BeanPostProcessor 이다
    • Autowired 는 Initialization 전에 실행된다 → postProcessBeforeInitialization 시점에 실행
    • BeanFactory(ApplicationContext) 는 BeanPostProcess 타입의 빈을 찾고 처리한다 → 이때 AutowiredAnnotationBeanPostProcessBeanPostProcess 타입의 빈으로 등록되어 있는 것

참고

  • 빈 주입시 필드 이름을 특정 빈 이름과 똑같이 지정하면 해당 빈이 선택되어 주입된다.
    (권장하지 않음)

컴포넌트 스캔

  • 자동으로 특정 Annotation 이 등록된 객체를 식별 후 빈으로 등록하는 기능
  • 수동으로 빈을 등록하는 방법에는 자바(@Configuration) 과 xml 등을 통한 방식이 있고 ApplicationContext 를 통해 빈으로 등록 및 처리하는 과정이 존재한다
  • 우리가 사용하는 스프링 부트의 @SpringBootApplication@Configuration 이다 즉 부트의 시작점 코드 자체가 빈 수동처리를 위한 자바 config 코드인 것 이다 + 컴포넌트 스캔 Annotation 또한 추가되어있다
  • 중요한 것은 "스캔은 어디부터 어디까지 스캔할 것 인가" / "스캔 중 어떤 것들을 제외해야하는가" 이다
  • 실제 스캐닝은 ConfigurationClassPostProcessor 라는 BeanFactoryPostProcessor 에 의해 처리된다

스프링에서 싱글톤을 보장하는 비밀

  • 우리가 자바를 통해 수동으로 빈을 등록하는 방법에는 @Configuration 을 사용할 수 있다
  • AnnotationConfigApplicationContext(AppConfig.class) 를 통해 getBean(AppConfig.class) 를 한다면 우리가 실제로 만든 클래스가 아닌 AppConfig$$EnhancerBySpringCGLIB$$~~ 형태의 클래스가 사용된다
  • 해당 바이트코드 조작을 통해 싱글톤을 보장한다 (예시: "만약 해당 빈이 있다면 반환 / 없다면 빈 생성")