[스프링 트러블슈팅] @Transactional이 이상해…

11월 초나 중순 쯤 KSUG에서 세미나를 한다길래 발표자로 지원했습니다. 예상 날짜는 11월 13인데 어찌될지는 아직 모릅니다. 제가 구상한 주제는 바로 “스프링 트러블슈팅”. 개구리 올챙이적 모른다고.. 저도 처음 스프링, 하이버네이트로 프로젝트를 시작했을 때 사소한 버그도 못잡아 토비님께 여쭤보곤 했었는데 요즘은 강의 다니면서 스프링 관련 문제들 찾아주고 해결해주는 재미가 쏠쏠 합니다. 잡아주기도 하고 잡는 방법을 알려드리기도 하는데… 그런 내용을 전달해 드릴계획입니다.

이번엔 그 중에 하나로 오늘 오전에 해결했던 문제 중 하나를 소개해 드릴까 합니다. 소개만…

[java]
public interface MemberService {

}
[/java]

[java]
@Service
@Transactional
public class MemberServiceImpl implements MemberService {

}
[/java]

[java]
@Controller
public class MemberController {
@Autowired MemberServiceImpl service;
}
[/java]

이렇게 설정한 상태에서 ApplicationContext를 만들다가 에러가 납니다. MemberController에 주입할 MemberServiceImpl 빈을 못 찾아서 MemberController의 @Autowired MemberServiceImpl 부분에서 에러가 납니다.

이 상황은 딱.. 예전에 토비님 블로그에 올라왔던 상황입니다. 토비님은 그 글에 대한 해답편도 올려두셨는데.. 해답은 토스3의 14장을 보라는 내용이었습니다. 지금 이 상황이 바로 그 퀴즈에 대한 정답이기도 하죠.ㅋㅋ

지금 이 상황에서 @Transactional을 지우면 에러 없이 ApplicationContext가 만들어 지지만 원하는 대로 동작하진 않겠죠. 트랜잭션이 필요했는데 그걸 못쓰는 것이니까요. 그럼 무엇이 문제이고 그 해결책은 무엇일까요. 객체지향적으로 생각하면 해결책은 쉽게 알 수 있는데 문제 원인을 남에게 설명할 수 있을 정도로 파악하기는 쉽지 않을 수 있습니다. 스프링 AOP에 대한 기본 지식을 잘 갖추고 있으시거나 토스3에서 AOP부분을 잘 읽으신 분들이라면 쉽게 알 수 있는 내용이긴 하죠.

저는 이 것과 더불어 스프링을 사용하시면서 자주 만나게 될 트러블들을 소개 및 재현해 드리고 그 원인과 해결책을 소개하는 시간으로 KSUG에서 뵙겠습니다. 아참.. 그리고 그날 제 발표 시간에 깜짝 이벤트도 준비 중이오니 많은 참석 바랍니다.

6 thoughts on “[스프링 트러블슈팅] @Transactional이 이상해…”

  1. 위에 예제는 잘 동작할것 같은데요 ㅎㅎ
    구현 메소드가 하나도 없어서 proxy가 안걸릴듯;;ㅎ

    나도 토스3보고 잡네요 ㅋ
    근데 긴가 민가 한데요 CGLIB 도 인터페이스 거시기 한놈도 만들어 주지 안나요? 저주 받은 머리;; ㅜㅠ

    1. ㅋㅋ코드를 너무 생략했나;

      CGlib만 놓고보면 그렇긴 한데 일단 스프링 AOP에선 인터페이스가 있고 기본값인 상태에선 JDK Proxy로 만드니깐.. 머; 흠냐 여기선 걍 JDK Proxy가 적용되면 문제(?)가 생기는거지..

      1. 인터페이스 기반으로 생성된 프록시가 concrete(콘크리트?ㅋㅋ)클래스로 기어들어가다 보니 모냥이 우스워져서. 에러가나는거구. 흠… 전 그것보다 봄싹에서 CGLIB으로 프록시 만들겠다고 설정되어 있는데.. 인터페이스 구현 클래스가 잘 프록시가 만들어진단 말이죠.. cglib으로 하는거 아닌가?ㅎㅎ

        1. 맞아 proxy-target-class가 true로 되어 있으면 무조건 CGlib 사용해서 클래스 기반 프록시 만들겠다는거지.. 왜? 그거 설정해도 JDK Proxy로 만들어져??

  2. 해답편 댓글에도 나오지만, 항상 AspectJ 를 쓰는 저는 JDK Proxy의 제약 사항을 알고도 맞출수 없었던 바로 그문제… 😀

Leave a Reply

Your email address will not be published. Required fields are marked *