본문 바로가기
Mybatis/MyBatis + Spring 연동

트랜잭션 처리 및 예외 관리

by DEVLIB 2025. 4. 17.
728x90

1. MyBatis + Spring Boot 트랜잭션 구조

MyBatis는 내부적으로 JDBC 기반이기 때문에, 트랜잭션은 Spring의 트랜잭션 매니저에 의해 처리됩니다. MyBatis Starter를 사용하면 아래 구성은 자동으로 설정돼요.

spring:
  datasource:
    ...
  transaction:
    default-timeout: 30s

2. 트랜잭션 처리 방법

A. 선언적 트랜잭션 (@Transactional)

가장 많이 사용되는 방식입니다. Service 계층에서 트랜잭션 범위를 지정할 수 있어요.

@Service
@RequiredArgsConstructor
public class UserService {

    private final UserMapper userMapper;

    @Transactional
    public void registerUser(User user) {
        userMapper.insertUser(user);
        userMapper.insertLog("회원가입 완료"); // 둘 다 성공해야 커밋됨
    }
}
  • 트랜잭션이 실패하면 전체 롤백
  • @Transactional(readOnly = true) → 조회 성능 최적화

B. 프로그래밍 방식

직접 TransactionTemplate을 사용해서 관리할 수 있어요.

@Transactional
public void saveAll() {
    try {
        ...
    } catch (Exception e) {
        throw new CustomDatabaseException("DB 오류 발생", e);
    }
}

3. 예외 처리 전략

A. MyBatis 예외는 Spring이 자동 변환

MyBatis 예외는 자동으로 Spring의 DataAccessException 계열로 변환되므로, 다음과 같이 공통 예외 처리가 가능해요:

@ExceptionHandler(DataAccessException.class)
public ResponseEntity<?> handleDbError(Exception e) {
    return ResponseEntity.status(500).body("DB 처리 중 오류가 발생했습니다.");
}

Spring Boot + MyBatis Starter는 MyBatisExceptionTranslator가 자동 등록돼요.


B. 커스텀 예외 처리

public class DuplicateUserException extends RuntimeException {
    public DuplicateUserException(String message) {
        super(message);
    }
}
 
if (userMapper.existsByEmail(user.getEmail())) {
    throw new DuplicateUserException("이미 등록된 이메일입니다.");
}

커스텀 예외는 REST API 응답과 통합할 때 특히 유용합니다.


4. 트랜잭션 전파 옵션

전파 방식 설명
REQUIRED (기본값) 이미 트랜잭션이 있으면 참여, 없으면 새로 생성
REQUIRES_NEW 무조건 새로운 트랜잭션 시작
NESTED 중첩 트랜잭션 지원 (savepoint 기반)

마무리 요약

항목 방법
트랜잭션 설정 @Transactional (Service 계층)
예외 처리 Spring의 DataAccessException 자동 변환
커스텀 예외 throw new MyException(...) 방식
롤백 처리 예외 발생 시 자동 롤백, @Transactional 이용
공통 핸들링 @ControllerAdvice에서 처리 가능

실전 예제 추천

  • 회원 가입 트랜잭션 (회원 등록 + 로그 등록)
  • 주문 처리 실패 시 전체 롤백
  • 중복 이메일 예외 → 사용자 친화적인 메시지 응답
LIST