🔍 이메일 인증 기능
이메일 인증 기능을 구현하고 있는데 트랜잭션 전파레벨과 관련한 문제가 있어 이를 정리하고자 합니다. 현재 로직은 다음과 같습니다.
- 회원가입을 하면 이메일로 UUID를 포함한 URL이 전송된다.
- 링크로 접속을 한다.
2-1. 만료가 되지 않았다면 사용자 인증 처리 된다.
2-2. 만료되었다면 UUID만 바꿔서 이메일은 재전송한다.
문제는 2-2에서 발생하였습니다. 이메일에는 바뀐 UUID로 전송이 되지만 DB에는 업데이트가 되지 않았습니다.
🔍 문제의 원인
문제의 원인은 빨간색 박스에 있습니다. 스프링에서 @Transactional는 같은 트랜잭션 안에서 하나의 쿼리라도 에러가 나면 모두 롤백하는 원자적 특성을 가지고 있습니다.
EmailToken이 만료가 되면 이를 새로 생성하고 예외를 던지는데, 이 부분에서 모두 롤백이 생깁니다.
만약 이메일 토큰도 새로 생성하고 싶고, 예외로 던지고 싶은데 어떻게 해야 할까?
🔍 트랜잭션 전파 레벨
트랜잭션 전파 레벨은 총 7가지가 있습니다.
- REQUIRED : 트랜잭션이 없다면, 새로운 트랜잭션을 생성한다.
- REQUIRES_NEW : 부모의 트랜잭션과 상관없이 항상 새로운 트랜잭션을 생성한다.
- SUPPORTS : 현재 트랜잭션이 있으면 이를 따라가고, 없으면 non-transactional하게 동작한다.
- NOT_SUPPORED : non-transactional하게 실행되며, 부모 트랜잭션이 존재하면 정지한다.
- MANDATORY : 부모 트랜잭션내에서 실행되면, 트랜잭션이 없으면 예외가 발생한다.
- NESTED : 부모 트랜잭션에서 진행될 경우 별개로 커밋되거나 롤백된다. 부모 트랜잭션이 없는 경우에는 REQUIRED와 동일하게 동작한다.
- NEVER : non-transactional하게 실행되며 트랜잭션이 존재하면 예외가 발생한다.
🔍 문제 해결
@Transactional의 전파 레벨은 REQUIRES_NEW로 설정하여 해결하였습니다.
🔍 테스트 코드