티스토리 뷰
[Spring] 생성자 주입을 사용해야 하는 이유, 필드인젝션이 안좋은 이유(+Lombok를 사용한 생성자 주입 방법)
Namhyun Sung 2019. 11. 20. 10:20Springboot를 활용하여 공부하고 있는 중 의존성 주입을 할때, Field
, Setter
Injection은 좋지 않다는 것을 알게 되었다. 왜 그런지 찾아보았고 정리해본다.
우선, 의존성 주입의 종류로는 Field
, Setter
, Constructor
이 있다.
1.
의존성 주입의 종류
1.Field Injection
@Service
public class MemberService{
@Autowired
private MemberRepository memberRepository;
}
2.Setter Injection
@Service
public class MemberService{
private MemberRepository memberRepository;
@Autowired
public void setMemberRepository(MemberRepository memberRepository){
this.memberRepository = memberRepository;
}
}
3.Constructor Injection
@Service
public class MemberService{
private MemberRepository memberRepository;
@Autowired
public MemberService(MemberRepository memberRepository){
this.memberRepository = memberRepository;
}
}
2. 왜 Constructor Injection을 권장하는가?
1. 단일 책임의 원칙
생성자의 인자가 많을 경우 코드량도 많아지고, 의존관계도 많아져 단일 책임의 원칙에 위배된다. 그래서 Constructor Injection을 사용함으로써 의존관계, 복잡성을 쉽게 알수 있어 리팩토링의 단초를 제공하게 된다.
2. 테스트 용이성
DI 컨테이너에서 관리되는 클래스는 특정 DI 컨테이너에 의존하지 않고 POJO여야 한다. DI 컨테이너를 사용하지 않고도 인스턴스화 할 수 있고, 단위 테스트도 가능하며, 다른 DI 프레임 워크로 전환할 수도 있게 된다.
3. Immutability
Constructor Injection에서는 필드는 final로 선언할 수 있다. 불변 객체가 가능한데 비해 Field Injection은 final는 선언할 수 없기 때문에 객체가 변경 가능한 상태가 된다.
4. 순환 의존성
Constructor Injection에서는 멤버 객체가 순환 의존성을 가질 경우 BeanCurrentlyInCreationException이 발생해서 순환 의존성을 알 수 있게 된다.
순환 의존성이란?
A Class가 있고 B Class가 있는데, 각각 서로가 서로를 참조하고 있는 상황에서 발생한다. 이러한 상황에서 A Class가 메모리에 올라가기 전에 B Class가 A Class를 의존주입하는 상황이나 혹은 그 반대의 경우 문제가 발생한다.
5. 의존성 명시
의존 객체 중 필수는 Constructor Injection을 옵션인 경우는 Setter Injection을 활용할 수 있다.
3. 테스트 코드 작성하기 좋다.
field Injection
의 경우 간단하긴하지만 테스트 코드를 작성할 때 불편하다는 단점이 있다. 어떤 불편함이냐면 단위 테스트를 하기위해 저 코드에서 Mock 객체로 끼워넣기가 복잡하다. 이유는 생성자
도, 수정자(setter)
도 없기때문이다.
그럼 setter Injection
은? setter Injection
은 테스트 코드 작성 시 mock
를 주입할 수 있다. 하지만 객체가 생성된 이후에도 주입된 객체들을 바꿀 수 있다는 단점이 있다. 하지만 내부 객체가 프로덕션 코드에서도 변경될 수 있기때문에 위험하기도 하다.
field, setter
주입은 이런 단점이 있기 때문에 Constructor Injection(생성자 주입)
을 사용해야된다. Constructor Injection
은 객체 생성시 주입객체를 받기 때문에 주입된 객체를 수정할 수 없다. 또한 생성자가 명시적으로 존재하기때문에 Mock 객체를 주입하기에도 편하다.
4. Lombok를 사용한 생성자 주입 방법
Constructor Injection
를 사용하면 코드가 복잡해 보일 수 있다. 이런 점을 보완하기 위해 Lombok
을 활용하는 방법도 많이 쓴다.
Lombok
의 @RequiredArgsConstructor
를 사용하는 방법인데 final
이나 @NonNull
이 설정된 필드 값을 파라미터로 받는 생성자를 만들어 준다.
@Service
@RequiredArgsConstructor
public class MemberService{
private final MemberRepository memberRepository;
}
위와 같은 코드를 작성하면 MemberRepository
에 한해서 생성자를 만들어 준다. 여러개의 의존성을 주입받는 경우 코드가 복잡해 보일 수 있기 때문에 위의 방법을 사용하는 것도 좋다.
5. 참고
-
https://yaboong.github.io/spring/2019/08/29/why-field-injection-is-bad/
-
실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발 in Inflearn
인프런의 JPA 활용1 강의를 통해서 생성자를 사용하는 이유, 롬복을 사용해서 주입받는 방법을 알게 되었다. 이 외에도 실무에서 쓰이는 것을 많이 알려주기 때문에 Spring, JPA를 공부하는 개발자라면 강력 추천한다!
'Programming > Java&Spring' 카테고리의 다른 글
[Java] final 키워드 (0) | 2020.05.29 |
---|---|
[Java] String, StringBuffer, StringBuilder 차이 (0) | 2020.05.26 |
Springboot jar 패키징 후 실행 방법 (0) | 2019.11.27 |
Maven과 Gradle (0) | 2019.11.23 |
Lombok 사용 시 @JsonIgnore 동작안하는 문제 해결 (0) | 2019.11.18 |
- Total
- Today
- Yesterday
- final
- 토비의스프링
- Spring
- 연동
- java
- apache
- StringBuilder
- 자바
- IoC
- stringbuffer
- 빈팩토리
- DI
- 쉘스크립트
- mod_jk
- 413
- lombok
- EmbededTomcat
- springboot
- jar 실행
- 스프링
- 템플릿
- AOP
- JsonProperty
- JsonIgnore
- 빌드도구
- Tomcat
- gradle
- 스프링프레임워크
- shellscript
- 애플리케이션컨텍스트
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |