오상우
오상우

Categories

  • java
  • spring

IoC 컨테이너와 DI

Dependency Injection

어떤 객체가 사용하는 의존 객체를, 해당 객체 내부가 아닌 외부에서 주입 받아 사용하는 방법론. 크게 setter 를 사용하는 방법과 constructor를 사용하는 방법으로 나뉜다.

interface Tire {
  public String roll();
}

class KoreaTire implements Tire {
  @Override
  public String roll() {
    return "KoreaTire";
  }
}

class Car {
  // 의존성이 클래스 내에서 자체 생성됨.
  private Tire tire = new Tire();

  public void ride() {
    System.out.println("ride with " + tire.roll());
  }
}

...

public class Main {
  public static void main(String[] args) {
    Car car = new Car();

    car.ride();
  }
}
class Car {
  private Tire tire;

  public void Car(Tire tire) {
    this.tire = tire;
  }

  public void setTire(Tire tire) {
    this.tire = tire;
  }

  public void ride() {
    System.out.println("ride with " + tire.roll());
  }
}



...

public class Main {
  public static void main(String[] args) {
    Car car = new Car();
    Tire tire = new KoreaTire();

    // setter DI
    car.setTire(tire);

    // constructor DI
    Car car2 = new Car(tire);

    car.ride();
  }
}

위 코드와 같이 인터페이스를 활용하여 외부에서 의존성을 주입받게 되면, 해당 인터페이스를 구현하는 객체는 모두 주입이 가능해져 프로그램이 모듈화 되고, 해당 인터페이스를 구현한 목업 객체를 이용하면 유닛 테스트도 훨씬 쉽게 진행할 수 있다.

Inversion of Control

위 코드는 객체의 생성과 의존성 주입 등을 개발자가 직접 main 함수에서 처리하였다. 이렇게 되면, 객체 생성과 의존성 주입 관계가 바뀌게 될 경우, 매번 소스코드를 수정해 주어야 한다는 문제가 발생한다. 이를 해결하기 위해 나온 것이 IoC라는 개념이다. 개발자는 비즈니스 로직을 담은 객체를 짜는 데 주력하고, 그렇게 만들어진 객체를 생성하고, 관리하고, 의존성을 주입하는 것은 프레임워크(스프링) 에게 맡기는 것이 제어의 역전(Inversion of Control)이다.

스프링 IoC 컨테이너

  • BeanFactory (자바 인터페이스)
  • 어플리케이션 컴포넌트의 중앙 저장소.
  • 빈 설정 소스(.xml   java config class파일)로부터 빈 정의를 읽어들이고, 빈을 구성하고 제공한다.

  • 스프링 IoC 컨테이너가 관리하는 객체.
  • 의존성 관리 (IoC 컨테이너의 주요 목적)
  • 스코프 관리 : 빈은 기본적으로 싱글턴 객체 / 원하지 않으면 프로토타입 객체로 생성
  • 라이프사이클 인터페이스 : 빈 객체의 생성 => 소멸 라이프사이클 사이에 훅 실행 가능

Applicatoin Context

  • BeanFactory를 구현한, 실제로 가장 흔히 사용되는 Spring IoC 컨테이너 객체
  • 위에 나온 기본적 기능 외에도
  • 메세지 소스 처리 기능
  • 이멘트 발행/구독 기능
  • 리소스 로딩 기능

등의 추가 기능 제공.