본문 바로가기

공부/Spring

스프링 - DI

Spring_DI

스프링 IoC/DI - 제어의 역전/의존성 주입 01

프로그래임에서 의존성이란?

예제 01 : 의존관계를 직접 해결

의사 코드

  • 운전자가 자동차를 생산한다.
  • 자동차는 내부적으로 타이어를 생산한다.

자바로 표현

new Car();
Car 객체 생성자에서 new Tire();

그리고 의존성을 단순하게 정의하면 다음과 같다

  • 의존성은 new 다.
  • new를 실행하는 Car와 Tire 사이에서 Car가 tire에 의존한다.

전체가 부분에 의존한다.

sequenceDiagram Driver->>+Car: 1. 자동차 생산 Car->>+Tire: 2. 타이어 생산 Tire->>+KoreaTire: 3. 타이어 생산 위임 KoreaTire-->>-Tire: . Tire-->>-Car: . Car-->>-Driver: .

인터페이스 Tire.java

public interface Tire {
    String getBrand();
}

쿨래스 KoreaTire.java

public class KoreaTire implements Tire{
    @Override
    public String getBrand() {
        return "코리아 타이어";
    }
}

쿨래스 Car.java

public class Car {
    Tire tire;

    public Car(){
        // 의존 관계가 일어나는 부분
        tire = new KoreaTire();
        // tire = new AmericaTire();
    }

    public String getTireBrand(){
        return "장착 타이어 : " + tire.getBrand();
    }
}

쿨래스 Driver.java

public class Driver {
    public static void main(String[] args) {
        Car car = new Car();
        System.out.println(car.getTireBrand());
    }
}

정리

  • 자동차는 타이어에 의존한다.
  • 운전자는 자동차를 사용한다.
  • 운전자가 자동차에 의존한다고 봐도 된다.
  • 자동차의 생성자 코드에서 tire 속성에 새로운 타이어를 생성해서 참조할 수 있게 해주었다.

위와 같은 의존의 문제점

  • Car와 Tire의 긴밀한 결합이 생긴다.
  • Tire가 바뀌면 Car도 바껴야 한다.

의존성 주입 (Dependency Injection)

위와 같은 의존의 문제점을 해결하기 위한 방법

의존성 주입 방법

  1. 생성자를 통한 방법
  2. 속성을 통한 방법
  3. 필드를 통한 방법

예제 02 : 스프링 없이 의존성 주입하기1 - 생성자를 통한 의존성 주입

의사 코드

  • 운전자가 타이어를 생산한다.
  • 운전자가 자동차를 생산하면서 타이어를 장착한다.

자바로 표현 - 생성자 인자 이용

Tire tire = new KoreaTire();
Car car = new Car(tire);

주입이란?

주입이란 말은 외부에서라는 뜻을 내포하고 있는 단어다.
결국 자동차 내부에서 타이어를 생산하는 것이 아니라 외부에서 타이어를 자동차에 장착하는 작업이 주입이다.

외부에서 생산된 tire 객체를 Car 생성자의 인자로 주입(장착) 하는 형태 구현한다.

sequenceDiagram Driver->>+Tire: 1. 타이어 생산 Tire->>+KoreaTire: 2. 타이어 생산 위임 KoreaTire-->>-Tire: . Tire-->>-Driver: . Driver->>+Car: 3. 자동차 생산 & 타이어 장착 Car-->>-Driver: .

쿨래스 Car.java

  • 생성자에 인자가 추가됨
public class Car {
    Tire tire;

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

    public String getTireBrand(){
        return "장착 타이어 : " + tire.getBrand();
    }
}

쿨래스 Driver.java

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

        System.out.println(car.getTireBrand());
    }
}

정리

  • 예제1보다 유연성이 있다. (예제1에서는 Car가 구체적으로 어떤 타이어를 생상할지 결정함)
  • 예제2는 운전자가 자동차를 생산할 때 어떤 타이어를 생산해서 장착할까를 고민하지 않고 운전자가 차를 생산할 때 어떤 타이어를 장착할지를 결정한다.
  • Car는 그저 Tire 인터페이스를 구현한 어떤 객체가 들어오기만 하면 정상 작동 가능하다. -> 확장성이 좋다.

