Spring - 생성자 주입의 장점, @RequiredArgsConstructor 쓰는 이유

devdo·2022년 1월 15일
0

Spring

목록 보기
8/11
post-thumbnail

Spring에서는 빈을 주입을 하는 방식이 단순히 어노테이션으로 @Bean, @Component, @Configuration 을 사용하는 것도 있지만 Java 코드를 사용해서 빈으로 등록하는 방법도 있습니다.

그중 하나가 생성자 주입 방식인데요. 이를 사용하는 이유를 정리합니다.

@Component
// @RequiredArgsConstructor // delombok
public class BComponent {
    private final AComponent aComponent;

    public BComponent(AComponent aComponent) {	// parameter를 받음
        this.aComponent = aComponent;
    }
}

일단 생성자주입 방식외에 parameter를 받으므로써 자바는 객체를 주입한다.

Java에서는 객체를 주입하는 방법이 파라미터를 받는 방법 밖에 없다. (토비의 스프링 vol1.0)

그렇다면 왜 setter, 메서드 방식 등 다른 방법 외에 생성자 주입방식을 권고하는 걸까?

☑️ 스프링team에서는 spring4.0(SpringBoot)부터 생성자 주입 방식을 권장합니다!


1) 런타임 의존성이 가능

객체를 생성하는 시점을 어플리케이션이 실행할 때(Runtime시) 의존성이 생성된다.

2) 명시적인 의존성

의존성이 숨겨져 있으면 그 클래스 안에 직접 살펴볼 수 밖에 없다. 숨겨진 의존성 방식은 별로다. 생성자주입 방식은 인자를 명시적으로 볼 수 있다.

3) 불변이다.

의존관계를 설정하는 부분과 시스템을 돌아가게하는 부분은 분리되어야 한다. (CleanCode)
변경 가능성을 최소화하라. (Effective Java)
수정자 주입을 사용하려면 setter 를 public 으로 열어야한다.
객체의 상태가 변경가능하면 문제가 생길 소지가 너무 크다.

생성자 주입은 빈이 등록되기위해
싱글톤 객체가 생성될 때 딱 한번만 주입하고 변경되지 않는다.

4) 테스트의 편함(컴파일 오류로 확인가능)

생성자 주입은 생성자의 매개변수로 주지 않으면 애초에 컴파일에러가 난다.
또, IDE 의 도움을 받으면 코드 작성시 매개변수로 확인도 가능하다.

수정자 주입에서는 의존관계가 무엇이 있었는지 있긴 한지는 코드의 setter 를 까봐야한다.
또한 런타임에 에러가 나게 된다.

또, 실제 Junit 테스트 프레임워크를 사요할 시, 생성자 주입은 테스트하기 쉬운 코드를 작성하는 데 도움이 됩니다. 의존성을 명시적으로 주입받으므로, Mockito와 같은 모킹 프레임워크를 사용하여 단위 테스트를 쉽게 작성할 수 있습니다.

5) final로 불변성 유지, 코드 깔끔해져!

@RequiredArgsConstructor 어노테이션을 사용한 생성자 주입방식을 사용하려면, final 을 쓸 수 밖에 없다!

☑️ final을 쓰는 건 엄연히 불변성을 위해서다!

필드에 final 을 쓰면 생성자나 필드 선언시에 초기화를 해야한다. 안그러면 컴파일에러다.
따라서 의존관계 주입 로직을 누락하는 실수를 방지할 수 있다.

앵간하면 생성자 주입을 쓰고, 특수한 상황에서만 setter(수정자) 주입을 쓰자.

그리고 필드 주입(@Autowired)도 테스트하기 어려운 등 단점이 존재하여 Intellij 에서도 되도록 쓰지말라고 경고를 띄운다.

Lombok의 이 어노테이션 기능을 쓰면 final 이 붙은 필드는 생성자 주입이 되어진다.

생성자가 하나만 있으면 @Autowired 가 붙여지는 것과 동일한 효과를 가지게 된다!

롬복까지 이용하여 생성자를 하나 만드는 @RequiredArgsConstructor 어노테이션을 사용하면, 코드가 매우 깔끔해진다.

예시

@Service 
@RequiredArgsConstructor 
public class MyService { 
	private final MyRepository myRepository; // Lombok이 자동으로 생성해주는 생성자
    
    // public MyService(MyRepository myRepository) { 
    	// this.myRepository = myRepository; 
    // } 
}


참고

https://alkhwa-113.tistory.com/entry/생성자-자동-주입의-장점 [기(술) 블로그]

profile
배운 것을 기록합니다.

0개의 댓글