🌱 스프링 삼각형
이전 포스팅 중 '스프링 개요'에서 스프링을 구성하는 핵심 요소에 대하여 알아봤었다.
오늘은 그중에서 DI에 대하여 조금 더 상세하게 포스팅하려고 한다.
🌱 DI (Dependency Injection)
의존성 주입(DI)이란, 객체를 직접 생성하는 것이 아니라 외부에서 객체를 생성한 후 주입 시켜주는 방식을 뜻한다.
일반적인 스프링 프로젝트 코드를 살펴보면, Controller에서 Service나 Repository 객체를 사용할 때, new 키워드를 통해 객체를 직접 생성하는 것이 아니라 스프링 컨테이너에 생성된 객체를 받아오는 방식으로 사용하는 것을 볼 수 있었을 것이다.
이를 통해 결합도를 낮추고 유연성을 높일 수 있기 때문이다.
결합도를 낮추고 유연성을 높인다는게 정확하게 와닿지 않을 수 있으니 아래의 그림을 통해 단계적으로 알아가 보자.
A객체에서 B와 C객체를 사용한다고 할 때, 크게 두 가지 방법으로 나눌 수 있을 것이다.
- [방법 1]과 같이 A객체 내부에서 new 키워드를 통해 B와 C 객체를 생성한 후 사용
- [방법 2]와 같이 외부에서 B와 C를 생성한 후, A객체에 주입을 시킨 후 사용
만약 프로세스가 변경되어 B와 C 객체가 아닌 B'와 C'로 변경이 되어야 한다면,
[방법 1]의 경우, A클래스와 B, C클래스는 강하게 결합되어 있기에 코드 수정에 있어서 보다 많은 자원이 낭비될 것이다.
반면 [방법 2]의 경우, B'와 C'만 주입하면 되기 때문에 [방법 1] 보다는 작업에 있어 적은 공수가 들 것이다.
그렇다면 의존성 주입은 어떻게 하는지 알아보자.
🌱 의존관계 주입 방법
의존관계 주입에는 크게 3가지 방법이 있다.
- 필드 주입
- 수정자 주입(= Setter 주입)
- 생성자 주입
1. 필드 주입
- 필드주입은 스프링 초장기부터 많이 사용되는 형태로 아래와 같이 코드가 간결하다는 장점이 있다.
하지만 외부에서 변경이 불가능하여 테스트하기 힘들다는 단점이 있다.
- DI 프레임워크에 의존적이고 객체지향적인 관점에서 좋지 않다.
@Controller
public class Controller {
@Autowired
private Service service;
}
2. 수정자 주입
- setter라 불리는 수정자 메서드를 통해서 의존관계를 주입하는 방법이다.
- 수정자 주입을 사용하면 setXXX 메서드를 public으로 열어두어야 하기 때문에 언제 어디서든 변경이 가능하다.
이러한 성격 때문에 간혹 다른 곳에서 다시 주입을 하게 된다면 예기치 않은 오류를 발생시킬 수도 있다.
- 선택, 변경 가능성이 있는 의존관계에 사용된다.
@Controller
public class Controller {
private Service service;
@Autowired
public setService(Service service) {
this.service = service;
}
}
3. 생성자 주입
- 생성자에 @Autowired를 붙여 의존관계를 주입하는 방법이다.
- 생성자 호출시점에 딱 한 번만 호출되는 것을 보장할 수 있다.
- 불변, 필수 의존관계에 사용된다.
@Controller
public class Controller {
private final Service service;
@Autowired
public Controller(Service service) {
this.service = service;
}
}
- 만약, 생성자가 딱 1개만 있다면 @Autowired를 생략할 수 있으며, 아래와 같은 코드로 변경 가능하다.
@Controller
public class Controller {
private final Service service;
public Controller(Service service) {
this.service = service;
}
}
- 또한 롬복을 사용하여 @RequiredArgsConstructor 어노테이션을 사용한다면, 아래와 같이 코드를 더욱 간결하게 줄일 수 있다.
@Controller
@RequiredArgsConstructor
public class Controller {
private final Service service;
}
🌱 정리
Spring은 의존성 주입을 도와주는 DI 컨테이너로써,
강하게 결합된 클래스들을 분리하고, 애플리케이션 실행 시점에 객체 간의 관계를 결정해 줌으로써 결합도를 낮추고 유연성을 확보해 준다.
이러한 특성 덕분에 다음과 같은 이점을 가져갈 수 있다.
- 코드의 재사용성, 유연성이 높아진다.
- 하나의 작업만 수행하는 최소 단위의 객체는 상황에서 따라 쉽게 재결합하고 재사용할 수 있기 때문이다. - 객체 간 결합도가 낮기 때문에 한 클래스를 수정했을 때, 다른 클래스도 수정해야 하는 상황을 막아준다.
- 유지보수가 쉬워지며, 테스트가 용이해진다.
- 확장성을 가진다.
References.
1. 김영한(인프런), 스프링 핵심 원리 - 기본편
2. gil.log - [Spring] DI, IoC 정리
3. 만자의 개발일지 - [Spring] IoC와 DI
4. Gyun's 개발일지 - [Spring] 스프링 의존성 주입(DI) 이란?
'Spring' 카테고리의 다른 글
[Security] JWT 소개 (0) | 2023.02.12 |
---|---|
[Spring] 스프링 AOP (0) | 2023.02.07 |
[Spring] 스프링 IoC (0) | 2023.02.05 |
[Spring] 스프링 MVC (0) | 2023.01.29 |
[Spring] 스프링 개요 (0) | 2023.01.27 |