[SPRING]IoC 와 DI

야부엉·2023년 11월 3일
0

SPRING

목록 보기
6/45

1. IOC(제어의 역전)와 DI(의존성 주입) 이해하기

1. 개념

  • IOC : 설계 원칙
  • DI : 디자인 패턴
  • IOC는 김치볶음밥을 맛있게 만들기 위한 재료가 신선해야 방법이고, DI는 김치 볶음밥을 만드는 레시피로 비교 생각하면 된다.
  • 좋은 코드를 위해서 스프링은 IoC와 DI를 제공한다.
  • 즉, 좋은 코드를 만들기 위해서는 DI 패턴을 사용해서 IOC 설계원칙을 지켜야 한다는것이다.

2. 의존성

  • 코드에서의 의존성은 변화가 일어났을 때 코드 수정이 얼마나 일어나냐?로 판단 할 수있다. 여기서 코드 수정은 실행 문에서가 아닌 기능을 작동하는 메서드 내에서의 수정이다.

  • 강하게 결합되어있는 경우를 예를 보자.

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가 치킨이 아니라 피자를 먹고싶다고 하면, eat() 메서드 내의 치킨 객체가 아닌 Pizza 객체를 생성해야하고 eat()를 해야한다. 음식이 바뀔 때마다, 계속 수정을 해야한다는 것이 강한 결합의 특징이다.

  • 약한 결합을 예를 보자

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("피자를 먹는다.");
    }
}
  • 치킨 말고 피자를 먹고 싶을 때도 다른 부분 수정없이 실행문에 eat(new Pizza())만 추가하면 해결 된다.
  • 즉, 의존성이 약할수록 코드 수정이 적게 일어난다.

3. 주입

  • 여러 방법을 통해 필요로 하는 객체를 해당 객체에 전달하는 방법
  1. 필드에 직접 주입
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에 필요한 객체를 주입받아 사용할 수 있다.
  1. 메서드를 통한 주입
public class Consumer {

    Food food;

    void eat() {
        this.food.eat();
    }

    public void setFood(Food food) {
        this.food = food;
    }
}
  • set메서드를 통해 주입 받을 수 있다.
  1. 생성자를 통한 주입
public class Consumer {

    Food food;

    public Consumer(Food food) {
        this.food = food;
    }
}
  • 생성자 매개변수로 사용함으로써 주입이 가능.

4. 제어의 역전

  • 위의 강한 결합(= 의존성이 높은) 코드를 보면 consumer가 food를 만든다. 다르게 말하면, consumer를 통해서 food가 생성 제어 된다는것을 알 수 있다.
    - 제어의 흐름이 consumer -> food
  • 위의 약한 결합(=의존성이 낮은) 코드를 보면, food가 생성이 된 후 consumer에게 제공이 되는 것을 볼 수 있다.
    - 제어의 흐름이 food -> consumer로 역전
  • 결론적으로, 의존성 주입을 하게 되면 제어의 역전을 지키게 된다. (DI 패턴을 사용하면 IoC 지켜진다.)
profile
밤낮없는개발자

0개의 댓글