이번 포스팅은 DI에 대해 알아보겠습니다.
의존성(Dependency)은 어떤 하나의 대상이 다른 대상에 의존하는 것을 의미합니다.
예를 들어, A는 B라는 객체를 부품으로 갖고 있습니다. 즉, A, B 클래스는 Has a 상속 관계입니다.
그렇다면 DI를 해야하는 이유가 무엇일까요?
DI를 하지 않으면 객체와 객체간의 결합력이 강하기 때문에 객체를 바꿔 끼우는 과정에서 많은 수정을 해야하는 번거로움이 있기 때문입니다.
이해를 위해 아래 예제를 보겠습니다.
public class A {
private B b;
public A() {
this.b = new B();
}
public void printHello() {
this.b.hello();
}
}
위 코드와 같이 A 클래스에서 printHello 메서드가 호출되기 위해서는 B 클래스가 필요합니다.
이것을 쉽게 표현하면 'A 클래스는 B 클래스에 의존한다.'라고 할 수 있습니다.
이를 개발자스러운 표현으로 바꾸면 'A 클래스는 B클래스의 의존성을 가진다.'라고 합니다.
그런데 위와 같은 코드는 결합도가 굉장히 높다고 할 수 있습니다.
(결합도는 어떤 대상과 어떤 대상이 서로 관련이 되어있는, 묶여있는 정도라고 생각하시면 됩니다.)
왜냐하면 B 클래스가 수정되면 A 클래스도 B 클래스의 수정부분을 똑같이 바꿔줘야 하기 때문입니다.
이러한 문제를 해결하기 위해 DI(의존성 주입)을 해보겠습니다.
의존성을 주입하는 방법은 크게 두 가지가 있는데요.
과거부터 사용해오는 XML 설정 방식과 스프링에서 제공해주는 어노테이션(@)을 활용하는 방식이 있습니다.
XML 방식도 중요하지만, 이 부분은 나중에 다뤄보고 지금은 어노테이션을 활용한 방식으로 진행해볼게요.
어노테이션을 활용한 DI
스프링에서는 DI를 할 때 @AutoWired라는 어노테이션을 사용합니다.
@AutoWired는 세 가지 부분에 달아줄 수 있습니다.
1. 생성자에다 붙이기(Constructor Injection)
2. Setter에다 붙이기(Setter Injection)
3. 필드에다 붙이기(Field Injection)
1. Constructor Injection
위의 예제를 생성자 Constructor Injection 방법으로 바꿔보면 아래와 같습니다.
public class A {
private B b;
@Autowired
public A(B b) {
this.b = b;
}
public void printHello() {
this.b.hello();
}
}
Constructor Injection 방법은 스프링 레퍼런스에서 가장 권장하는 방법이라고 합니다.
필수적으로 사용해야하는 레퍼런스(예제에서는 B b) 없이는 해당 인스턴스(예제에서는 A)를 만들 수 없도록 강제할 수 있기 때문입니다. (나머지 아래의 방법은 인위적으로 해당 인스턴스를 만들 수 있다고 합니다!)
그리고 스프링 4.3부터 어떠한 클래스에 생성자가 딱 하나 뿐이고 그 생성자로 주입받는 레퍼런스 변수들이 Bean으로 등록되어 있다면 그 Bean을 자동으로 주입하도록 기능이 추가되었습니다.
따라서 스프링 4.3 이후 버전이라 가정하에 위의 예제는 @Autowired를 붙이지 않아도 정상적으로 동작합니다.
2. Setter Injection
위의 예제를 생성자 Setter Injection 방법으로 바꿔보면 아래와 같습니다. 단, Setter를 존재해야 합니다.
public class A {
private B b;
@Autowired
public void setB(B b) {
this.b = b;
}
public void printHello() {
this.b.hello();
}
}
3. Field Injection
위의 예제를 생성자 Field Injection 방법으로 바꿔보면 아래와 같습니다.
public class A {
@Autowired
private B b;
public void printHello() {
this.b.hello();
}
}
@Autowired를 붙인다면 어떠한 클래스든지 갖다 쓸 수 있는 것일까요?
NONONONONO. 스프링 IoC 컨테이너에 들어있는 Bean 객체만 사용할 수 있습니다.
스프링 IoC 컨테이너는 무엇이고 여기에 Bean을 어떻게 넣을 수 있는지는 다음 글에서 확인하실 수 있습니다.
'Programming > Spring Framework' 카테고리의 다른 글
[스프링부트] @JsonNaming, @JsonProperty는 언제 사용할까? (1) | 2021.05.12 |
---|---|
[스프링] IoC Container에 Bean 객체가 등록되는 방법 두 가지를 알아보자 (0) | 2021.01.09 |
[스프링부트] postman을 활용한 간단한 RESTful 웹 서비스 만들기 - POST/DELETE 요청 (0) | 2019.09.22 |
[스프링부트] postman을 활용한 간단한 RESTful 웹 서비스 만들기 - GET 요청 (0) | 2019.09.22 |
[스프링부트] Bean 객체를 등록하는 두 가지 방법(@Component, @Bean) (4) | 2019.09.20 |