예제 03 : 스프링 없이 의존성 주입하기2 - 속성을 통한 의존성 주입

의사 코드

  • 운전자가 타이어를 생산한다.
  • 운전자가 자동차를 생산한다.
  • 운전자가 자동차에 타이어를 장착한다.

자바로 표현 - 속성 접근자 메소드 사용

Tire tire = new KoreaTire();
Car car = new Car();
car.setTire(tire);

속성을 통한 의존성 주입

  • 원할 때 Car의 Tire를 교체할 수 있다.
sequenceDiagram Driver->>+Tire: 1. 타이어 생산 Tire->>+KoreaTire: 2. 타이어 생산 위임 KoreaTire-->>-Tire: . Tire-->>-Driver: . Driver->>+Car: 3. 자동차 생산 Car-->>-Driver: . Driver->>+Car: 4. 타이어 장착 Car-->>-Driver: .

쿨래스 Car.java

  • 생성자가 없음
  • get/set 속성 메소드 추가
public class Car {
    Tire tire;

    public Tire getTire(){
        return tire;
    }

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

    public String getTireBrand(){
        return "장착 타이어 : " + tire.getBrand();
    }
}

쿨래스 Driver.java

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

        System.out.println(car.getTireBrand());
    }
}

예제 04 : 스프링 통한 의존성 주입

의사코드

  • 운전자가 종합 쇼핑몰에서 자동차를 구매 요청한다.
  • 종합 쇼핑몰은 자동차를 생산한다.
  • 종합 쇼핑몰은 타이어를 생산한다.
  • 종합 쇼핑몰은 자동차에 타이어를 장착한다.
  • 종합 쇼핑몰은 운전자에게 자동차를 전달한다.
sequenceDiagram Driver->>+종합 쇼핑몰: 1. 종합 쇼핑몰 방문 종합 쇼핑몰->>-Driver: . Driver->>+종합 쇼핑몰: 2. 자동차 구매 종합 쇼핑몰->>+Car: 3. 자동차 생산 Car-->>-종합 쇼핑몰: . 종합 쇼핑몰->>+Tire: 4. 타이어 생산 Tire->>+KoreaTire: 5. 타이어 생산 위임 KoreaTire-->>-Tire: . Tire-->>-종합 쇼핑몰: . 종합 쇼핑몰->>+Car: 6. 타이어 장착 Car-->>-종합 쇼핑몰: . 종합 쇼핑몰->>-Driver: 자동차 전달

종합 쇼핑몰 역할은 [스프링 프레임워크] 다.

// 종합 쇼핑몰 == DI 컨테이너
ApplicationContext context = ...;

// 상품 구매
Car car = context.getBean("car", Car.class);
Tire tire = context.getBean("tire", Tire.class);

// 타이어 장착
car.setTire(tire);

System.out.println(car.getTireBrand());

예제 05 : 스프링 통한 의존성 주입 - @Autowired를 통한 속성 주입

의사코드 - 점점 더 현실 세계와 닮아간다.

  • 운전자가 종합 쇼핑몰에서 자동차를 구매 요청한다.
  • 종합 쇼핑몰은 자동차를 생산한다.
  • 종합 쇼핑몰은 타이어를 생산한다.
  • 종합 쇼핑몰은 자동차에 타이어를 장착한다.
  • 종합 쇼핑몰은 운전자에게 자동차를 전달한다.

의사코드는 위와 동일하다.

@Autowired 어노테이션을 이용하면 설정자 메소드를 이용하지 않고도 종합 쇼필몰에서 속성을 주입한다.

public class Car{
    @Autowired
    Tire tire;

    public String getTireBrand(){
        return "장착된 타이어 : " + tire.getBrand();
    }
}

'공부 > Spring' 카테고리의 다른 글

스프링 인터셉터 설정  (0) 2019.08.06
스프링 트랜잭션  (0) 2019.08.06
스프링부트 아파치 mod_jk 연동하기  (0) 2019.07.14
[Boot] JPA 네이밍 전략  (0) 2019.03.11
[Boot] 의존 설정  (0) 2019.03.11