
IoC(제어의 역전)는 서버 컨테이너 기술, 디자인 패턴, 객체 지향 설계 등에 적용하게 되는 일반적인 개념인데 반해 DI(Dependency Injection)는 IoC 개념을 조금 구체화 시킨 것이라고 볼 수 있다.

A 클래스가 B 클래스의 기능을 사용 할 때, 'A 클래스는 B 클래스에 의존한다' 라고한다.
이처럼 클래스 끼리는 사용하고자 하는 클래스의 객체를 생성해서 참조하게 되면 의존 관계가 성립하게 된다.

MenuController 생성자로 MenuService의 객체를 전달 받고 있다.
이처럼 생성자를 통해서 어떤 클래스의 객체를 전달 받는 것을 '의존성 주입'이라고 한다.
생성자의 파라미터로 객체를 전달하는 것을 외부에서 객체를 주입한다라고 표현한다.
그럼 여기서 객체를 주입해주는 '외부'는 무엇일까?
바로 CafeClient클래스가 MenuController의 생성자 파라미터로 menuService를 전달하고 있기 때문에 객체를 주입해주는 외부가 된다.
클래스의 생성자로 객체를 전달 받는 코드가 있다면 '아, 객체를 외부에서 주입 받고 있고나. 의존성 주입이 이루어지고 있구나'

만약 빨간색 네모칸에 있는 menuService를 menuServiceStub으로 바꿔야하는 상황이 왔다.
하지만 MenuServiceStub 클래스를 사용할 대상이 수십, 수백군데라면 어떻게 해야할까?
하나하나 다 바꿀 수는 있지만 매우 많은 시간이 필요할 것이다.
결국 new 키워드를 사용해서 객체를 생성하게 되면 참조 할 클래스가 바뀌게 될 경우, 이 클래스를 사용하는 모든 클래스들을 수정할 수 밖에 없다.
이처럼 new 키워드를 사용해서 의존 객체를 생성할 때, 클래스들 간에 강하게 결합(Tight Coupling) 되어 있다라고 한다.
결론적으로는 클래스 간의 강한 결합은 피해 느슨합 결합(Loose Coupling)이 필요하다.
코드를 작성할 때 이렇게 작성해 놓으면 나중에 또 수정이 필요한 부분이 뭐가 있을까? 라는 생각은 한번 쯤 해보는 게 좋다.
대표적인 방법으로는 **인터페이스 (Interface)를 사용하는 것이다.

MenuController가 MenuService라는 클래스를 직접적으로 의존하는 게 아니라 클래스 이름은 같지만 인터페이스를 의존하고 있다.
MenuController가 MenuService를 의존하고 있지만 MenuService의 구현체는 MenuServiceImpl인지 MenuServiceStub인지 알지 못한다. 알 필요가 없다.
MenuController 입장에서는 그저 메뉴 목록 데이터만 조회할 수 만 있므녀 그만이니까.
이처럼 어떤 클래스가 인터페이스 같이 일반화된 구성 요소에 의존하고 있을 때, 클래스 간에 느슨하게 결합(Loose Coupling) 되어있다고 한다.

(1)을 자세히 보면 new 로 MenuServiceStub 클래스의 객체를 생성해서 MenuService 인터페이스에 할당한다.
이처럼 인터페이스 타입의 변수에 그 인터페이스의 구현 객체를 할당할 수 있는데 이를 업캐스팅(Upcasting)이라고 한다.
이제 업캐스팅을 통한 의존성 주입으로 인해 MenuController와 MenuService는 느슨한 결합 관계를 유지하게 됐다.
하지만, 클래스들 간의 관계를 느슨하게 만들기 위해서는 new 키워드를 사용하지 않아야 되는데, CafeClient 클래스의 (1)을 보면 MenuServiceStub의 객체와 MenuController 객체를 생성하기위해 여전히 new를 사용하고 있다.
어떻게하면 new를 제거하고 의존 관계를 느슨하게 만들 수 있을까?
바로 Spring이 대신 해준다.

Config 클래스에서 (3)과 같이 MenuController 객체 생성을 정의해 두면 (1)을 이용해서 이 객체를 애플리케이션 코드에서 사용하게 된다.
한마디로 Config 클래스에 정의해둔 MenuController 객체를 Spring의 도움을 받아서 CafeClient 클래스에 제공을 하고 있는 것이다.
애플리케이션 흐름의 주도권이 사용자에게 있지 않고, Framework나 서블릿 컨테이너 등 외부에 있는 것 즉, 흐름의 주도권이 뒤바뀐 것을 IoC(Inversion Of Control)라고 한다.
DI(Dependency Injection)는 IoC 개념을 조금 구체화 시킨 것으로 객체 간의 관계를 느슨하게 해준다.
클래스 내부에서 다른 클래스의 객체를 생성하게 되면 두 클래스 간에 의존 관계가 성립하게 된다.
클래스 내부에서 new를 사용해 참조할 클래스의 객체를 직접 생성하지 않고, 생성자 등을 통해 외부에서 다른 클래스의 객체를 전달 받고 있다면 의존성 주입이 이루어 지고 있다는 것이다.
new 키워드를 사용하여 객체를 생성할 때, 클래스 간에 강하게 결합(Tight Coupling)되어 있다고 한다.
객체들 간의 느슨한 결합은 요구 사항의 변경에 유연하게 대처할 수 있도록 해준다.
의존성 주입(DI)은 클래스들 간의 강한 결합을 느슨한 결합으로 만들어 준다.
Spring에서는 애플리케이션 코드에서 이루어지는 의존성 주입(DI)을 Spring에서 대신 해준다.