의존성 주입이란 하나의 객체 또는 함수가 의존하는 다른 객체 또는 함수들을 전달 받는 디자인 패턴이다. IoC(Inversion of Control, 제어 역전)의 한가지 형태인 의존성 주입은 객체 구성과 객체 사용을 분리해서, 느슨한 결합 상태의 프로그램을 만드는 것을 지향한다.
의존성 주입은 주입 받은 서비스를 사용하는 객체나 함수가 서비스를 구성하는 방법을 알 필요가 없게 한다. 그 대신, ’주입기(injector)’를 사용해 서비스를 전달 받는 클라이언트(객체나 함수)
에게 의존성을 제공한다. 의존성 주입은 암시적인 의존성을 명시적으로 만들어 아래 문제들을 해결하는데 도움을 준다.
기본적으로 의존성 주입은 메서드의 파라미터로 전달하는 것으로 이루어진다. 클라이언트는 스스로 서비스를 빌드하지 않기 때문에 클라이언트가 사용하는 서비스에 대한 인터페이스를 선언하기만 하면 된다.
의존성 주입의 구성요소 4가지
의존성 주입의 3가지 종류
생성자 주입(Constructor Injection)
- 의존성은 클라이언트의 생성자(constructor)로 제공된다.Setter 주입(Setter Injection)
- 클라이언트는 의존성을 받아 들이는 setter 메서드를 노출한다.인터페이스 주입(Interface Injection)
- 의존성의 인터페이스가 injector 메서드를 제공한다. Injector 메서드는 클라이언트에게 의존성을 주입한다.아래 예제에서 Client
클래스는 Service
변수를 생성자를 통해 초기화한다.
클라이언트는 하드코딩된 의존성을 생성하여 서비스를 직접 구성하고 제어한다.
class Client {
service: Service;
constructor() {
this.service = new Service();
}
}
생성자 주입은 의존성 주입의 가장 일반적인 형태로 생성자를 통해 의존성을 요청하는 방식이다.
클라이언트는 필수적인 의존성과 함께 인스턴스화된다.
class Client {
// 의존성이 생성자를 통해 주입된다.
constructor(private service: Service) {
this.service = service;
}
}
Setter 주입은 생성자가 아니라 setter 메서드를 통해 의존성을 주입한다.
언제든지 의존성을 클라이언트에 주입할 수 있다.
유연성이 높은 방식이지만, 모든 의존성이 주입됐는지 확인하기 어렵다.
class Client {
service;
// 의존성이 setter 메서드를 통해 주입된다.
setService = (service) => {
this.service = service;
}
}
의존성 주입을 구현하는 가장 간단한 방법은 프로그램의 루트에서 직접 클라이언트에게 서비스를 주입하는 것이다.
// 서비스 생성
const service = new Service();
// 클라이언트에 서비스 주입
const client = new Client(service);