해결된 질문
작성
·
228
답변 2
4
제 미약한 지식이 조금이나마 도움이 되었으면 좋겠습니다!
//필드 주입 방식
@Autowired
private final MemberRepository memberRepository;
// final이 있다면 생성자로 초기화를 해줘야 하기 때문에 틀린 java 문법이라 생각합니다.
@Autowired
private MemberRepository memberRepository; // final 키워드 없음
// 질문자님의 의도는 이거 였을 것 같아 이것을 기준으로 설명드리도록 하겠습니다!
먼저 위의 코드는 필드 주입(Field Injection)이며, 의존성 주입 이후에도 해당 필드를 변경할 수 있게 됩니다. 이는 객체가 변경 가능(mutable) 상태가 되어, 런타임 중 객체의 상태가 예기치 않게 변경될 위험이 있습니다.
// 생성자 주입 방식
@Autowired
public MemberServiceImpl(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
반면 생성자 주입(Constructor Injection)을 사용하게 될 경우, 모든 의존성이 생성자를 통해 주입되고, 필드는 final로 선언될 수 있습니다. 이는 객체가 생성된 이후에도 상태가 변경되지 않는 불변성(immutable)을 보장하여, 객체의 안정성과 신뢰성을 높일 수 있습니다.
생성자 주입(Constructor Injection)을 사용할 경우 필요한 의존성이 명시적으로 드러납니다. 객체를 생성할 때 필요한 모든 의존성이 생성자 파라미터로 제공되기 때문에, 어떤 의존성이 필요한지 바로 알수 있게 됩니다. 이렇게 될 경우 코드의 가독성이 증가하고, 필수 의존성을 누락시키는 실수를 사전에 방지할 수 있게 됩니다.
하지만 필드 주입(Field Injection)을 사용할 경우, 클래스 내부를 들여다보지 않고는 객체 생성에 필요한 의존성이 무엇이 있는지 즉각적으로 알 수 없다는 문제가 있습니다.
생성자 주입을 사용하게 될 경우, 테스트 코드에서 특정 구현체나 목(mock) 객체를 쉽게 주입할 수 있습니다. 부연 설명을 하자면 스프링 컨테이너 없이도 순수 자바 코드로 단위 테스트를 진행할 수 있게 되며, 테스트의 단순성과 속도를 개선할 수 있다는 장점이 있습니다.
필드 주입을 사용하게 될 경우, 리플렉션 같은 추가적인 기술을 사용하지 않는 한, 테스트 환경에서 의존성을 주입하기 어렵습니다.
// 참고:
리플렉션이란, 자바에서 제공하는 API로 런타임 시점에서 클래스의 메타데이터를 조회하거나 수정할 수 있게 해주는 기능을 함. 자세히 궁금하다면 한번 찾아보세요!
생성자 주입을 사용할 경우, 순환 참조가 있는 경우 어플리케이션 시작 시점에서 바로 오류를 발생시킵니다. 즉, 순환 참조 문제를 조기에 발견하고 수정할 수 있게 해줍니다.
하지만 필드 주입을 사용하게 될 경우, 순환 참조가 발생하더라도 어플리케이션의 시작 시점에는 오류가 발생하지 않고, 런타임 중에만 문제가 드러나서 디버깅하는고 많은 고생을 하게될 것입니다.ㅎㅎ
정리하자면 이렇게 크게 4가지 이유로 많은 개발자들이 의존성 주입을 할 때는 생성자 주입을 권장한다고 합니다. But, 상황에 따라 필드 주입이나 setter 주입이 더 적합한 경우도 있으니 스승님께서 가르쳐 주신 방법들도 충분히 숙지하고 있다면 나중에 큰 도움이 될 것 같습니다.
// 저도 스프링을 배우는 학생이기 때문에 틀린 내용이 있다면 과감하게 지적해주세요!!
환영합니다~~