반응형

@RequiredArgsConstructor를 처음엔

그냥 생성자를 알아서 주입해주는구나~ 생각만 가볍게 해두고 공식처럼 사용해왔다.

 

발단


그렇게 스프링부트 프로젝트를 협업을 통해 진행한지 좀 지났을 때

리팩토링을 위해 코드를 개선하다가 문제가 발생했다.

하나의 도메인에서 다른Repository를 불러오는 것이 응집도를 올린다고 생각했고, 또 Repository에 직접 접근하는 것은 막아야 한다고 생각했기에 xxxxRepository를 그대로 써오는 것에서 xxxxService로 변경해 사용하는 것으로 바꿔 생각했다.

이 과정에서 우리는 Service부분의 클래스 생성을 xxxxRepository → xxxxService로 변경, 생성자 주입을 시켰는데 문제가 발생했다..!

결론부터 말하자면 @RequiredArgsConstructor의 특성을 제대로 생각하지 못한 것이 문제였고 자세한 이유는 아래에서 다루겠다.

 

그래서


처음에 원인 파악을 할 때 해당 클래스들의 생성자 주입에서 final이 빠졌다고 인지를 아예 못 한 상황이였고, 때문에 한참을 뻘짓 한 것 같다.

그 때 당시에 코드변경 후 직접 실행해 확인하지 않고, 바로 테스트코드를 작성하고 있어서 해당 UserService 자체가 문제라고 인지하지 못했고,

테스트코드 작성도 익숙치 않은 상태라 테스트코드를 못짜서 그렇다고 판단을 했고, 테스트 환경을 좀 더 공부하는 뻘짓(?)을 했고, 해당 뻘짓을 할 때 디버그를 통해 알아낸 정보는 아래의 사진과 같았다.

Service에 있는 클래스가 모두 null로 되어있는 것… 이걸 발견하고도 한참 뻘짓하기도 하고 기초중의 기초적인 실수였지만....

그래도! 발견한 것에 의미를 두자! 라고 생각을 하기로 했다.

정리해서 말하자면 @RequiredArgsConstructor 어노테이션의 특성이 생성자 주입 시 final선언을 해줘야 자동으로 생성자 주입을 하고 스프링 빈을 생성하는데, final이 없어 생성자 주입을 하지 않았기 때문에 각 Service들이 null상태로 있었던 것이고, 이러한 문제가 발생했었던 것이다.

기존 UserService.java 생성자주입 예시

private final UserRepository userRepository;
private final UserTagRepository userTagRepository;
private final FriendRepository friendRepository;

 

xxxxService로 변경했을 때 문제가 있던 코드 필드

private final UserRepository userRepository;
private UserTagService userTagService;
private FriendService friendService;

 또 만약에 또 이런 문제가 생겼을 때 디버그를 통해 필드객체가 null로 되어있다면 final선언을 했는지 한번 더 확인할 수 있는 계기가 되었다.

반응형

'LTF(learn through failure) > Spring' 카테고리의 다른 글

SQL Injection  (0) 2023.09.30

+ Recent posts