의존성 주입이란?
•
프로그램 디자인이 결합도를 느슨하게 되도록하고 의존관계 역전 원칙을 따르도록 클라이언트의 생성에 대한 의존성을 클라이언트의 행위로부터 분리하는 것이다.
예시
•
여기서 객체 A는 B에 의존하고 있다. 즉 의존성이 존재한다. A를 사용하기 위해선 b가 생성된 후 주입되어 있어야 한다.
public class A {
private B b;
}
Java
복사
•
의존성 주입은 객체가 필요로 하는 다른 객체를 직접 생성하는 대신, 생성자 파라미터, 팩토리 메소드 인수 또는 속성으로 정의하고 컨테이너가 객체를 생성할 때 해당 의존성을 주입하는 프로세스다.
•
이처럼 의존 관계를 외부에서 결정하고 주입하는 것을 관리하고 사용하게 만드는 것을 의존성 주입이라고 한다.
◦
이를 통해 객체 간의 의존 관계를 느슨하게 유지하여 유지보수에 도움이 되도록하는 것이다.
의존성 주입의 장점
•
결합도가 감소한다.
◦
의존성 주입을 사용하면 객체의 의존성을 외부에서 관리해주므로 결합도가 낮아지고 이로인해 유지 보수성이 향상된다.
•
테스트가 용이해진다.
◦
특정 객체를 검증할 때, 해당 객체가 의존성을 가진 다른 객체를 테스트 더블로 대체하여 처리할 수 있다.
의존성 주입의 종류
필드 주입
@Component
public class A {
@Autowired
private B b;
}
Java
복사
•
개요
◦
필드에 @Autowired 어노테이션을 추가하여 의존성을 주입하는 방법이다.
◦
즉, 객체의 필드를 사용하여 의존성을 주입하는 방식이다.
•
특징
◦
외부에서 접근이 불가능하다.
◦
DI 컨테이너 상에서만 동작하므로 순수 자바 코드로 테스트하기 어렵다.
▪
필드를 수정할 수 없게 되므로 테스트를 위해 의존성을 모킹하기 어렵기 때문이다.
▪
통합 테스트라면 괜찮지 않을까? 비관리 의존성에는 사용하지 않는식으로..
◦
어플리케이션의 실제 코드와 상관없는 특정 테스트를 하고 싶을때 사용하는 것이 좋다.
Setter, Method 주입
@Component
class A {
private B b;
@Autowired
public void setB(B b) {
this.b = b;
}
}
Java
복사
•
POJO
class A {
private B b;
public void setB(B b) {
this.b = b;
}
}
Java
복사
•
개요
◦
setter 메소드에 @Autowired 어노테이션을 붙여 의존성을 주입할 수 있다.
◦
@Component를 통해 실행되는 클래스를 빈으로 등록하고 의존관게를 주입하게 된다.
◦
@Autowired가 있는 setter 메소드들은 자동으로 의존관계를 주입한다.
•
특징
◦
의존 관계가 변경될 수 있다. 또한 초기 값이 없으므로 NPE가 발생할 가능성이 있다.
◦
가급적이면 변경 가능성이 있는 의존 관계에 사용하는 것이 좋다.
생성자 주입
@Component
public class A {
private final B b;
@Autowired
public A(B b) {
this.b = b;
}
}
Java
복사
•
POJO
public class A {
private final B b;
public A(B b) {
this.b = b;
}
}
Java
복사
•
개요
◦
생성자 주입은 컨테이너가 생성자를 호출하면서 이뤄지는 의존성 주입이다.
▪
이는 정적 팩토리 메소드를 호출하여 빈을 생성하는 것과 비슷한 원리로, 스프링 공식문서에서도 이를 유사한 경우라고 언급하고 있다.
▪
spirng.io 개발팀이 일반적으로 최선의 경우라고 추천한다.
◦
생성자에 @Autowired 어노테이션을 붙여 의존성을 주입할 수 있다.
•
특징
◦
객체 생성 시점에 모든 의존성이 주입되므로 객체의 불변성을 보장하므로 객체가 안정적이다.
▪
final 키워드를 사용할 수 있으므로 컴파일 시 의존성 문제를 발견할 수 있다.
◦
의존하는 객체가 존재하지 않을 때, 컴파일 시점에 오류가 발생하므로 런타임 오류를 예방할 수 있다.