클라우드 낚시꾼

[Spring] @Autowired(required)와 의존관계 주입 방법 본문

BE Framework/SpringBasic

[Spring] @Autowired(required)와 의존관계 주입 방법

KanuBang 2024. 3. 18. 13:12
728x90

의존관계 주입 방법에는 다음과 같은 4가지가 있다. 

  • 생성자 주입
  • 수정자 주입(setter 주입)
  • 필드 주입
  • 일반 메서드 주입

이 글에서는 위 4가지의 의존관계 주입 방법과 @Autowired에 대해 알아볼 것이다.


1. @Autowired와 required

@Autowired스프링 빈 클래스 내의 필드에 의존관계를 자동으로 주입한다. 참고로, 의존관계 자동 주입은 스프링 컨테이너가 관리하는 스프링 빈이어야 동작한다. 스프링 빈이 아닌 클래스에 @Autowired 코드를 적용해도 아무 기능이 작동하지 않는다.

 

@Autowired의 옵션 처리

 

@Autowired의 옵션인 required는 해당 의존성이 필수인지를 나타내는데 사용된다. @Autowired의 디폴트 required 값은 true 이다. 즉, @Autowired가 붙은 곳에는 스프링이 자동으로 의존관계 주입을 시도한다. 하지만, 이때 자동 주입 대상이 없으면 오류가 발생한다.

 

case1: setNoBean1 메서드

위 코드의 setNoBean1 메서드는 Member 클래스의 인스턴스를 주입받는다. 하지만, Member 클래스는 스프링 빈으로 등록되어 있지 않은 상황이라고 가정해보자. 이런 상황이라면, @Autowired가 자동 주입 대상을 찾지 못해 오류를 발생시킨다. 그래서 setNoBean1 메서드는 required를 false로 설정하여 자동 주입할 대상이 없으면 메서드 자체가 호출되지 않도록 하였다.

 

case2: setNoBean2 메서드

setNoBean2 메서드는 @Autowired의 required를 false로 설정하는 대신에 매개변수 앞에 @Nullable을 붙였다. @Nullable 애노테이션은 자동 주입할 대상이 없으면 null이 입력되게 한다.

 

case3: setNoBean3 메서드

setNoBean3 메서드는 @Autowired의 required를 false로 설정하여 자동 주입 대상을 찾지 못할 경우 메서드 자체가 호출되지 않도록 했다. 이때, 매개변수 앞에 Optional<>을 붙여 자동 주입할 대상이 없으면 Optional.empty가 입력되도록 하였다.


2. 생성자 주입

생성자 주입

 

생성자를 통해서 의존관계를 주입 받는 방식을 생성자 주입이라고 한다. 생성자 호출시점에 딱 1번만 호출되어 주입 받기에 불변, 필수 의존관계에 사용된다. 참고로, 생성자가 클래스 내에 하나만 존재하면, @Autowired를 생략해도 자동 주입 된다.


3. 수정자 주입(setter 주입)과 일반 메서드 주입

수정자 주입

 

필드의 값을 변경하는 수정자 메서드를(setter 메서드) 통해서 의존관계를 주입하는 방법이다. 선택, 변경 가능성이 있는 의존관계에 사용된다. 일반 메서드 주입은 setter 메서드 대신에 일반 메서드를 통해서 의존관계를 주입하는 방법이다. 


4. 필드 주입

필드 주입

 

필드에 바로 의존관계를 주입하는 방법이다. 코드가 간결해서 좋아 보이지만, DI 프레임워크가 없으면 아무것도 할 수가 없어 치명적이다.(자동으로 의존관계를 주입 받지 못하기 때문이다.) 예를 들어, 순수 자바 코드에는 당연히 @Autowired가 동작하지 않기 때문에 필드가 의존관계를 주입 받을 수 없다.


5. 생성자 주입을 선택하자

대부분의 의존관계는 불변해야 한다.

대부분의 의존관계는 주입이 한번 일어나면 애플리케이션 종료시점까지 의존관계를 변경할 일이 없다. 또한, 대부분의 의존관계는 애플리케이션 종료 전까지 불변해야 혼동이 발생하지 않는다. 생성자 주입은 객체를 생성할 때 딱 1번만 호출되므로 이후에 호출될 일이 없다. 따라서 의존관계를 불변하게 설계할 수 있다. 하지만, 수정자 주입을 사용하면, setXxx 메서드를 public으로 열어두어야 한다. 그렇기에 누군가 실수로 변경할 수도 있고, 변경하면 안되는 메서드를 열어두는 것은 좋은 설계 방법이 아니다.

 

수정자 주입의 누락 가능성

생성자 주입은 필수적인 의존관계에 사용되기 때문에 IDE가 컴파일 오류를 발생시켜 어떤 값을 필수로 주입해야 하는 지 알려준다. 하지만, 수정자 주입은 선택적인 의존관계에 사용되기 때문에 어떤 값을 필수로 주입해야 하는 지 알 수 없다. 이로 인해 수정자 주입은 의존관계 누락 가능성이 많다.

 

final 키워드는 생성자 주입만 사용할 수 있다.

어떤 클래스 내에 final 멤버가 있다면, 이 멤버는 선언 시점에 초기화되거나 생성자 시점에 초기화되어야 한다. 이런 final 멤버의 특성 때문에 수정자 주입과 final 멤버는 함께 쓰일 수 없다. 또한, 필드 주입은 DI 프레임워크 없이 순수 자바 코드로는 의존관계를 부여 받을 수 없기에 final 멤버와 함께 쓰일 수 없다. 그래서 결국 생성자 주입만이 final 멤버와 함께 쓰일 수 있다. 


6. 결론: 항상 생성자 주입을 선택하고 가끔 옵션이 필요하면 수정자 주입을 선택하자.

생성자 주입 방식을 선택하는 이유는 여러가지가 있지만, 프레임워크에 의존하지 않고, 순수한 자바 언어의 특징을 잘 살리는 방법이기도 하다. 기본으로 생성자 주입을 사용하고, 필수 값이 아닌 경우에는 수정자 주입 방식을 옵션으로 부여하자.


7. 세줄 요약 (+ 출처)

  1. @Autowired는 스프링 빈들 사이의 의존관계 자동 주입을 도와준다. 그리고 옵션 required는 해당 의존성이 필수인지를 나타낸다. 
  2. 생성자 주입은 불변, 수정자 주입은 선택적인 의존관계에 사용된다. 생성자 주입을 기본으로 하고, 선택적인 의존관계는 수정자 주입 방식을 사용하자.
  3. 필드 주입은 DI 프레임워크가 없으면 의존관계를 주입하고 변경하는 것이 아예 불가능하므로 안티 패턴이다. 일반 메서드 주입은 수정자 주입이 있기 때문에 잘 사용되지 않는다.
 

스프링 핵심 원리 - 기본편 강의 - 인프런

스프링 입문자가 예제를 만들어가면서 스프링의 핵심 원리를 이해하고, 스프링 기본기를 확실히 다질 수 있습니다., 스프링 핵심 원리를 이해하고, 성장하는 백엔드 개발자가 되어보세요! 📢

www.inflearn.com

 

728x90