- 스프링은 빈 컨테이너를 통해 빈 객체를 관리해준다 (IoC). 이 때, 필요한 곳에 적절히 객체를 주입해 사용해야 한다. (DI)
- 사실 스프링을 사용하지 않더라도, 객체 지향적 관점에서 사용되는 개념
의존성
: 어떠한 객체 A가 다른 객체 혹은 인터페이스 B를 사용할 때 A는 B에 대한 의존성이 발생하며, “A는 B에 의존한다.” 라고 말한다.
강한 결합
- A클래스에서 B 객체를 생성하고 있다고 가정 할 때 A는 B에 강한 의존 관계를 갖는다.
- e.g.) Person 클래스 내부에 Chicken 객체를 생성하는 부분이 있다고 할 때, Chicken이 아니라 Pizza가 되려면 Person 클래스 내부를 변경해야한다.
- 유연성을 떨어트리고, 변경을 어렵게 만든다.
약한(느슨한) 결합
- 객체를 주입받음.
- 외부에서 생성된 객체를 Interface를 통해 넘겨받아 결합도를 낮추고, 유연한 구조를 갖으며 변경을 용이하게 만듦
- 위의 예시에서 Person 클래스는 Food Interface를 갖도록 하면, Chicken이든 Pizza든 Food에 주입(?)하도록 만들면 됨(implement)
- 이렇게 하면 Chicken -> Pizza로 변경할때 그 구현체만 변경하면 됨.
의존성 주입 방법 세가지
의존성 주입받을 클래스 A, 주입될 객체 B라고 가정.
1. Field Injection
: @Autowired
로 의존성 주입받는 방법
- 일단 간편하다. 그러나 많은 단점이 존재.
- DI 컨테이너와의 결합성과 테스트 용이성
- 일단 의존성을 받았으면, 독립적으로 Instance화 가능한 POJO여야 한다. Test 환경에서 Spring Been 컨테이너 없이 돌아가야 하는데, 이 방식으로 사용한다면 일단 테스트에 용이하지 않다.
- 단일 책임 원칙 위반 가능성
- 의존성을 주입하기 쉬워지고, 의존 객체가 많아지면 하나의 클래스가 많은 책임을 갖게 될 수 있음
- 의존관계가 보이지 않음
- DI 컨테이너에게 의존성 관리 책임을 위임하는 것이기 때문에 클래스 의존관계가 명확히 보이지 않는다.
- 불변성 불가
- (자바 기준) final 선언 불가. 따라서 객체가 불변성이 아님. Contructor Injection에서는 final로 명시해 불변 객체로 만들 수 있다.
2. Setter Injection
: setter를 통해 선택적으로 주입된 객체를 사용할 때
- 런타임에 수정자를 통해 의존성 주입을 하게 됨. -> 런타임 에러 우려
- setter를 통해 주입하려는 객체가 주입 되지 않았어도 베이스 객체는 얼마든지 생성, 사용될 수 있다는 것이 문제
- e.g) 만약 주입된 객체 본체(구현체)가 없는 상황이라고 가정할 때
- 일단 컴파일타임에는 생성, 사용 가능.
- 그러나 해당 의존 객체를 사용하려한다면 주입이 되지 않았기 때문에 NPE 발생 우려
- e.g) 만약 주입된 객체 본체(구현체)가 없는 상황이라고 가정할 때
3. Constructor Injection - 가장 권장.
: 객체를 생성하는 시점에 바로 의존성 주입.
- Spring에서 가장 권장하는 방식
- 순환 의존성을 알 수 있다.
- 컴파일 단계에서 확인 가능.
BeanCurrentlyInCreationException
발생
- 컴파일 단계에서 확인 가능.
- 필수적으로 사용해야하는 것 없이는 Instance를 만들지 못하도록 강제할 수 있음.
- 항상 의존관계가 주입되기 때문에 Setter에서의 NPE 문제를 피할 수 있다.
- 의존성 주입이 번거롭다
- 따라서 만약 생성자에서 너무 의존관계가 많아진다면 SRP 원칙을 고려하게 되고, 리팩토링이 필요한 시점이라는 것을 알 수 있게 된다.
- 테스트 용이
- DI 컨테이너와 결합도가 낮아 갖고 있는 의존성을 Instance화 할 수 있음.
- 불변으로 만들 수 있다.
- Kotlin에서는 기본적으로 val로 선언, java -> final
Reference)
https://velog.io/@gillog/Spring-DIDependency-Injection-%EC%84%B8-%EA%B0%80%EC%A7%80-%EB%B0%A9%EB%B2%95
https://velog.io/@damiano1027/Java-%EA%B0%95%ED%95%9C-%EA%B2%B0%ED%95%A9%EA%B3%BC-%EC%95%BD%ED%95%9C-%EA%B2%B0%ED%95%A9
https://ohjongsung.io/2017/06/02/%ED%95%84%EB%93%9C-%EC%A3%BC%EC%9E%85-field-injection-%EC%9D%84-%ED%94%BC%ED%95%98%EC%9E%90