티스토리 뷰

스프링 부트 환경에서 코드를 작성하던 와중에 문득 그런 생각이 들었다.

“나는 왜 의존주입할 때 생성자 주입을 주로 사용하고 있지?”

 

저 생각이 떠올랐지만 명확하게 이유를 설명할 수는 없었다.

그래서 이번 기회에 왜 생성자 주입을 사용하고 많은 사람들이 생성자 주입을 하는지 알아보겠다.


의존주입의 종류

의존주입의 종류에는 보통 세가지가 있다.

 

생성자 주입

  • 의존관계가 변하지않고 필수로 필요한 경우에 사용
  • 스프링에서는 생성자가 하나 있다면 @Autowired 생략가능
  • 필드를 final로 선언가능 => 불변 선언 가능
@Service
public class TestService {
    
    private final BoardRepository boardRepository;
    
    @Autowired
    public TestService(BoardRepository boardRepository) {
        this.boardRepository = boardRepository;
    }
}

생성자 주입은 위와 같은 형태이다. 생성자가 하나인 경우에 @Autowired는 생략가능하고 Lombok과 함께 사용한다면 더욱 간단하게 코드를 작성할 수 있다. 코드는 아래와 같다.

@RequiredArgsConstructor
@Service
public class TestService {
    
    private final BoardRepository boardRepository;
}

Lombok의 @RequiredArgsConstructor는 final이 붙은 필드에 대해 생성자를 작성해 준다. 

 

필드 주입

  • 필드에 @Autowired 어노테이션을 붙임으로써 의존주입
  • 인텔리제이를 사용하며 IDE에서 경고문구를 띄움
  • 프레임워크가 없다면 사용불가한 방법
  • 테스트코드에서는 간단하게 사용 중

인텔리제이에서 추천하지 않는다.

setter 메서드 주입

  • setter 메서드위에 @Autowired 어노테이션을 붙임
  • 의존관계를 변경할 경우 사용함, 하지만 변경하는 경우가 거의 없음

그럼 왜 생성자 주입이 좋은 것일까?

생성자 주입을 사용하면 좋은 점

필드를 final로 선언하면서 객체의 불변성을 보장할 수 있다.

처음 인스턴스가 생성될 때 이후에 필드를 변경하고자 하면 에러가 발생한다. 이로써 객체의 불변성이 보장된다.

만약 setter메서드 주입을 사용한다면 외부에서 의존관계가 변경될 가능성이 열려있는데 생성자 주입을 사용한다면 

변경 가능성을 완전히 지울 수 있다.


테스트 코드 작성에 용이하다.

서비스 계층에 대한 단위 테스트 코드를 작성한다고 가정해보자.

해당 클래스가 의존하는 다른 클래스가 있을 것인데  이 의존관계를 setter메서드 주입을 통해 주입한다면 1번의 장점이 사라진다. 아니면 필드 주입을 사용한다고 하면 단위 테스트를 작성하기는 힘들어질 것이다. 왜냐하면 @Autowried를 통해 프레임워크가 주입해주기 때문에 의존 객체에 대한 Mock객체 등을 개발자가 임의로 주입할 수 없기 때문이다.

하지만 생성자 주입은 테스트코드 단에서 테스트 대상 코드에 Mock 객체를 의존주입하거나 커스텀한 객체를 의존주입할 수 있게되어 테스트 코드 작성에 용이해 진다.


Lombok 라이브러리와의 궁합

위에서 얘기했듯이 Lombok의 @RequiredArgsConstructor를 통해 코드가 간결해지는 장점을 가져갈 수 있고

더구나 final을 붙일 수 있으므로 객체의 불변성이라는 장점까지 가져가게 된다. 개발자 입장에서는 굉장히 편리한 것이다.

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/09   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
글 보관함