Spring

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

dev-nadan 2025. 7. 29. 12:52

이전 편에서는 컴포넌트 스캔을 통해 빈을 자동 등록하고, 생성자에 @Autowired를 붙여 의존성을 주입하는 기본 방식을 살펴봤다. 이번 편에서는 스프링이 제공하는 다양한 의존관계 주입 방법들을 정리한다.


1. 생성자 주입

가장 권장되는 방식

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

 

  • 생성자 주입은 불변성(immutable) 을 보장할 수 있다.
  • final 키워드와 함께 사용하면, 필수 의존관계임을 명확히 할 수 있다.
  • 생성자가 하나뿐이면 @Autowired 생략 가능

왜 추천될까?

  • 생성 시점에 모든 의존성이 주입되므로, 객체가 완전히 초기화된 상태로 사용 가능
  • 테스트 코드에서 명확한 주입이 가능

2. 수정자(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;
    }
}

 

  • 스프링 컨테이너가 객체 생성 후, setter를 통해 의존성 주입
  • 선택적으로 의존관계를 주입할 때 유용
  • @Autowired(required = false)로 선택적 주입 가능

단점

  • 객체가 완전히 초기화되지 않은 상태로 사용될 수 있음
  • 불변성을 깨뜨림 → 유지보수 어려워짐

3. 필드 주입

절대 쓰지 말자

@Component
public class OrderServiceImpl implements OrderService {

    @Autowired
    private MemberRepository memberRepository;

    @Autowired
    private DiscountPolicy discountPolicy;
}

 

  • 간결하고 편리하지만 테스트가 매우 어려움
  • 의존성을 변경할 수 없기 때문에 불변성 보장도 안 됨
  • 외부에서 주입할 수 없어 DI 프레임워크에 강하게 결합
필드 주입은 테스트 코드도 작성하기 어렵고, 실제 코드가 스프링에 너무 의존적이기 때문에 안티패턴으로 간주됨. 절대 사용 금지

 


4. 일반 메서드 주입

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

 

  • 한 번에 여러 의존성을 주입받고 싶을 때 사용
  • setter 주입과 거의 유사하지만 일반 메서드에서 사용 가능
  • 잘 사용되진 않음

5. 자동 주입이 되기 위한 조건

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

설계 원칙 정리

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