의존성 주입 (DI:Dependency Injection)
- 의존 관계 주입 또는 의존성 주입이라 불린다.
- Spring의 3가지 핵심 기술 중 하나로, 객체 간의 의존 관계를 외부에서 설정하여 주입하는 방법
- DI를 통해 객체를 직접 생성하는 것이 아니라 외부에서 생성된 객체를 주입시키므로, 유연성을 높이고 결합도를 낮추는 장점이 있다.
DI 3가지 방법
1. Constructor Injection (생성자 주입)
- 가장 권장되는 방식으로, 생성자를 통해 의존성을 주입되는 방식
- 생성자를 통해 주입되기 때문에 한 번 할당되면 변경이 불가능하고 불변성을 유지할 수 있다.
final 키워드를 사용할 수 있어 불변성(Immutobillty)을 보장
- 초기에 할당되기 때문에 NPE(Null Pointer Exception)이 발생하지 않음
- 보통 lombok의
@RequiredArgsConstructor를 함께 사용하여 코드를 간결하지 작성할 수 있다.
public class Injection {
private final InjectionService injectionService;
public Injection(InjectionService injectionService) {
this.injectionService = injectionService;
}
}
@RequiredArgsConstructor
public class Injection {
private InjectionService injectionService;
}
2. Setter Injection (수정자 주입)
- Setter 메서드를 통해 의존성을 주입하는 방식
- Spring에서는
@Autowired 어노테이션을 사용하여 Setter 메서드를 자동으로 호출하여 의존성을 주입
@Autowired 어노테이션은 Field, Setter, Method, Constructor에 사용이 가능
- 필드에
final 키워드를 사용할 수 없으며, 객체 생성 이후에 Setter 메서드가 호출(생성자 이후에 호출)되므로 NPE(Null Point Exception) 발생할 수 있다.
- Spring 3.x 버전까지는 DI 권장 방식이였다.
public class Injection {
private InjectionService injectionService;
@Autowired
public void setInjectionService(InjectionService injectionService) {
this.injectionService = injectionService;
}
}
3. Field Injection (필드 주입)
- Bean으로 등록된 객체를 Field에 직접
@Autowired 어노테이션을 사용하여 의존성을 주입하는 방식
- 가장 간단하지만, 순환 참조와 같은 문제를 발생시킬 수 있고, 의존 관계를 명확하게 알기 어렵다는 단점이 있다.
- SOILD 원칙 중 단일 책임 원칙(SRP)을 위반할 가능성이 있으며, Unit Test가 어려워 질 수 있다.
final 키워드를 사용할 수 없다.
public class Injection {
@Autowired
private InjectionService injectionService;
}
결론
- Spring 개발 환경에서는 생성자 주입(Constructor Injection)을 권장한다.
- 생성자 주입은 객체를 한 번 생성되면 변경되지 않도록 보장할 수 있고, 불변성을 유지할 수 있다.
- 수정자 주입(Setter Injection)은 선택적으로 사용하며, 필드 주입(Field Injection)은 피하는 것이 좋다.
- 의존 관계는 한 번 설정되면 일반적으로 애플리케이션이 종료될 때까지 변경되지 않아야 하므로, Setter 메서드를 공개적으로 열어두는 것은 지양해야 한다.
참고자료
https://backendcode.tistory.com/249#head4