프로그래밍/spring

@Transactional 롤백 동작 정책 (예외가 발생했는데 롤백이 안될때)

승민아 2024. 3. 6. 14:20

클라이언트는 회원가입시 이메일 인증 번호와 프로필 이미지를 서버로 전송한다.

이때 이메일 인증 번호가 일치할때

이메일 인증서를 찾아 삭제하고, 프로필 이미지 업로드 로직을 수행한다.

 

그런데 프로필 이미지 업로드 로직을 수행할때

업로드 용량의 제한이 있어서 예외가 발생할 수 있다. 이때 @Transactional을 통해 롤백을 수행하여

삭제한 이메일 인증서를 삭제하지 않고 다시 원래 상태로 DB에 두는 롤백을 원했다.

 

그러나 예외는 발생했지만 롤백은 되지 않는 문제가 발생했다.

 

문제의 코드는 다음과 같다.

@Transactional
public MemberResponse addMember(SignUpMember signUpMember, MultipartFile memberImg) throws DuplicateException, IOException, MailException, FileException {

    //  findBy로 메일 인증서 반환
    MailCertification mailCertification = mailCertificationRepository.findByMail(mail)
        .orElseThrow(() -> new MailException(ErrorCode.NOT_MAIL_CERTIFICATION));
        
    // 메일 인증서 삭제
    mailCertificationRepository.delete(mailCertification);
    
    ...
        
    if (memberImg != null) {
        if(memberImg.getSize() > 1000000) { // 프로필 이미지 용량 예외
            throw new FileException(ErrorCode.FAIL_FILE_SIZE);
        }
    }
}

 

 

DB 상태는 다음과 같다.

현재 이메일과 그 이메일 인증 번호가 DB에 존재하는 상황이다.

 

발생한 예외가 용량 예외는 아니지만

파일 확장자 예외 또한 메일 인증서 삭제 이후에 발생하는 예외이다.

 

 

예외 발생으로 롤백될 것 같았지만 여전히 DELETE 쿼리는 날라간다...

 

 

 

문제 이유

기본 정책으로 RuntimeException과 그 서브 클래스에 대해 롤백이 진행된다.

 

Checked Exception에 대해서는 트랜잭션이 동작하지 않는다.

 

문제의 원인은 파일 관련 예외들을 내가 발생하고 예외 처리를 진행했기에 Checked Exception인 것이다.

 

그럼 Checked Exception은 어떻게 롤백 시킬까?

 

@Transactional의 rollbackOn 속성을 사용하자.

@Transactional(rollbackOn = {FileException.class})
public MemberResponse addMember(SignUpMember signUpMember, MultipartFile memberImg) throws DuplicateException, IOException, MailException, FileException
{ ... }

발생한 예외 클래스를 rollbackOn에 등록해주면 된다.