티스토리 뷰


스프링의 의존성 주입,  (필드 vs 생성자)

스프링의 의존성 주입방법에는 여러 가지가 있지만 아마 가장 많이 쓰이고 있는게 @autowired 를 통한 필드 주입일 것입니다. 하지만 여기서는 생성자 주입을 이용했을 때의 장점을 알아보겠습니다. 아래는 각각의 의존성 주입을 위한 간단한 샘플 코드 입니다.


Field injection

1
2
3
4
5
6
public class Member {
 
    @Autowired
    private ProductService productService;
}
 
cs


Constructor injection

1
2
3
4
5
6
7
8
public class Member {
    private final ProductService productService;
 
    @Autowired
    public Member(ProductService productService) {
        this.productService = productService;
    }
}
cs


1. 단일책임원칙

위 예제를 보면 필드를 통한 의존성 주입 방법이 더 간결하고 좋아 보입니다.  심지어 생성자를 통한 의존성 주입을 이용할 경우 Member 클래스가 사용하게 될 서비스가 늘어난다면 생성자 소스는 지저분 해질 것입니다. 아래처럼 말이죠.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Member {
    private final ProductService productService;
 
    private final GroupService groupService;
 
    private final BucketService bucketService;
 
    private final PayService payService;
 
    @Autowired
    public Member(ProductService productService, GroupService groupService, BucketService bucketService, PayService payService) {
        this.productService = productService;
        this.groupService = groupService
        this.bucketService = bucketService;
        this.payService = payService;
    }
}
cs

하지만 사실이건 클래스의 리팩토링 관점으로 접근해야 됩니다.

이렇게 생성자가 지저분 해진다는 건 클래스가 의 의존하는 클래스들이 많고 그렇다면 하나의 클래스가 많은 책임을 가지고 있을 가능성이 높습니다.(이건 SOLID 중 단일책임원칙 에 위배됩니다.) 꺼꾸로 보면 필드 주입은 저런 생성자 메소드의 복잡합이 노출되지 않기 때문에 편의대로 무분별하게 서비스를 사용할 수 있기에 객체지향적인 코드 관점에서는 독이 되는 경우입니다.

생성자 주입은 그런한 필수 의존성(final)을 명확하게 해주고 클래스가 커질 경우 코드 형태만으로도 문제가 있음을 알 수 있습니다.


2. IOC 컨테이너와의 의존성 해방

또한 DI 컨테이너와 의존 관계를 끊어 줍니다. 필드 주입을 해도 스프링 테스트 라이브러리를 이용해서 객체를 주입할 수 있지만 스프링 테스트 라이브러리를 이용하지 않고 테스트를 한다면 어떻게 될까요? 

1
2
3
  public List<Product> getProductList() {
      return productService.getList(this.memberNo); // Null Point Exception
  }
cs

ProductService 에 대한 setter 가 없기 때문에 객체를 생성해서 주입할 방법이 없습니다. 생성자 주입을 이용한 클래스일 경우에는 아래와 같이 사용 가능합니다. Spring Container 의존하지 않고 말이죠.

1
2
3
ProductService ps = new ProductServiceTest();
Member m = new Member(ps);
m.getProductList()
cs

3. POJO

추가로 생성자가 한개 일경우에는 스프링 4.3+ 에서는 @Autowired 주석도 삭제 가능합니다. 이렇게 되면 완벽히 POJO 스럽죠.

1
2
3
4
5
6
7
8
public class Member {
    private final ProductService productService;
 
    public Member(ProductService productService) {
        this.productService = productService;
    }
}
cs


이상 스프링의 생성자를 통한 의존성 주입의 장점을 알아보았습니다. 사실 필드 나, 생성자를 통한 의존성 주입 어떤 것을 사용해도 무방하다고 생각합니다. 단지 스프링 팀에서 생성자 주입을 권장하고 있고 이러한 장점이 있으니 선택은 여러 가지 개발 환경요인에 따라 결정하면 되겠죠.


공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크