sonarqube에서 아래와 같은 버그를 수정하라고 권고했다.
"saveUserSignUpInfo's" @Transactional requirement is incompatible with the one for this method.
기존 소스는 아래와 같은 방식으로 구현되어있었다.
같은 class 내부에서 메소드를 호출하는 방식이다.
public void signUp(UserAuthRequest request, HttpServletRequest servletRequest) throws Exception {
...
saveUserSignUpInfo(request);
}
@Transactional
public Long saveUserSignUpInfo(UserAuthRequest request) throws Exception {
...
}
In proxy mode (which is the default), only external method calls coming in through the proxy are intercepted. This means that self-invocation (in effect, a method within the target object calling another method of the target object) does not lead to an actual transaction at runtime even if the invoked method is marked with @Transactional. Also, the proxy must be fully initialized to provide the expected behavior, so you should not rely on this feature in your initialization code (that is, @PostConstruct).
스프링 문서에 따르면 Proxy Default Mode는 외부 메서드 (동일하지 않은 Bean)에서 호출하는 경우에만 프록시를 타고 Self(this.xxx())를 호출하는 경우 런타임에 @Transactional가 동작하지 않습니다. 또한 외부에서 Bean을 호출 하여 Proxy가 인터럽트 했더라도 동일한 Bean에서 this.xxxx()(Self 호출)에서는 Proxy가 동작하지 않게 됩니다.
=> 결론은 같은 Bean 내부에서 this.xxx()메서드 호출 시에는 proxy를 통해서 @Transactional 설정이 동작하지 않는다.
가장 간단한 해결 방법은 Service 클래스를 나누고 외부 Bean 호출을 통해서 Proxy가 올바르게 동작하게 하는 것이라고한다.
그래서 트랜젝셔널의 위치에 대해 다시 고민해보고 같은 Bean내에서 호출하는 것 아닌 다른 위치로 변경하였더니 소나큐브에서 해당 메세지는 사라졌다.
참고 블로그
https://cheese10yun.github.io/spring-transacion-same-bean/
소나큐브,소나린트를 사용하여 코드리팩토링을 하다보면 기본적인 것을 놓칠때도 많아서 공부를 많이해야겠구나 다시 생각하게 된다...ㅎ
잘 봤습니다. 좋은 글 감사합니다.