의존성 주입
기술노트
💉 의존성 주입 (Dependency Injection)
의존성 주입(DI)은 객체 지향 프로그래밍에서 객체 간의 의존 관계를 외부에서 결정하고 주입해주는 디자인 패턴입니다. 객체가 자신이 사용할 다른 객체(의존성)를 직접 생성하는 것이 아니라, 외부(DI 컨테이너)로부터 전달받는 방식입니다.
DI는 '제어의 역전(Inversion of Control, IoC)' 원리를 구현하는 대표적인 방법 중 하나입니다.
🤔 의존성 주입은 왜 필요한가?
어떤 클래스 `A`가 다른 클래스 `B`의 기능을 사용한다고 가정해 봅시다. DI가 없다면, `A`는 자신의 코드 안에서 `B b = new B();` 와 같이 `B` 객체를 직접 생성해야 합니다. 이 경우, `A`는 `B`라는 구체적인 클래스에 강하게 결합(Tightly Coupled)됩니다. 만약 `B`를 다른 `C` 클래스로 교체하려면, `A`의 코드를 직접 수정해야만 합니다.
DI를 사용하면, `A`는 `B`를 직접 생성하지 않고, 외부의 누군가(DI 컨테이너)가 생성한 `B` 객체를 전달받아 사용합니다. 따라서 `A`는 `B`라는 구체적인 구현이 아닌, `B`가 구현한 특정 '인터페이스'에만 의존하게 됩니다. 이를 통해 나중에 `B`를 `C`로 쉽게 교체할 수 있는 '느슨한 결합(Loose Coupling)'이 가능해집니다.
⚙️ 의존성 주입의 종류
- 생성자 주입 (Constructor Injection) : 객체를 생성하는 시점에 생성자의 매개변수를 통해 의존성을 주입받는 방식입니다. 의존성이 반드시 필요함을 명확히 표현할 수 있어 가장 권장됩니다.
- 수정자 주입 (Setter Injection) : Setter 메서드를 통해 의존성을 주입받는 방식입니다. 의존성을 선택적으로 주입할 수 있습니다.
- 필드 주입 (Field Injection) : 멤버 변수(필드)에 어노테이션 등을 사용하여 직접 의존성을 주입하는 방식입니다. 코드가 간결해지지만, 외부에서 제어하기 어려워 권장되지 않는 경우가 많습니다.
💡 개발자 핵심 Point
- 의존성 주입의 핵심 목표는 객체 간의 결합도를 낮추어, 코드의 유연성과 재사용성, 테스트 용이성을 높이는 것입니다.
- 현대적인 프레임워크, 특히 Spring 프레임워크는 DI와 IoC를 핵심 원리로 삼고 있습니다. 개발자가 직접 객체를 생성하고 관리하는 것이 아니라, Spring 컨테이너가 객체의 생성과 의존 관계 주입을 모두 관리해줍니다.
- DI를 사용하면, 테스트 시에 실제 객체 대신 가짜 객체(Mock Object)를 쉽게 주입할 수 있어, 단위 테스트(Unit Test)가 매우 용이해집니다.