본문 바로가기
Stack/Spring

DI 와 Ioc의 원리와 사용법

by 김코딩개발자 2022. 5. 29.

 강한 결합

  • 어떤 객체를 다른 클래스에서 생성하여 사용하였을 때, 해당 객체에 변경을 가하면 해당 객체를 생성한 다른 클래스에서도 똑같이 변경을 해줘야 하는 상태를 의미한다.
    다음 예시를 통해 더 자세히 알아보자.

1. Animal이라는 객체를 선언

public class Animal {
}

2. Cat이라는 클래스에서 Animal 객체를 생성

public class Cat{
    public Animal animal;
    
    public Cat() {
        this.animal = new Animal();
    }
}

3. Animal 클래스에서 Animal 객체에게 이름을 지어준다면,

public class Animal {
    public Animal(String name) {
    }
}

4. Cat 클래스에 있는 Animal 객체에게도 해당 변경사항을 적용시켜 줘야한다.

public class Cat{
    public Animal animal;
    
    public Cat() {
        this.animal = new Animal(String name);
    }
}
  • 문제점 : 만약 Animal 객체를 Dog, Chicken, Cow 같은 다른 클래스에서도 생성했었다면,
    변경사항을 수정하는데 더 긴 시간이 걸렸을 것이다. 이는 유지보수 측면에서 정말 최악일 수 있다.

  • 해결책 : 모든 클래스에서 객체를 생성하고 있기 때문에 이와 같은 문제가 발생하고 있다.
    그럼 객체를 한 번만 생성하고, 해당 객체를 재사용 한다면 이 문제는 해결될 수 있다.

약한 결합

  • 위와 같은 해결책을 사용하는 것을 약한 결합이라고 한다. 약한 결합은 강한 결합과 반대로 객체를 변경해도 다른 곳에 아무런 영향이 주지 않는다.
    다음 예시를 통해 더 자세히 알아보자.

1. Animal 객체를 생성 (Animal 객체를 한 번만 생성)

public class Animal {
}

Animal animal = new Animal();

2. Cat 클래스 선언 및 객체 생성 (Animal 객체를 재사용)

public class Cat {
    private final Animal animal;
    
    public Cat(Animal animal) {
        this.animal = animal;
    }
}

Cat cat = new Cat(animal);

3. Animal 객체에게 이름을 지어줘도,

public class Animal {
}

Animal animal = new Animal(String name);

4. 변경을 할 데가 없다.

public class Cat {
    private final Animal animal;
    
    public Cat(Animal animal) {
        this.animal = animal;
    }
}
Cat cat = new Cat(animal);
  • 이처럼 생성된 객체를 재사용하면 변경사항을 한 번만 적용하면 되기 때문에 유지보수에도 상당히 유리한 것을 알 수 있다.

의존성 주입(DI)을 통한 제어의 역전(IoC)

위에서 코드로 표현한 것을 이번엔 그림으로 나타내 보자.

  • 강한 결합

    강한 결합에서는 Animal 객체를 변경하면 Cat 클래스 내에 있는 Animal 객체도 똑같이 변경해줘야 하기 때문에 Animal 클래스에 의해 Cat클래스가 제어되고 있음을 볼 수 있다.

  • 약한 결합

    하지만 약한 결합에서는 객체를 따로 생성하기 때문에 객체를 필요시에만 가져다 쓸 수 있다. 이렇게 객체가 상황에 맞게 쓰여지는 것을 의존성 주입(Dependency Injection)이라고 한다.
    그리고 DI가 발생하면서 객체를 변경하면 해당 객체를 재사용한 곳에 자동적으로 반영이 되기 때문에 제어흐름이 뒤바뀌는 것을 알 수 있다. 이렇게 제어흐름이 바뀌는 것을 제어의 역전(Inversion of Control)이라고 한다.

빈(Bean)으로 객체 생성 및 관리하기

  • DI를 위해서는 객체생성을 해야하는데 Spring Framework(Bean, Spring IoC)에서 그 역할을 대신 해준다.
    Bean은 스프링이 관리하는 객체를 의미하고,
    Spring IoC는 그런 Bean을 모아둔 통이라고 생각하면 된다.

 

============================================================================================

 

위 포스트에서 요점요약 

 

객체를 생성하는 클래스가  객체를 부르는 클래스에 의해서 통제되면 강한결합 그것을

DI(의존성 주입)을 통해 

객체를 부르는클래스 객체 생성클래스를 통제한다

부르는 클래스에서

파라미터에 클래스와 객체를넣고

맴버변수 private final 을 사용함으로써

새로운 객체를 생성하는 것이아니라 

 

이렇게 하여 

객체를 부르는 클래스가 통제되는것이다

 

이것을 

IoC (inversion of control: 제어의 역전)

이라고 부르는것이다

 

강의에서는 가위를 예시로 들었는데

 

  • 용도에 맞게 필요한 객체를 그냥 가져다 사용
    • "DI (Dependency Injection)" 혹은 한국말로 "의존성 주입"이라고 부릅니다.
  • 사용할 객체가 어떻게 만들어졌는지는 알 필요 없음
  • 실생활 예제) 가위의 용도별 사용
    • 음식을 자를 때 필요한 가위는? → 부엌가위 (생성되어 있는 객체 kitchenScissors)
    • 무늬를 내며 자를 때 필요한 가위는? → 핑킹가위 (생성되어 있는 객체 pinkingShears)
    • 정원의 나무를 다듬을 때 필요한 가위는? → 전지가위 (생성되어 있는 객체 pruningShears)


이것이 프로그램의 유지보수에 더 효율적이다.

 

 

문제는...

가위로 예시를 들면 가위를 쓰기전에 가위를 만들어 놓아야 필요할때 가위를 쓸수있다

하지만 스프링은 객체를 쓰지않으면 미리 객체를 생성해두지않는다

그렇기 위해 

빈!BEAN

을 사용한다  미리 스프링에서 생성해놓고 관리하는 객체들을 의미한다

스프링은 이것을  Ioc 컨테이너에 넣어놓고 보관한다

이러한 모양이 스프링에서 빈을 관리하고있다! 이런 표시이다

 

@Component를 이용하면

스프링에서 빈을 생성하고 Ioc컨테이너에 넣어준다!

그 빈은 

@Autowired 를 사용하여 이용할수있다!

 

Lombok 의 @RequiredArgsConstructor 는 이것을 생략하여 사용할수있게해준다