프디아

[Spring] 객체를 주입하는 3가지 방식

inhooinu 2025. 2. 12. 23:26

이번 글에서는 Spring의 핵심 개념인 DI에 대해 알아보고, 이를 구현하는 세 가지 방식에 대해 정리해보고자 한다.

 

DI란?

DI는 Dependency Injection의 약자로, 말 그대로 의존성 주입을 의미한다.

Spring 개발 환경에서는 Spring IoC로 인해 객체에 대한 제어권을 개발자가 아니라 스프링이 갖게 된다.

따라서 개발자가 특정 객체를 사용하려면 어노테이션을 활용해 Spring에 객체 주입을 요청해야 한다.

 

이러한 DI (객체 주입) 방식에는 3가지가 있다.

 

첫 번째 방식: Setter 주입

public class ProductController {
    private ProductService productService;

    @Autowired
    public void setProductService(ProductService productService) {
        this.productService = productService;
    }
}

 

과거에 많이 사용되던 방법이다.

Setter 주입 방식은 Setter 메서드가 public으로 열려 있어 개발자가 언제든지 값을 변경할 수 있다는 점이 문제가 된다.
(객체의 일관성이 깨질 위험이 있기 때문)

 

두 번째 방식: 필드 주입

public class ProductController {
    @Autowired
    private ProductService productService;
}

 

필드 주입 방식을 사용하면 필드가 private, 즉, 외부에서 변경할 수 없으므로 Setter 주입 방식의 문제점을 해결할 수 있다.


하지만 TDD(Test-Driven Development)가 주목받으면서, 필드가 private으로 선언되어 테스트 시 다른 의존성을 주입하기 어렵다는 한계가 드러났다.

 

세 번째 방식: 생성자 주입

public class ProductController {
    private final ProductService productService;

    @Autowired
    public ProductController(ProductService productService) {
        this.productService = productService;
    }
}

 

생성자 주입 방식은 다음과 같은 장점을 가진다.

  • final 키워드를 사용하여 의존성이 변경될 가능성을 원천 차단할 수 있다.
  • Spring 없이도 new ProductController(new ProductService()); 와 같이 직접 객체를 생성하여 주입할 수 있어 테스트가 용이하다.

 

결론

간단한 코드를 작성할 때는 필드 주입 방식이 코드가 간결하다는 점에서 나쁘지 않은 선택일 수도 있다.

그러나 확장성과 TDD까지 고려한다면, 객체를 주입할 때는 생성자 주입 방식이 가장 적절한 선택이라고 할 수 있다.