Spring

[Spring 완전 정복 시리즈] 18편 - 의존관계 자동 주입 방식 완전 정리

dev-nadan 2025. 7. 30. 13:03

이전 편에서는 다양한 방식으로 의존성을 주입하는 법에 대해 살펴봤다. 이번 편부터는 스프링이 제공하는 의존관계 자동 주입의 모든 방식을 정리하고, 실제 현업에서는 어떤 방식이 가장 효과적인지 비교 분석해본다.


생성자 주입 - 가장 권장되는 방식

@Component
public class OrderServiceImpl implements OrderService {

    private final MemberRepository memberRepository;
    private final DiscountPolicy discountPolicy;

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

 

  • 생성 시점에 한 번만 호출되므로 불변성을 보장할 수 있다.
  • final 키워드와 함께 사용하면 필수 의존성임을 명확히 표현할 수 있다.
  • 생성자가 하나라면 @Autowired는 생략 가능하다.
  • 테스트 코드에서 명시적으로 주입하기 용이하다.

수정자(setter) 주입 - 선택적 의존성에 사용

@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;
    }
}

 

  • 선택적 의존성, 혹은 변경 가능한 의존성 주입에 사용한다.
  • @Autowired(required = false) 옵션을 사용하면 빈이 없어도 예외가 발생하지 않음.
  • 단점: 객체가 완전히 초기화되지 않은 상태로 사용될 수 있으며, 불변성이 깨짐.

필드 주입 - 테스트 불가능, 사용 금지

@Component
public class OrderServiceImpl implements OrderService {

    @Autowired
    private MemberRepository memberRepository;

    @Autowired
    private DiscountPolicy discountPolicy;
}

 

  • 가장 간단해 보이지만 절대 권장되지 않는 방식
  • 외부에서 의존성을 변경하거나 주입할 수 없어 테스트 작성이 거의 불가능
  • DI 프레임워크에 강하게 결합됨 → 스프링이 아니면 작동하지 않음
  • 결국 테스트하려면 setter 만들어야 해서 본말전도

일반 메서드 주입

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

 

  • 일반 메서드에 @Autowired를 붙이면 의존성이 주입됨
  • setter 주입과 거의 유사한 방식
  • 거의 사용되지 않음, 필요 시 한 번에 여러 의존성을 넣고 싶은 경우만

자동 주입이 되기 위한 조건

  • @Autowired스프링 컨테이너가 관리하는 빈이어야만 동작함
  • new 키워드로 생성한 객체에는 아무런 주입이 일어나지 않음
  • 외부 객체나 빈이 아닌 객체에는 작동하지 않음

옵션 처리 - 빈이 없을 수도 있을 때

@Autowired(required = false)
public void setNoBean1(Member noBean1) {
    System.out.println("noBean1 = " + noBean1);
}

@Autowired
public void setNoBean2(@Nullable Member noBean2) {
    System.out.println("noBean2 = " + noBean2);
}

@Autowired
public void setNoBean3(Optional<Member> noBean3) {
    System.out.println("noBean3 = " + noBean3);
}
  • required = false: 아예 메서드 호출 안 됨
  • @Nullable: null 값으로 호출
  • Optional: Optional.empty로 주입됨

설계 원칙 요약

주입 방식 특징 사용 시점
생성자 주입 불변 + 필수 가장 권장, 기본값
수정자 주입 선택적 + 변경 가능 조건부 의존성
필드 주입 외부 주입 불가, 테스트 불가 사용 금지
일반 메서드 주입 한 번에 여러 의존성 주입 가능 거의 사용하지 않음