IoC / DI

김나영·2023년 6월 27일
0

Spring

목록 보기
12/38

DI

  • 객체를 직접 생성하는게 아닌 외부에서 생성한 후 주입하는 방식

의존성

  • 하나의 코드가 다른 코드를 필요로 하는 것

강한 의존성(결합)

public class Consumer {
    void eat() {
        Chicken chicken = new Chicken();
        chicken.eat();
    }
    public static void main(String[] args) {
        Consumer consumer = new Consumer();
        consumer.eat();
    }
}
class Chicken {
    public void eat() {
        System.out.println("치킨을 먹는다.");
    }
}
  • 코드가 실행되는데 있어서는 아무런 문제가 없지만 만약 Consumer 가 치킨이 아니라 피자를 먹고 싶어 한다면? 많은 수의 코드 변경이 불가피함

  • Consumer 와 Chicken 의 관계는 강한 결합

약한 결합 및 약한 의존성

  • Java의 Interface를 활용하면 약하게 만들 수 있음
public class Consumer {

    void eat(Food food) {
        food.eat();
    }
    public static void main(String[] args) {
        Consumer consumer = new Consumer();
        consumer.eat(new Chicken());
        consumer.eat(new Pizza());
    }
}
interface Food {
    void eat();
}
class Chicken implements Food{
    @Override
    public void eat() {
        System.out.println("치킨을 먹는다.");
    }
}
class Pizza implements Food{
    @Override
    public void eat() {
        System.out.println("피자를 먹는다.");
    }
}
  • Interface 다형성의 원리를 사용하여 구현하면 고객이 어떠한 음식을 요구하더라도 쉽게 대처할 수 있음

주입

  • 여러 방법을 통해 필요로 하는 객체를 해당 객체에 전달하는 것

필드에 직접 주입

public class Consumer {
    Food food;
    void eat() {
        this.food.eat();
    }
    public static void main(String[] args) {
        Consumer consumer = new Consumer();
        consumer.food = new Chicken(); // 필드에 직접 주입
        consumer.eat();
        consumer.food = new Pizza(); // 필드에 직접 주입
        consumer.eat();
    }
}
  • Food를 Consumer에 포함 시키고 Food에 필요한 객체를 주입받아 사용

메서드를 통한 주입

public class Consumer {
    Food food;
    void eat() {
        this.food.eat();
    }
    public void setFood(Food food) {
        this.food = food;
    }
    public static void main(String[] args) {
        Consumer consumer = new Consumer();
        consumer.setFood(new Chicken()); // 메서드로 주입
        consumer.eat();
        consumer.setFood(new Pizza()); // 메서드로 주입
        consumer.eat();
    }
}
  • set 메서드를 사용하여 필요한 객체를 주입받아 사용

생성자를 통한 주입

public class Consumer {
    Food food;
    public Consumer(Food food) {
        this.food = food;
    }
    void eat() {
        this.food.eat();
    }
    public static void main(String[] args) {
        Consumer consumer = new Consumer(new Chicken()); // 생성자로 주입
        consumer.eat();
        consumer = new Consumer(new Pizza()); // 생성자로 주입
        consumer.eat();
    }
}
  • 생성자를 사용하여 필요한 객체를 주입받아 사용

IoC(Inversion of Control)

  • 메서드나 객체의 호출 작업은 개발자가 결정하는 것이 아니라 외부에서 결정하는 것

  • 제어의 역전(제어의 흐름을 바꾼다)

ex)

  • Consumer가 직접 Food를 만들어 먹었기 때문에 새로운 Food를 만들려면 추가적인 요리준비(코드변경)가 불가피

    • 그렇기 때문에 이때는 제어의 흐름이 Consumer → Food
  • 이를 해결하기 위해 만들어진 Food를 Consumer에게 전달해주는 식으로 변경함으로써 Consumer는 추가적인 요리준비(코드변경) 없이 어느 Food가 되었든지 전부 먹을 수 있게 됨

    • 결과적으로 제어의 흐름이 Food → Consumer 로 역전

0개의 댓글