🔶 1. Dependency Injection이란?
Dependency Injection (의존성 주입)은 객체가 자신이 사용할 의존 객체(Dependency)를 직접 생성하지 않고, 외부에서 주입받는 설계 패턴입니다.
즉, 객체 A가 객체 B를 필요로 할 때, 객체 A가 직접 B를 생성하는 것이 아니라, 외부에서 객체 B를 생성해서 A에 주입(inject)해주는 방식입니다.
🔶 2. 왜 Dependency Injection을 사용하는가?
✅ 1. 결합도 감소 (Low Coupling)
- 객체 간의 결합도를 낮춰서 코드 간의 의존성을 줄입니다.
- 코드가 다른 코드에 덜 의존하므로, 변경에 강하고 재사용이 용이합니다.
✅ 2. 테스트 용이성 향상
- Mock 객체나 Stub 객체를 쉽게 주입할 수 있어 **단위 테스트(Unit Test)**가 쉬워집니다.
✅ 3. 유지보수성 향상
- 구현체를 쉽게 교체할 수 있어, 기능 확장이나 버그 수정이 간단해집니다.
✅ 4. 역제어(Inversion of Control, IoC) 구현
- 객체의 생성과 생명주기 관리를 프레임워크나 컨테이너(Spring 등)가 담당하게 됩니다.
🔶 3. 어떻게 사용되는가? (예제 중심 설명)
✅ 전통적인 방식 (의존성을 직접 생성)
public class OrderService {
private final PaymentService paymentService;
public OrderService() {
this.paymentService = new KakaoPayService(); // 강한 결합
}
}
- OrderService는 항상 KakaoPayService에 의존합니다.
- 다른 결제 수단으로 교체하기 어렵고 테스트도 힘듭니다.
✅ Dependency Injection 방식
public class OrderService {
private final PaymentService paymentService;
// 생성자 주입 (Constructor Injection)
public OrderService(PaymentService paymentService) {
this.paymentService = paymentService;
}
public void order() {
paymentService.pay();
}
}
- 이젠 외부에서 어떤 구현체든 주입 가능 (KakaoPayService, NaverPayService, MockPaymentService 등)
- 확장성과 테스트 용이성이 증가합니다.
🔶 4. 의존성 주입 방식의 종류
✔ 생성자 주입 (Constructor Injection)
- 가장 일반적이며 불변성(immutability) 보장
public class UserService {
private final UserRepository userRepository;
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
}
✔ 세터 주입 (Setter Injection)
- 선택적인 의존성이나 나중에 설정할 수 있는 경우에 사용
public class UserService {
private UserRepository userRepository;
public void setUserRepository(UserRepository userRepository) {
this.userRepository = userRepository;
}
}
✔ 필드 주입 (Field Injection)
- 테스트 어려움, 유지보수 불편으로 일반적으로는 권장하지 않음
public class UserService {
@Autowired
private UserRepository userRepository;
}
🔶 5. Spring Framework에서의 DI
Spring에서는 DI를 매우 강력하게 지원합니다.
예시:
@Service
public class UserService {
private final UserRepository userRepository;
@Autowired // 생성자가 하나일 경우 생략 가능
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
}
그리고 DI 컨테이너는 applicationContext.xml 혹은 @ComponentScan, @Configuration 기반으로 관리됩니다.
🔶 6. 결론
항목 설명
| 의미 | 객체가 직접 의존성을 생성하지 않고 외부에서 주입 받는 것 |
| 장점 | 낮은 결합도, 높은 유연성, 테스트 용이, 유지보수성 향상 |
| 방식 | 생성자 주입, 세터 주입, 필드 주입 |
| 사용 예 | Spring Framework, Guice, Dagger 등 |
'탐구하기' 카테고리의 다른 글
| @SpringBootApplication은 어떤역할을 하는 어노테이션일까? (0) | 2025.06.02 |
|---|---|
| 프록시 패턴과 AOP에 대해서 연관성 (0) | 2025.05.22 |
| POJO란 무엇인가? (3) | 2025.05.20 |
| Spring 프레임워크는 무엇일까? (1) | 2025.05.20 |
| WAS란 무엇일까? (1) | 2025.05.19 |