DI(Dependency Injection) 의존성 주입
Dependency Injection(DI)은 객체 지향 프로그래밍에서 인스턴스를 생성하고 관리하는 방식이다.
DI는 객체가 필요로 하는 의존성(dependency)을 외부에서 제공해줌으로써 객체 간 결합도를 낮추고 유연성과 확장성을 높일 수 있다.
DI의 유형
- 생성자 주입(Constructor Injection)
- 생성자 주입은 객체 생성 시 생성자를 통해 의존성을 주입하는 방식이다. 클래스의 생성자에서 필요한 인자를 받아 의존성을 만족시키는 객체를 생성한다. 이후 객체 내에서 해당 의존성을 사용할 수 있게 된다.
//TypeScript
class Car {
private engine: Engine;
constructor(engine: Engine) {
this.engine = engine;
}
start() {
this.engine.start();
}
}
위 예시 코드에서 Car 클래스의 생성자에서 Engine 객체를 인자로 받고 있다. 이후 Car 객체 내에서 Engine 객체를 사용할 수 있게 된다.
- Setter 주입(Setter Injection)
- Setter 주입은 setter 메서드를 통해 의존성을 주입하는 방식이다. 객체 생성 후, 해당 객체의 setter 메서드를 호출하여 의존성을 주입한다.
//TypeScript
class Car {
private engine: Engine;
setEngine(engine: Engine) {
this.engine = engine;
}
start() {
this.engine.start();
}
}
위 예시 코드에서 Car 클래스의 setEngine() 메서드를 통해 Engine 객체를 주입한다. 이후 Car 객체 내에서 Engine 객체를 사용할 수 있다.
- 인터페이스 주입(Interface Injection)
- 인터페이스 주입은 인터페이스를 통해 의존성을 주입하는 방식이다. 클래스 내에서 필요한 인터페이스를 정의하고, 해당 인터페이스를 구현하는 객체를 주입한다.
//TypeScript
interface Engine {
start(): void;
}
class Car {
private engine: Engine;
setEngine(engine: Engine) {
this.engine = engine;
}
start() {
this.engine.start();
}
}
위 예시 코드에서 Engine 인터페이스를 정의하고, Car 클래스에서 Engine 인터페이스를 필드로 가지고 있다. Car 객체 생성 후 setEngine() 메서드를 통해 Engine 인터페이스를 구현하는 객체를 주입한다. 이후 Car 객체 내에서 Engine 객체를 사용할 수 있다.
DI의 장점
- 결합도의 감소 : DI를 사용하면 객체 간의 결합도를 낮출 수 있다. 의존성이 내부에서 해결되는 것이 아니라 외부에서 주입되기 때문이다. 이는 객체 간의 의존성이 제거됨으로써 유지보수성과 테스트 용이성을 높인다.
- 코드의 재사용성 - DI를 사용하면 의존성이 외부에서 주입되기 때문에, 같은 코드를 다른 의존성과 함께 사용할 수 있다. 이는 코드의 재사용성을 높인다.
- 유연성과 확장성 - DI를 사용하면 의존성을 변경하거나 확장하기가 용이해진다. 새로운 의존성을 추가하거나 변경할 때 다른 코드를 수정할 필요가 없기 때문이다.
- 테스트 용이성 - DI를 사용하면 테스트하기 쉬운 코드를 작성할 수 있다. 의존성이 외부에서 주입되기 때문에 모의 객체(mock object)를 사용하여 의존성을 대체할 수 있다.
- 코드 가독성 - DI를 사용하면 코드의 가독성이 향상된다. 의존성이 명시적으로 주입되기 때문이다.
DI의 단점
- 구현 복잡도의 증가
- DI를 이용하면 인스턴스 생성, 의존성 주입 등 구현에 대한 작업이 복잡해질 수 있다. 특히 의존성이 복잡하고 규모가 큰 프로젝트에서는 DI를 적용하기 위한 작업량이 많아질 수 있다.
- 런타임 오류 발생 가능성 존재
- DI를 이용하면 의존성 주입을 자동으로 처리하므로, 코드의 실행 순서나 실제 주입되는 의존성에 대한 문제가 발생할 수 있다. 이로 인해 런타임 오류가 발생할 수 있다.
- 리팩토링의 어려움
- DI를 이용하면 의존성 주입 부분이 코드 전체에 흩어져 있기 때문에, 코드 리팩토링이 어려울 수 있다. 특히 의존성이 깊게 들어가 있는 경우, 코드 변경이 필요할 때 해당 의존성에 대한 모든 코드를 수정해야 하는 번거로움이 있다.
- 초기 구성이 복잡할 수 있음
- DI를 사용하면 코드 초기 구성이 복잡해질 수 있다. 예를 들어, DI 컨테이너를 설정하고 초기화하는 작업이 필요하기 때문이다.
- 개발자들이 DI 패턴에 대한 이해가 필요함
- DI를 사용하는 경우, 개발자들이 DI 패턴과 의존성 주입의 원리에 대한 이해가 필요하다. 이에 따라 적절한 DI 패턴과 주입 방식을 선택하고, 코드를 작성해야 한다.
'CS' 카테고리의 다른 글
#6. MSA(Micro Service Architechure) (0) | 2023.02.23 |
---|---|
#5. 인덱스 (0) | 2023.02.22 |
#3. REST API (0) | 2023.02.21 |
#2. 객체지향프로그래밍(OOP) (0) | 2023.02.21 |
#1. 시간복잡도와 공간복잡도 (0) | 2023.02.19 |