Backend/Spring(활용)

Spring 의존관계 자동 주입(DI) 방식 선택 기준 정리

개발자-제이 2025. 4. 1. 14:19

 

1. 의존관계 자동주입이란?

스프링에서의의존관계 자동 주입(Dependency Injection, DI)이란, 개발자가 직접 객체를 생성하지 않고 스프링 컨테이너가 필요한 의존 객체를 자동으로 주입해주는 기능이다.

@Component
public class OrderService {
    private final PaymentService paymentService;

    public OrderService(PaymentService paymentService) {
        this.paymentService = paymentService;
    }
}

이처럼 객체 간 결합도를 낮추고 유연하고 테스트 가능한 구조를 만들 수 있게 해준다.

 

2. 의존관계 주입 방식과 예제

먼저 의존성 인터페이스와 구현체를 정의한다.

public interface PaymentService {
    void pay(int amount);
}

@Component
public class KakaoPaymentService implements PaymentService {
    public void pay(int amount) {
        System.out.println("카카오페이로 결제: " + amount + "원");
    }
}

2.1 생성자 주입 (가장 권장되는 방식)

@Component
public class OrderService {

    private final PaymentService paymentService;

    @Autowired // Spring 4.3+ 에서는 생략 가능
    public OrderService(PaymentService paymentService) {
        this.paymentService = paymentService;
    }

    public void processOrder(int amount) {
        paymentService.pay(amount);
    }
}

장점: 불변성 유지, 테스트 용이성 ↑, DI 실패 시 컴파일 타임 에러 유도

2.2 필드 주입

@Component
public class OrderService {

    @Autowired
    private PaymentService paymentService;

    public void processOrder(int amount) {
        paymentService.pay(amount);
    }
}

 

  • 장점: 코드 간결
  • 단점: 테스트 어려움, 순환참조 발생 시 탐지 어려움

 

2.3 세터 주입

@Component
public class OrderService {

    private PaymentService paymentService;

    @Autowired
    public void setPaymentService(PaymentService paymentService) {
        this.paymentService = paymentService;
    }

    public void processOrder(int amount) {
        paymentService.pay(amount);
    }
}

 

  • 장점: 선택적 의존성에 적합
  • 단점: 불변성 깨짐, 누락 가능성 존재

 

 

 

3. @Autowired를 이용한 자동주입

@Component
public class MyService {
    @Autowired
    private DependencyService dependency;
}

 

  • 타입 기반 매칭
  • 동일 타입이 여러 개일 경우 @Qualifier나 @Primary 사용
  • @Autowired(required = false) 또는 Optional<>로 선택적 주입 가능

 

4. 생성자 vs 필드 vs 세터 주입

 

주입 방식 장점 단점 실무 추천도
생성자 주입 불변성 보장, 테스트 용이 코드 길어짐 ⭐⭐⭐⭐
필드 주입 코드 간결 테스트 불가, 유지보수 불리
세터 주입 선택적 주입 가능 필수 누락 가능성 ⭐⭐

 실무에서는 생성자 주입 + Lombok(@RequiredArgsConstructor) 조합이 가장 많이 쓰인다.

 

5. 자동주입 시 고려할 점

@Qualifier

@Autowired
@Qualifier("kakaoPaymentService")
private PaymentService paymentService;

@Primary

@Primary
@Component
public class DefaultPaymentService implements PaymentService {}

Optional

@Autowired
private Optional<PromotionService> promotionService;

 

6. Spring Boot의 자동 구성과 DI

 

  • @SpringBootApplication 내부의 @ComponentScan이 자동으로 Bean을 탐색
  • @Component, @Service, @Repository, @Controller 등은 모두 DI 대상

 

7. Bean의 스코프와 주입 시기

 

스코프 설명 객체 생성 시점
Singleton (기본) 애플리케이션당 1개 컨테이너 초기화 시
Prototype 요청마다 새로운 객체 요청 시 생성
Request HTTP 요청당 웹 요청 시 생성
Session 세션당 세션 생성 시

 싱글톤에서 프로토타입 빈 주입 시 Provider 또는 ObjectFactory를 활용해야 함.

 

8. 실무에서의 Best Practice

 

  • 생성자 주입을 기본으로 통일
  • 필수 → 생성자, 선택 → 세터 or Optional
  • @Autowired 생략 가능 (생성자 1개일 경우)
  • @Qualifier, @Primary를 통한 명확한 주입 처리
  • ComponentScan 범위 명확히 지정

 

9. 요약

 

항목 설명
의존관계 주입 객체 간 관계를 외부에서 설정
추천 주입 방식 생성자 주입 + final + Lombok
DI 핵심 애노테이션 @Autowired, @Qualifier, @Primary
장점 결합도 감소, 테스트 유리, 유지보수 용이
주의할 점 순환 참조, 스코프 관리, 의존성 누락

 

반응형