소프트웨어 엔지니어링에서 **의존성 주입**은 하나의 객체가 다른 객체의 의존성을 제공하는 테크닉이다. "의존성"은 예를 들어 서비스로 사용할 수 있는 객체이다. 클라이언트가 어떤 서비스를 사용할 것인지 지정하는 대신, 클라이언트에게 무슨 서비스를 사용할 것인지를 말해주는 것이다. "주입"은 의존성(서비스)을 사용하려는 객체(클라이언트)로 전달하는 것을 의미한다. 서비스는 클라이언트 상태의 일부이다. 클라이언트가 서비스를 구축하거나 찾는 것을 허용하는 대신 클라이언트에게 서비스를 전달하는 것이 패턴의 기본 요건이다.

의존성 주입의 의도는 객체의 생성과 사용의 관심을 분리하는 것이다. 이는 가독성과 코드 재사용을 높혀준다.

의존성 주입은 광범위한 역제어 테크닉의 한 형태이다. 어떤 서비스를 호출하려는 클라이언트는 그 서비스가 어떻게 구성되었는지 알지 못해야 한다. 클라이언트는 대신 서비스 제공에 대한 책임을 외부 코드(주입자)로 위임한다. 클라이언트는 주입자 코드를 호출할 수 없다. 그 다음, 주입자는 이미 존재하거나 주입자에 의해 구성되었을 서비스를 클라이언트로 주입(전달)한다. 그리고 나서 클라이언트는 서비스를 사용한다. 이는 클라이언트가 주입자와 서비스 구성 방식 또는 사용중인 실제 서비스에 대해 알 필요가 없음을 의미한다. 클라이언트는 서비스의 사용 방식을 정의하고 있는 서비스의 고유한 인터페이스에 대해서만 알면 된다. 이것은 "구성"의 책임으로부터 "사용"의 책임을 구분한다.

## 의도
의존성 주입은 다음과 같은 문제를 해결한다.

객체를 필요로하는 클래스 내에서 직접 객체를 생성하는 것은 클래스를 특정 객체에 커밋하는 것이고 이후에 클래스로부터 독립적으로(클래스의 수정 없이) 인스턴스의 생성을 변경하는 것이 불가능하기 때문에 유연하지 못하다. 이는 다른 객체를 필요로하는 경우 클래스를 재사용할 수 없게하며, 실제 객체를 모의 객체로 대체할 수 없기 때문에 클래스를 테스트하기 힘들게한다.

클래스는 더 이상 객체 생성에 대한 책임이 없으며, 추상 팩토리 디자인 패턴에서처럼 팩토리 객체로 생성을 위임할 필요가 없다.

아래의 UML 클래스 및 시퀀스 다이어그램을 참고.

## 개요
스스로 냉장고로 가서 무언가를 가져올 때 문제가 발생할 수 있다. 문을 열어 놓고 갈수도 있고, 엄마나 아빠의 물건을 가져갈 수도 있다. 심지어 있지도 않은 물건이나 유효기간이 지난 것을 찾고 있을 수도 있다.

필요한 것을 정의해야한다. "나는 점심이랑 같이 마실 뭔가가 필요해", 그 후에 뭔가를 가져왔는지 확인하고 앉아서 먹으면 된다.|source=John Munsch, 28 October 2009. 이는 클라이언트가 의존성을 찾기 위해 그들이 사용하는 시스템에 대해 알도록 하는 서비스 로케이터 패턴과 정반대되는 것이다.

의존성 주입의 기본 단위인 주입은 새롭거나 관습적인 메커니즘이 아니다. "매개변수 전달"과 동일하게 동작한다. 주입으로써 "파라미터 전달"은 클라이언트를 세부 사항과 분리하기 위해 수행되고 있는 부가적인 의미를 전달한다.

또한 주입은 전달을 제어하는 대상(클라이언트가 아님)에 대한 것이며 전달의 수행 방식-참조 또는 값 전달-과 독립적이다.

