Spring DI
by 뚜부니스프링 DI
Spring DI (Dependency Injection)
스프링에서 의존성 주입은, 각 객체 간의 의존성을 스프링 컨테이너가 자동으로 연결해줌을 의미합니다.
만약 스프링 DI를 사용하지 않는다면 어떻게 될까요?
예를 들어 A 클래스 내부에서 B 클래스와 C 클래스를 활용한다고 할 때, 아래와 같이 A 클래스 내부에서 B 클래스와 C 클래스를 생성해서 사용하도록 구성했다고 합시다.
public class A {
private B b;
private C c;
public A() {
b = new B();
c = new C();
}
}
이렇게 생성한 경우, B 클래스나 C 클래스에 변경사항이 발생하면, A 클래스에 수정이 필요하게 됩니다. 이러한 코드를 결합도가 높은 코드라고 표현하며, A 클래스는 B 클래스와 C 클래스에 의존성을 가진다고 표현합니다.
스프링 DI는 이러한 의존성을 외부에서 주입하여 결합도를 낮춰줍니다.
public class A {
@Autowired
private B b;
@Autowired
private C c;
}
Spring DI 구현 방법
1. 필드 주입 (Field Injection)
필드 주입은 의존성을 주입하고 싶은 필드에 @Autowired 애노테이션을 붙여주면 의존성이 주입됩니다.
public class A {
@Autowired
private B b;
@Autowired
private C c;
}
특징
- 코드가 간결합니다.
- 필드에 final 키워드를 사용할 수 없어 불변성을 활용할 수 없습니다.
여러 블로그를 읽어보면 SRP 위반이나 보이지 않는 의존성에 대해 나오는데, 아래 링크를 걸어둔 블로그를 읽어보면 이는 필드 주입만의 문제가 아닐 수 있다는 생각이 들어 특징에서 제외했습니다.
[Spring] DI(Dependency Injection) 정리
참고로, 인텔리제이에서 필드 주입 사용 시 경고창이 나옵니다.
빈을 주입하는 순서
- 주입 받으려는 빈의 생성자를 호출하여 빈을 찾거나 빈 팩토리에 등록합니다.
- 생성자 인자에 사용하는 빈을 찾거나 생성합니다.
- 필드에 주입합니다.
필드 주입 방식은 런타임에서 의존성을 주입하기 때문에 의존성을 주입하지 않아도 객체가 생성될 수 있습니다.
public class App {
public static void main(String[] args) {
A a = new A(); // 의존성을 주입하지 않았지만 컴파일 에러는 발생하지 않음
}
}
2. 수정자 주입 (Setter Based Injection)
수정자 주입은 setter 메서드에 @Autowired 애노테이션을 붙여 의존성을 주입하는 방식입니다. 선택, 변경 가능성이 있는 의존관계에 사용하는 게 좋으며, 자바 빈 프로퍼티 규약의 수정자 메서드 방식을 사용하는 방법입니다.
public class A {
private B b;
private C c;
@Autowired
public void setB(B b) {
this.b = b;
}
@Autowired
public void setC(C c) {
this.c = c;
}
}
특징
- 선택, 변경 가능성이 있는 의존관계에 사용하는 것이 좋습니다.
- 자바빈 프로퍼티 규약의 수정자 메서드 방식을 사용하는 방법입니다. (setXxx)
- 필드에 final 키워드를 사용할 수 없어 불변성을 활용할 수 없습니다.
- 선택적으로 주입할 수 있기 때문에 누락 가능성이 있으며, 누락 시 NPE 가 발생합니다.
빈을 주입하는 순서
- 주입 받으려는 빈의 생성자를 호출하여 빈을 찾거나 빈 팩토리에 등록합니다.
- 생성자 인자에 사용하는 빈을 찾거나 생성합니다.
- 주입하려는 빈 객체의 수정자를 호출하여 주입합니다.
필드 주입 방식과 마찬가지로, 수정자 주입 방식도 런타임에서 의존성을 주입하기 때문에 의존성을 주입하지 않아도 객체가 생성될 수 있습니다.
public class App {
public static void main(String[] args) {
A a = new A(); // 의존성을 주입하지 않았지만 컴파일 에러는 발생하지 않음
}
}
3. 생성자 주입 (Constructor Based Injection)
생성자 주입은 생성자를 사용하여 의존성을 주입하는 방식입니다.
public class A {
private final B b;
private final C c;
@Autowired // 생성자가 딱 하나만 존재하면, @Autowired 를 생략해도 자동 주입된다.
public A(B b, C c) {
this.b = b;
this.c = c;
}
}
또한, Lombok 라이브러리에서 제공하는 @RequiredArgsConstructor 기능을 사용하면 final 이 붙은 필드를 모아서 생성자를 자동으로 만들어주기 때문에, 필드 주입처럼 간단하게 사용할 수 있습니다.
@RequiredArgsConstructor
public class A {
private final B b;
private final C c;
}
특징
- 필드에 final 키워드를 사용할 수 있어 불변성을 활용할 수 있습니다.(객체 생성 시 딱 1번 호출되므로 이후 변경될 일 X)
- 객체가 생성되는 시점에 빈을 주입하기 때문에 NPE 발생을 막습니다.
빈을 주입하는 순서
- 생성자의 인자에 사용되는 빈을 찾거나 빈 팩토리에서 생성합니다.
- 찾은 인자 빈으로 주입하려는 생성자를 호출합니다.
객체가 생성되는 시점에 빈을 주입하기 때문에 의존성을 주입하지 않으면 컴파일 에러가 발생하게 됩니다.
public class App {
public static void main(String[] args) {
// AS-IS : 의존성을 주입하지 않아 컴파일 에러가 발생함
A a = new A(); }
}
public class App {
public static void main(String[] args) {
// TO-BE : 의존성 주입
B b = new B();
C c = new C();
A a = new A(b, c);
}
}
🔗 참고
'Spring' 카테고리의 다른 글
Spring @RequestParam vs. @RequestPart (0) | 2024.12.21 |
---|---|
Spring Boot, MongoDB 프로젝트 네이밍 설정 방식 (0) | 2024.12.06 |
Kotlin + Spring 프로젝트 MongoDB 설정 (0) | 2024.11.30 |
Spring 프로젝트 내부에 React 설정 및 Build (Gradle) (0) | 2023.01.15 |
properties로 Spring Boot log를 설정해보자! (0) | 2022.04.23 |
블로그의 정보
개발하는 두부
뚜부니