[TIL] Spring의 의존성 주입 방법
Spring 프레임워크의 핵심 기술 중 하나는 DI(Dependency Injection, 의존성 주입)이다. 이번 포스팅에서는 Spring이 제공하는 3가지의 의존성 주입 방법들을 알아보고, 가장 권장되는 방법이 무엇인지 정리하고자 한다.
📌 의존성 주입(DI) 이란?
의존성 주입은 객체 지향 프로그래밍에서 의존하는 객체를 직접 생성하거나 관리하지 않고 외부에서 주입받는 것을 의미한다. 다시 말해, 필요한 객체를 직접 생성하는 것이 아닌 외부로부터 객체를 받아 사용하는 것이다.
의존성 주입을 할 경우, 객체간의 결합도를 줄이고 코드의 재활용성을 높일 수 있다는 장점이 있다.
📌 의존성 주입의 3가지 방법
Spring은 @Autowired 어노테이션을 이용해 다음의 3 가지 의존성 방법을 제공한다.
(@Autowired 는 Spring에게 의존성을 주입하는 지시자 역할로 쓰임)
- 생성자 주입(Constructor Injection)
- 필드 주입(Field Injection)
- 수정자 주입(Setter Injection)
결론적으로, Spring Framwork reference에서 권장하는 방법은 생성자를 통한 주입이다.
그 이유에 대해 알아보기 전에, 우선 각각의 방법들에 대해 알아보자.
1. 생성자 주입 (Constructor Injection)
의존성 주입을 하는 가장 좋은 형태이며, Spring에서도 권장하는 방식이다. 단일 생성자인 경우에는 @Autowired 어노테이션을 붙이지 않아도 되지만, 생성자가 2개 이상인 경우에는 생성자에 @Autowired 어노테이션을 붙여주어야 한다. (생성자 우선 순위와 관련이 있다)
@Component
public class Example {
// final로 선언할 수 있다
private final TeamService teamService;
// 단일 생성자인 경우는 추가적인 어노테이션이 필요 없다.
//@Autowired
public Example(TeamService teamService) {
this.teamService = teamService;
}
}
2. 필드 주입 (Field Injection)
필드에 @Autowired 어노테이션만 붙여주면 자동으로 의존성 주입이 된다. 사용법이 매우 간단하기 때문에 가장 많이 접할 수 있는 방법이다. Spring Framework는 Java의 Reflection API를 사용해 private으로 선언된 필드에도 의존성을 주입할 수 있다.
@Component
public class Example {
@Autowired
private TeamService teamService;
}
필드 주입은 가장 코드가 짧고 주입하기도 간편하고, 보기에도 직관적이지만, 권장되는 방법은 아니다.
그 이유는 다음과 같다.
- 필드 주입을 사용하면 의존성 주입을 위해 Spring Container가 필요하게 되므로 테스트가 어려움
- 객체가 생성된 후에도 의존성이 변경될 수 있어, 불변성을 해칠 수 있다. 객체의 안정성을 보장하기 어려움
3. 수정자 주입 (Setter Injection)
Setter 메소드에 @Autowired 어노테이션을 붙이는 방법이다. 꼭 'setter' 여야된다보다, 동일한 기능을 한다면 메서드 이름이 수정자 네이밍 패턴(setXXXX)이 아니어도 된다.
@Component
public class Example {
private TeamService teamService;
@Autowired
public void setTeamService(TeamService teamService) {
this.teamService = teamService;
}
}
Setter Injection은 Field Injection에 비해 Spring 컨테이너와의 결합도는 낮아져 테스트 코드를 짤 수 있다는 등의 장점은 있지만, 역시 권장되는 방법은 아니다.
그 이유는 다음과 같다.
- set 메서드를 거치지 않고도 의존당하는 객체가 생성될 수 있다는 점은 극복하지 못함
- 수정자 주입을 사용하면 setXXX 메서드를 public으로 열어두어야 하기 때문에, 언제 어디서든 변경이 가능함 (불변성 해침)