이번 글에서는 IoC와 DI의 개념을 간단히 (최대한 스프링과의 연계를 빼고) 정리해 보았다.
제어의 역전
프로그램의 제어 흐름을 직접 제어하는 것이 아니라 외부에서 관리하는 것
public class A {
private B b;
public A() {
this.b = new B();
}
}
A클래스에서 B를 필드로 가지고 있고, 생성자 내부에서 B를 직접 생성해 필드를 초기화하고 있다.
-> 이러한 코드의 객체생명주기를 직접 제어하는 코드라고 할 수 있다.
public class A {
private B b;
public A(B b) {
this.b = b;
}
}
앞서 보았던 코드와의 차이는 생성자에서 외부로부터 B를 인자로 받아 필드를 초기화하고 있다는 것이다.
-> 이렇게 프로그램의 제어흐름을 직접 제어하는 것이 아니라 외부에서 관리하는 것을 제어를 역전시켰다고 말할 수 있다.
객체지향 원칙을 잘 지키기 위함이다.
역할과 관심을 분리해 응집도를 높히고 결합도를 낮추며, 이에 따라 변경에 유연한 코드를 작성할 수 있는 구조가 될 수 있기 때문이다.
의존성 주입
외부에서 의존성을 주입해 준다는 것
의존 -> 변경에 의해 영향을 받는 관계
흔히들 IoC와 DI를 헷갈려하거나, 동일시하고는 한다. 하지만 사실 IoC와 DI는 다른 개념이다. 절대 IoC == DI가 아니다! (DI ⊂ IoC 라면 몰라도) DI 없이도 IoC를 만족하는 프로그램을 만들 수 있다. IoC는 프로그램 제어권을 역전시키는 개념이고, DI는 해당 개념을 구현하기 위해 사용하는 디자인 패턴 중 하나로, 이름 그대로 객체의 의존관계를 외부에서 주입시키는 패턴을 말한다.
의존성 주입에는 세가지 주요 스타일이 있다.
public class A {
private B b;
public A(B b) {
this.b = b;
}
}
생성자 호출 시 외부로부터 의존성을 받는 방법이다.
이 방법은 필요한 의존성을 모두 포함하는 생성자를 만들고 그 생성자를 통해서 의존성을 주입한다.
public class A {
private B b;
public void setB(B b) {
this.b = b;
}
}
의존성을 입력받는 setter 메서드를 만들고 메서드들을 호출해서 의존성을 주입한다.
public interface BInjection {
void inject(B b);
}
public A implements BInjection {
private B b;
@Override
public void inject(B b) {
this.b = b;
}
}
어떤 의존성을 주입할 것인지를 인터페이스에 명시하고, 의존성을 주입받는 클래스는 해당 인터페이스의 구현체로 만든다.
setter 주입과 비슷하지만 의존성 주입을 빠트릴 수 있는 setter와는 다르게 override를 통해 메서드 구현을 강제할 수 있다는 차이가 있다.
출처 : https://www.youtube.com/watch?v=VHZ2i4cuwb8&list=PLi-xJrVzQaxU-xK2ao8utngQJqAX4DQty&index=7
https://www.youtube.com/watch?v=8lp_nHicYd4
https://velog.io/@ohzzi/Spring-DIIoC-IoC-DI-%EA%B7%B8%EA%B2%8C-%EB%AD%94%EB%8D%B0