DevBoi

[Spring] 의존성 주입에 대한 방법 정리 본문

Develop/[Spring]

[Spring] 의존성 주입에 대한 방법 정리

HiSmith 2022. 1. 17. 18:20
반응형

의존성 주입에 대해서는 3가지 방법이 존재한다.

 

1. 필드 주입

 

변수 선언부에 @Autowired를 붙인다.

예) 필드, 즉 변수 선언부에 @Autowired를 붙이면 된다.

 

2. 생성자 주입

 

사실상 저렇게 생성자에 주입을 받아도 되지만, final 과 RequiredArg 어노테이션을 사용해서 주입을 받아도된다

즉 lombok으로 의존관계를 설정하는 방법이다.

오류는 다른 이유에서 나는 거니까 무시하고, 해당 내용만 참고하도록 하자

 

3. 메소드 주입

setter 메소드를 사용해서 해당 의존성을 주입 받을 수도 있다.

 

 

필드고, 생성자고, 메소드고 를 떠나서 다 똑같이 @Autowired를 쓰고 있다는 것을 알수 있다.

이게 어떤식으로 동작을 하는걸까?

 

우선 @AutoWired는 의존관계를 주입할때 사용하는 어노테이션 이다.

즉 의존 객체의 타입에 해당하는 빈을 찾아 주입하는 역할을 한다.

 

빈이란, 스프링이 제어권을 가져서 직접 생성하고 의존관계를 부여, 관리하는 오브젝트를 의미한다.

 

빈은 생성되는 라이프사이클이 있다.

스프링 컨테이너에 등록이 되어있고  크게 객체생성, 의존관계 설정 초기화 소멸 순으로 나뉜다.

 

요로케 빈을 생성할때, 필요한 다른 빈들을 트리 형태로 가져와서 읽어들인다.

자바빈과 스프링 빈의 차이는, 제어권의 차이이다. 라이프 사이클을  스프링 컨테이너에게 넘긴것들은

스프링 빈이라고 불리며, 해당 스프링 빈은 컨테이너에 등록이 되어야 한다.

즉 컨트롤러나 서비스 Repository와 같은 것들에 한해서이다.

 

무튼 ! 그러면 어떤걸 쓰는게 가장 좋을까?

우선 스프링에서 권장하는 방법은 생성자를 통한 주입이다.

이유는 해당 빈이 의존성 없이는 생성이 불가능 하게 끔 할수 있기 떄문에 안전 고리같은 개념이기 때문이다.

 

!!생성자 주입일때 !!

1. 순환 참조 미리 방지

객체가 생성 되는 시점에 순환 참조를 방지 할수 있기 때문에 권장한다.

순환 참조란, 두개의 빈 A,B에서 서로를 의존주입을 원할때 생성시에 발생한다.

 

필드나 메서드 주입은 해당 시점에 발생하지만, 생성자는 초기 로드될때 빈이 생성되면서 이를 체크할수 있다.

즉 생성자는 구동할때 바로 순환 참조를 체크하여 방지할수있고, 메서드나 필드는 실행되고 나서야 순환참조 에러를 알수 있다.

 

2.불변성

또한 아까 말했듯이 final로 선언하게 되면, final은 null일수 없기 때문에 , 그리고 런타임 이후로 변하지 않기 때문에

불변성을 지킬수 있다.

 

3. 단일 책임의 위반, 리팩토링 시점 감지 가능

생성자로 만들다 보면 파라미터로 많은 injection 대상 빈을 넘기게 되고 이는 결국

한 빈에서 많은 책임을 가지고 있다는 것을 쉽게 알수있다.

이는 리팩토링 신호를 주기도 한다.

 

!!다른 주입일때!!!

다른 주입일때는 아래와 같은 크리티컬한 단점들이 존재한다.

1. final 객체를 사용할수 없어서, 값이 바뀌어 버릴수 있다.

2. 순환 참조 관련 해당 메소드나, 로직이 돌아가야만 알수 있다.

3. 추상화 되어있어서 정확한 의존관계를 알기 어렵다.

4. 단일 책임 원칙에 대한 리팩토링 감지가 어렵다.

5. final을 사용하지 않아서, 주입하지 않고 사용하면 NullPointException발생이 가능하다.

final은 기본적으로 null을 방지하지만, set 메소드로인한 주입의 경우, set해주지 않아도 객체 생성은된다.

이럴경우, set을 뺀채로 해당 빈의 메소드를 사용하려는 순간 npe가 떠버린다.

 

여러가지의 운영 방향성이나 관리의 측면에서 생성자 주입이 좋다는 것을 알수 있고,

필요시에는 set메소드를 조금 섞어서 쓰면된다.

의존 관계에 대해서 변경이 가능하거나 필요한 경우에는 setter 메소드를 사용해야하기 때문이다.

추가로, 자바빈 프로퍼티 규약으로 인해, 의존관계를 직접 바꾸지 않고 수정자 메서드 방식을 사용하여 바꾸기도 했다.

주입할 대상이 없으면 오류가 나고, 주입할 대상이 없어도 오류가 나는걸 방지하고 싶으면, @Autowired(required = false) 로 지정하면 된다.

 

의존관계를 변경할 일이 과거에는 많았다고 하지만, 요즘은 거의 없기때문에 사실상 생성자 주입이 올바른 관리 포인트이다.

 

 

반응형