본문 바로가기

Development/Spring Boot

[Spring Boot] IoC, DI, 컨테이너

1- 제어의 역전 : IoC ( Inversion of Control)

  • 말 그대로 제어의 역전
  • 내가 무언가를 호출하는게 아니라 프레임워크가 대신 호출하는 것을 말함
  • 스프링에만 극한된 개념이 아니라 여러 곳에서 나옴
  • AppConfig 등장 이후 구현 객체는 자신의 로직을 실행하는 역할만 담당함
    제어 흐름 자체를 AppConfig가 가져감
  • 코드 예시
@Override
public Order createOrder(Long memberId, String itemName, int itemPrice) {

    // IoC에 의하면 OrderServiceImpl은 memberRepository에 대한 제어권이 없음
    Member member = memberRepository.findById(memberId);
    int discountPrice = discountPolicy.discount(member, itemPrice);

    return new Order(member.getId(), itemName, itemPrice, discountPrice);

}

 

2- 프레임워크 vs 라이브러리

  • 프레임워크: JUnit
    - 개발자는 테스트 코드를 쫙 작성해.
    - 우리는 로직만 딱 작성을 하는데, JUnit에서 본인만의 라이프 사이클 속에서 로직을 실행함
    - 예시로, @BeforeEach 어노테이션이 올라가있는 메서드가 있다면 그것을 먼저 실행하고 실행하고자 했던 메서드가 실행된다는 등
    - 한 마디로 라이프사이클에서 내가 만든 로직이 콜백식으로 실행됨

  • 라이브러리
    - 내가 작성한 코드가 제어 흐름을 담당하는 것

3- 의존관계 주입 : DI ( Dependency Injection )

  • OrderServiceImpl은 DiscountPolicy 인터페이스에만 의존함. 고로 실제 어떤 구현체가 사용되는지 모름>
  • 의존관계는 정적인 클래스 의존 관계와 실행 시점에 결정되는 동적인 객체(인스턴스) 의존 관계를 분리해 생각해야 함

  • 정적인 클래스 의존관계
    - 산출물: 클래스 다이어그램
    - 클래스가 사용하는 import 코드만 보고 의존관계 쉽게 판단 가능
    - 주문 발생시 어떤 역할들이 요구되어 설계되었는지 판단 가능함
    - 요점을 한 문장으로 정리하자면, 정적인 의존관계는 애플리케이션을 실행하지 않아도 분석 가능
    - 허나 의존관계만으로는 어떤 구현체가 주입되는지 알 수 없음

  • 동적인 객체 의존관계
    - 산출물: 객체 다이어그램
    - 어플리케이션 실행 시점에서 생성된 객체 인스턴스의 참조가 연결된 의존 관계
    - 의존관계 주입: 애플리케이션 실행 시점(런타임)에 외부에서 실제 구현 객체를 생성하고, 클라이언트에 전달해 클라이언트와 서버의 실제 의존관계가 연결되는 것
    - 객체 인스턴스를 생성하고 참조값을 전달해 연결됨
    - 의존관계 주입을 사용하면 클라이언트 코드를 변경하지 않고, 클라이언트 호출 대상의 타입 인스턴스 변경 가능
      (클라이언트 코드 변경 없이 구현체 변경 가능하다는 뜻)
    - 의존관계 주입을 사용하면 정적인 클래스 의존관계 변경 없이 동적인 객체 의존관계 변경 가능
      한 마디로, 기존 정적인 클래스 다이어그램의 구조를 변경하지 않고 ( == 애플리케이션 코드를 건드리지 않고 ) 구현체만 
      변경할 수 있음

3- IoC 컨테이너, DI 컨테이너

  • AppConfig 처럼 객체를 생성하고 관리해 의존관계를 연결해주는 것은 'IoC 컨테이너' 또는 'DI 컨테이너'
  • 아에 DI 컨테이너가 좀 더 정확한 용어임.
    IoC의 핵심은 제어권이 역전. 즉, 넘어가있다는 것기에 너무 범용적인 용어임.
    그래서 후대에 특성에 맞게 DI 컨테이너로 이름을 바꿈.
  • AppConfig 코드를 보면 OrderServiceImpl을 생성할 때, 생성자 파라미터로 넘어가는 멤버 리파지터리와 할인 정책을 생성하여 집어넣어줌.
    --> 이런 것을 DI 컨테이너라 함.
  • AppConfig에 대해 용어가 많음
    - 전체의 조립을 하는 역할을 함.
    - 그래서 어셈블러 혹은 오브젝트 팩토리 등으로 불리기도 함