본문 바로가기
BackEnd/Spring

의존 관계 자동 주입

by 규난 2022. 12. 18.
728x90

다양한 의존 관계 주입 방법

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

생성자 주입

  • 이름 그대로 생성자를 통해서 의존 관계를 주입 받는 방법
  • 생성자 호출시점에 딱 1번만 호출되는 것이 보장
  • 불변, 필수 의존 관계에 사용
@Component
public class OrderServiceImpl implements OrderService {

	private MemberRepository memberRepository;
  private DiscountPolicy discountPolicy;

	// 생성자가 딱 1개만 있으면 @Autowire 생략 가능
	@Autowire
	public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
        this.memberRepository = memberRepository;
        this.discountPolicy = discountPolicy;
	}
}

수정자 주입

  • setter라 불리는 필드의 값을 변경하는 수정자 메서드를 통해 의존 관계를 주입하는 방법
  • 선택, 변경 가능성이 있는 의존 관계에 사용
  • 자바빈 프로퍼티 규약의 수정자 메서드 방식을 사용하는 방법 (get…, set… 라는 메서드를 통해 읽고 쓰는 규칙)
@Component
public class OrderServiceImpl implements OrderService {

	private MemberRepository memberRepository;
  private DiscountPolicy discountPolicy;

	@Autowire
	public setMemberRepository(MemberRepository memberRepository) {
        this.memberRepository = memberRepository;
	}

	@Autowire
	public setDiscountPolicy(DiscountPolicy discountPolicy) {
        this.discountPolicy = discountPolicy;
	}
}

필드 주입

  • 이름 그대로 필드에 바로 주입하는 방법
  • 코드가 간결하지만 외부에서 변경이 불가능해서 테스트하기 힘들다는 단점이 있음
    • 스프링 없이 테스트를 하면(예를 들어 MockTest) DI가 되지 않아 memberRepsitory와 discountPolicy에 null이 들어가서 테스트를 진행할 수 없음. 테스트를 하려면 결국 OrderServiceImpl setter 메서드가 필요하게 되고 테스트가 힘들어지는 단점이 생김
  • DI 프레임워크가 없으면 아무것도 할 수 없음
  • 인텔리제이에서는 권장하지 않는 방식이라고 알려 줌
  • 어플리케이션의 실제 코드와 관계 없는 테스트 코드와 스프링 설정 목적으로 하는 @Configuration 같은 곳에서만 사용하자
@Component
public class OrderServiceImpl implements OrderService {

	@Autowire
	private MemberRepository memberRepository;

	@Autowire
  private DiscountPolicy discountPolicy;
}

일반 메서드 주입

  • 일반 메서드를 통해 주입을 받고 한번에 여러 필드를 주입 받을 수 있음
  • 잘 사용하지 않음
@Component
public class OrderServiceImpl implements OrderService {

  private MemberRepository memberRepository;
  private DiscountPolicy discountPolicy;

	@Autowired
  public void init(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
      this.memberRepository = memberRepository;
      this.discountPolicy = discountPolicy;
  }
}

생성자 주입을 사용해라

불변

  • 대부분 의존관계 주입은 한번 일어나면 어플리케이션이 종료시점까지 의존관계를 변경할 일이 없다. 오히려 대부분의 의존관계는 어플리케이션 종료 전까지 변하면 안된다.
  • 수정자 주입을 사용하면 public method를 사용해 set, get method를 열어두는데 누군가 실수로 set method를 이용해 변경 할 수 있기 때문에 좋은 설계가 아니다.
  • 생성자 주입은 객체를 생성시 딱 1번만 호출이 되므로 이후에 호출되는 일이 없어서 불변하게 설계가 가능하다.

누락

  • 필드에 final 키워드를 사용하여 혹시라도 생성자에 값이 설정되지 않은 경우 컴파일 시점에 에러를 알려주기 때문에 의존관계 주입으 누락을 막을 수 있다.

롬복을 이용하여 생성자 생성하기

  • @RequiredArgsConstructor 어노테이션을 이용하면 final이 붙은 필드를 모아서 생성자를 자동으로 만들어 줌
@Component
@RequiredArgsConstructor
public class OrderServiceImpl implements OrderService {
  private final MemberRepository memberRepository;
  private final DiscountPolicy discountPolicy;

	// 롬복이 생성자 코드를 자동으로 만들어 줌
	// public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
	// 	this.memberRepository = memberRepository;
	// 	this.discountPolicy = discountPolicy;
	// }
}

자동, 수동 의존 관계 주입의 올바른 실무 운영 기준

  • 업무 로직 빈과 기술 지원 빈을 나눈다.
  • 업무 로직 빈이란 웹을 지원하는 컨트롤러, 핵심 비지니스로직이 있는 서비스, 데이터 계층의 로직을 처리하는 리포지토리등이 모두 업무 로직이다.
  • 업무 로직은 유사한 패턴이 있기 때문에 자동 의존 관계 주입을 사용하는 것이 좋고, 보통 문제가 발생해도 어떤 곳에서 문제가 발생했는지 파악하기 쉽다.
  • 기술 지원 빈 이란 기술적인 문제나 공통 관심사(AOP)를 처리할 때 주로 사용된다. 데이터 베이스 연결이나 공통 로그 처리 처럼 업무 로직을 지원하기 위한 하부 기술이나 공통 기술이다.
  • 기술 로직은 업무 로직과 비교해서 양이 매우 적고, 보통 어플리케이션 전반에 걸쳐 광범위하게 영향을 미친다. 그리고 기술 지원 로직 적용이 잘 되고 있는지 아닌지 파악하기 어려운 경우가 많아서 가급적 수동 의존 관계 주입을 사용해 명확하게 드러내는 것이 좋다.
728x90

'BackEnd > Spring' 카테고리의 다른 글

DispatcherServlet과 Spring MVC 아키텍처  (0) 2022.12.18
빈 스코프  (0) 2022.12.18
빈 생명주기 콜백  (0) 2022.12.18
싱글톤 컨테이너  (0) 2022.12.18
OOP 5가지 원칙 SOLID과 IoC, DI  (0) 2022.12.18