Study/Spring

[Spring] 스프링 핵심 원리 - 의존관계 자동 주입

sw_develop 2025. 4. 16. 22:02

다양한 의존관계 주입 방법

  • 의존관계 주입은 크게 4가지 방법 존재
    • 생성자
    • 수정자(setter)
    • 필드
    • 일반 메서드

 

1) 생성자 주입

  • 특징
    • 생성자 호출 시점에 딱 1번만 호출되는 것이 보장
    • 불변, 필수 의존관계에 사용

 

예시)

@Component
public class OrderServiceImpl implements OrderService {
	
	private final MemberRepository memberRepository;
	private final DiscountPolicy discountPolicy;
	
	@Autowired // 생성자가 1개인 경우 생략 가능
	public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
		this.memberRepository = memberRepository;
		this.discountPolicy = discountPolicy;
	}
}

 

2) 수정자 주입

  • setter라 불리는 필드의 값을 변경하는 수정자 메서드를 통해 의존관계를 주입하는 방법
  • 특징
    • 변경, 선택 가능성이 있는 의존관계에 사용
      • 외부에서 setter 메서드 호출할 경우 변경될 수 있음
      • 스프링 빈이 존재하지 않을 경우 의존관계가 맺어지지 않을 수 있음
    • 자바빈 프로퍼티 규약의 수정자 메서드(setXXX) 방식을 사용하는 방법임

 

예시)

@Component
public class OrderServiceImpl implements OrderService {
	
	private MemberRepository memberRepository;
	private DiscountPolicy discountPolicy;
	
	@Autowired
	public void setMemberRepository(MemberRepository memberRepository) {
		this.memberRepository = memberRepository;
	}
	
	@Autowired
	public void setDiscountPolicy(DiscountPolicy discountPolicy) {
		this.discountPolicy = discountPolicy;
	}
}

 

3) 필드 주입

  • 특징
    • DI 프레임워크가 없으면 아무것도 할 수 없음
      • 외부에서 변경이 불가능해서 테스트하기 힘듦 (외부에서 의존관계 주입하려면 결국 setter 메서드 제공해줘야 함)
    • 사용하지 말자!
      • 어플리케이션의 실제 코드와 관계 없는 테스트 코드에는 OK
        • @SpringBootTest를 사용해 스프링 컨테이너를 사용하는 경우에만 동작함

 

예시)

@Component
public class OrderServiceImpl implements OrderService {
	
	@Autowired
	private MemberRepository memberRepository;
	
	@Autowired
	private DiscountPolicy discountPolicy;
	
}

 

4) 일반 메서드 주입

  • 특징
    • 한 번에 여러 필드를 주입받을 수 있음
    • 일반적으로 잘 사용하지 않음
    • 수정자 주입과 동일한 문제점 갖음

 

예시)

@Component
public class OrderServiceImpl implements OrderService {
	
	private MemberRepository memberRepository;
	private DiscountPolicy discountPolicy;
	
	@Autowired
	public void init(MemberRepository memberRepository) {
		this.memberRepository = memberRepository;
	}
}

 

생성자 주입을 선택해라!

  • 의존관계를 불변하게 만들 수 있음
    • 대부분의 의존관계 주입은 한 번 일어나면 어플리케이션의 종료 시점까지 변경할 일이 없음
    • 수정자 주입을 사용하면, setter 메서드를 public으로 열어두어야 하여 변경될 가능성 있음
    • 생성자 주입은 객체를 생성할 때 딱 1번만 호출되고 이후에 호출되는 일이 없음. 따라서 불변하게 설계할 수 있음
  • 의존관계 주입 누락 방지
    • DI 프레임워크 없이 순수한 자바 코드를 단위 테스트할 때 수정자 주입을 사용할 경우 의존관계 주입이 되지 않은 채 테스트가 수행되어 NPE 발생할 수 있음
  • final 키워드를 사용해 컴파일 시점에 의존관계 주입 오류 알 수 있음
    • 생성자 주입을 사용하면 필드에 final 키워드를 사용할 수 있음
    • 생성자에서 혹시라도 값이 설정되지 않은 오류를 컴파일 시점에 막아줌

 

참고

스프링 핵심 원리 - 기본편