[스프링-기본편] 다양한 의존관계 주입 방법

박준수·2022년 11월 4일

생성자 주입

  • 생성자 주입은 이름 그대로 생성자를 통해 의존관계를 주입받는 방법
  • 생성자 호출 시점에 딱 한번만 호출되는 것이 보장된다.
  • 주로 불변, 필수 의존 관계에 사용한다.

불변 : 처음에 세팅한 값을 변경하는 것을 허용하지 않는 것
필수 : 변수에 final 키워드를 적용하면 무조건 값이 초기화되어야 한다. 따라서 해당 필드가 초기화되어있지 않으면 컴파일 오류를 발생시킨다. 생성자로 해당 필드를 필수로 초기화해야한다.

생성자가 딱 1개만 있으면 @Authwiired를 생략해도 자동 주입된다.

수정자 주입(Setter 주입)

  • setter라 불리는 필드의 값을 변경하는 수정자 메서드를 통해 의존관계를 주입하는 방법
  • 선택, 변경 가능성이 있는 의존관계에 사용

필드 주입

  • 이름 그대로 필드에 바로 주입하는 방법이다.
  • 코드가 간결하지만 외부에서 변경이 불가능해서 테스트 하기 힘들다는 치명적인 단점!
  • DI 프레임워크(스프링)가 없으면 아무것도 할 수 없다.
  • 즉 사용하지 말자!

@SpringBootTest 처럼 스프링 컨테이너를 테스트에 통합한 경우에만 가능하다.

일반 메서드 주입

  • 일반 메서드를 통해서 주입 받을 수 있다.
  • 한번에 려버 필드를 주입 받을 수 있다.
  • 일반적으로 잘 사용하지 않는다.

생성자 주입을 권장하는 이유

불변

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

누락

프레임워크 없이 순수한 자바 코드를 단위 테스트하는 경우는 굉장히 많다.
이때 수정자 의존관계 등을 사용한다면, 만약 실수로 setter를 호출하여 의존관계를 주입하는 것을 누락한다면, Null Point Exception 등의 런타임 에러가 발생할 수 있다.
하지만 생성자 주입을 사용한다면 실수로 주입 데이터를 누락했을 때 런타임 에러가 아닌 컴파일 오류가 발생한다. 컴파일 오류는 세상에서 가장 빠르고, 좋은 오류다!!
즉, IDE에서 바로 어떤 값을 누락했는지 쉽게 파악할 수 있다. 따라서 수정자 주입보다 누락을 쉽게 잡을 수 있다.

final 키워드

생성자 주입을 사용하면 필드에 final 키워드를 사용할 수 있다. 따라서 생성자에서 혹시라도 값이 설정되지 않는 오류를 컴파일 시점에 막아준다. 수정자 주입등의 나머지 주입 방식은 모두 생성자 호출 이후에 호출되므로, 필드에 final 키워드를 사용할 수 없다.

결론 : 그냥 생성자 주입 방식을 사용하고 필수 값이 아닌 경우에는 수정자 주입 방식을 옵션으로 부여하면 된다. (생성자 주입과 수정자 주입을 동시에 사용할 수 있다.)

출처 : 출처

조회 빈이 2개 이상일 때

조회한 빈이 모두 필요할 때

예를 들어 할인 서비스를 제공하는데, 클라이언트가 할인의 종류(rate, fix)를 선택할 수 있다면은 의도적으로 정말 해당 타입의 스프링 빈이 다 필요하다.


로직 분석

DiscountService는 Map으로 모든 DiscountPolicy 를 주입받는다. 이때 fixDiscountPolicy ,rateDiscountPolicy 가 주입된다.
discount () 메서드는 discountCode로 "fixDiscountPolicy"가 넘어오면 map에서
fixDiscountPolicy 스프링 빈을 찾아서 실행한다. 물론 “rateDiscountPolicy”가 넘어오면
rateDiscountPolicy 스프링 빈을 찾아서 실행한다

주입 분석

Map<String, DiscountPolicy> : map의 키에 스프링 빈의 이름을 넣어주고, 그 값으로
DiscountPolicy 타입으로 조회한 모든 스프링 빈을 담아준다.
List : DiscountPolicy 타입으로 조회한 모든 스프링 빈을 담아준다.
만약 해당하는 타입의 스프링 빈이 없으면, 빈 컬렉션이나 Map을 주입한다.

자동, 수동의 올바른 실무 운영 기준

애플리케이션은 크게 업무 로직과 기술 지원 로직으로 나눌 수 있다.

  • 업무 로직 빈: 웹을 지원하는 컨트롤러, 핵심 비즈니스 로직이 있는 서비스, 데이터 계층의 로직을 처리하는 리포지토리등이 모두 업무 로직이다. 보통 비즈니스 요구사항을 개발할 때 추가되거나 변경된다.
  • 기술 지원 빈: 기술적인 문제나 공통 관심사(AOP)를 처리할 때 주로 사용된다. 데이터베이스 연결이나, 공통 로그 처리 처럼 업무 로직을 지원하기 위한 하부 기술이나 공통 기술들이다.

애플리케이션에 광범위하게 영향을 미치는 기술 지원 객체는 수동 빈으로 등록해서 딱! 설정 정보에 바로 나타나게 하는 것이 유지보수 하기 좋다!

비지니스 로직중에서 다형성을 적극 활용할 때 어떤 빈들이 주입될 지, 각 빈들의 이름은 무엇일지 코드만 보고 한번에 쉽게 파악하기 쉽지 않기에 수동 빈으로 등록하거나 또는 자동으로 하면 특정 패키지에 같이 묶어두는게 좋다!

profile
방구석개발자

0개의 댓글