이메일로 사용자가 인증코드 발송 요청을 보내면 적합한 회원인지 검증을하고, 인증 번호를 발송해준다. 인증 번호를 보낼 때 사용자가 여러 번 클릭해서 요청을 할 수도 있으므로 이전의 인증 번호를 삭제하고 다시 생성해서 DB에 저장후 보내준다.
하지만 실제로 삭제되지 않고 인증코드 발송 요청을 할때마다 쌓이는 문제가 발생했다.
sendEmail
에서 SMTP 외부 프로세스를 이용하므로 sendEmail
이 있는 메서드에 트랜잭션을 걸면 안된다고 생각을 했다. 외부 서비스를 이용하면서 많은 시간이 걸리는데 그 긴시간동안 기다리며 DB를 잠금해야하기 때문이다.
하지만 한 서비스에서 트랜잭션이 걸리지 않은 메서드에서 트랜잭션이 걸린 메서드를 호출한다고 해서 트랜잭션이 걸리는 것이 아니라는 것을 깜빡했다. AOP가 또 생성되지 않기 때문이다.
JPA는 트랜잭션 위에서 돌아가는데 트랜잭션이 없으므로 제대로 동작하지 않은 것이다. 그러면 delete
는 안되는데 save
는 왜 됐을까?
save는 내부적으로 구현을 보면 @Transactional
을 가지고 있다. 그래서 save
만 제대로 동작을 한 것이다.
지금 당장은 완벽한 해결책을 찾지 못했다. 간단하게 서비스 두 개로 분리해서 각각을 따로 호출하는 방식으로 하거나, 성능의 영향이 아주 크지 않다면 @Transactional
을 위의 메서드로 올려 둘 수도 있다.