의존성 주입은 네 가지 역할을 담당하는 객체 및 인터페이스를 전제로 한다.

비유하자면,

사용될 수 있는 모든 객체는 **서비스**로 여겨진다. 다른 객체를 사용하는 모든 객체는 **클라이언트**로 여겨진다. 이름은 객체가 무엇을 위한 것인지와 무관하며 한 번의 주입에서 객체가 하는 역할과 관련이 있다.

**인터페이스**는 클라이언트가 의존성으로 예상하는 타입이다. 쟁점은 무엇을 접근할 수 있게 하는가이다. 이는 실제로 서비스에 의해 구현된 인터페이스 타입일 수도 있지만 추상 클래스 또는 DIP를 위반하고, 테스트를 하기위한 동적으로 결합도 낮추는것을 희생하긴 하지만 concrete 서비스 자체일 수도 있다. 클라이언트가 인터페이스를 구성하거나 확장하는 것처럼 구체적으로 다룰 수 없도록 알지 못하게 하는 것이 요구된다.

클라이언트는 의존성의 특정 구현에 대한 구체적인 지식이 필요 없다. 인터페이스의 이름과 API만 알면 된다. 결과적으로 인터페이스가 변경되더라도 클라이언트는 수정할 필요가 없어진다. 하지만 인터페이스가 클래스로 존재하다가 인터페이스 타입으로(그 반대의 경우에도) 리팩토링될 경우 클라이언트는 다시 컴파일이 필요할 수 있다. 이는 클라이언트와 서비스가 독립적으로 발행될 경우 중요하다. 이런경우에 결합도가 높아지는 문제는 안타깝게도 의존성 주입으로 해결할 수 없다.

**주입자**는 클라이언트에게 서비스를 소개한다. 종종 클라이언트를 생성하기도 한다. 주입자는 객체를 클라이언트와 같이 처리하고 나중에 다른 클라이언트의 서비스로 처리하여 매우 복잡한 객체 그래프를 함께 연결할수도 있다. 주입자는 실제로 함께 동작하는 많은 객체가 될 수 있지만 클라이언트는 될 수 없다. 주입자는 다음과 같은 많은 이름들로 참조될 수 있다: assembler, provider, container, factory, builder, spring, construction code, or main.

의존성 주입은 모든 객체가 구성과 동작을 분리하도록 요구하는 하나의 규율로 적용될 수 있다. 구성을 수행하는 DI 프레임워크에 의지하면 **new** 키워드의 사용을 금지하거나 덜 엄격하게 값 객체의 직접 생성을 허용할 수 있다.

### 분류
역제어(IoC)는 DI보다 더 일반적이다. 간단하게 말하자면 IoC는 호출을 요구하는 대신 다른 코드가 호출할 수 있게 함을 의미한다. DI가 없는 IoC의 한 예로 템플릿 메소드 패턴이 있다. 여기서 다형성은 서브클래싱, 즉, 상속을 통해 달성된다.

의존성 주입은 컴포지션을 통해 IoC를 구현하므로 종종 전략 패턴과 동일하지만, 전략 패턴의 의도는 객체의 수명동안 의존성을 교환할 수 있도록 하는 것이고, 의존성 주입에서는 단일 의존성 인스턴스만 사용할 수 있도록 하는 것이다. 여전히 다형성은 유지되지만 위임과 컴포지션을 통해 이루어진다.

### 의존성 주입 프레임워크
[http://cdi-spec.org/ CDI]와 그 구현물인 [http://weld.cdi-spec.org/ Weld], Spring, Guice, Play framework, [https://ruediste.github.io/salta/ Salta], Glassfish HK2, [https://google.github.io/dagger/ Dagger], Managed Extensibility Framework(MEF)와 같은 애플리케이션 프레임워크는 의존성 주입을 지원하지만 필수는 아니다.

## 적용 유형
마틴 파울러는 다음과 같은 세 가지의 의존성 주입 패턴을 제시하였다.