inblog logo
|
sxias
    트러블슈팅

    [트러블슈팅] 11. Transaction 오류

    문정준's avatar
    문정준
    Mar 25, 2025
    [트러블슈팅] 11. Transaction 오류
    Contents
    1. Transaction의 범위Solution

    1. Transaction의 범위

    • 필터링 또는 값 체크를 위해 Insert, Update, Delete 등의 DML 작업 처리 전에 select로 값을 참조한 후 삽입을 진행할 경우, 정상적으로 작동할 줄 알았는데 오류가 발생하는 경우가 많음
    notion image
    @Transactional public void 계좌생성(AccountRequest.SaveDTO saveDTO, int userId) { // 1. 계좌번호 확인 Account account = accountRepository.findByNumber(saveDTO.getNumber()); // 2. 있으면 exception (계좌번호는 PK : Unique) if (account != null) throw new RuntimeException("이미 계좌가 존재합니다."); // 3. 없으면 생성 accountRepository.save(saveDTO.getNumber(),saveDTO.getPassword(),saveDTO.getBalance(), userId); }
    • 이는 트랜잭션의 내부 구조에 의해 발생하는 오류로, 필터링을 따로 수행해주어야 함
    [Spring Boot] @Transactional 내부에서 발생한 Exception과 rollback (+ 고찰 추가)
    📕 목차 1. @Transactional 내부에서 Exception 발생 2. 로그 추적 3. 코드 추적 4. 문제의 근원 5. 결론 1. @Transactional 내부에서 Exception 발생 📌 발단 @Slf4j @Helper @RequiredArgsConstructor public class UserSyncHelper { private final UserService userService; /** * 일반 회원가입 시 이미 가입된 회원인지 확인 * * @param phone String : 전화번호 * @return Pair : 이미 가입된 회원인지 여부 (TRUE: 가입되지 않은 회원, FALSE: 가입된 회원), 가입된 회원인 경우 회원 ID 반환 * @throws UserErrorExcep..
    [Spring Boot] @Transactional 내부에서 발생한 Exception과 rollback (+ 고찰 추가)
    https://jaeseo0519.tistory.com/369
    [Spring Boot] @Transactional 내부에서 발생한 Exception과 rollback (+ 고찰 추가)
    응? 이게 왜 롤백되는거지? | 우아한형제들 기술블로그
    이 글은 얼마 전 에러로그 하나에 대한 호기심과 의문으로 시작해서 스프링의 트랜잭션 내에서 예외가 어떻게 처리되는지를 이해하기 위해 삽질을 해본 경험을 토대로 쓰여졌습니다. 스프링의 트랜잭션의 세부적인 동작방식을 살펴보기 때문에 코드가 많고 설명이 조금 긴 편입니다. 상황재현과 테스트를 위해 작성한 코드는 github에 있습니다. 테스트에 사용한 버전은 SpringBoot 2.1.2, MySQL 5.7입니다. 때는 지난 12월의 어느날 beta서버에서 에러로그가
    응? 이게 왜 롤백되는거지? | 우아한형제들 기술블로그
    https://techblog.woowahan.com/2606/
    응? 이게 왜 롤백되는거지? | 우아한형제들 기술블로그

    Solution

    • 본 문제는 필터링 등의 비검사 예외와 Runtime 예외의 역할의 구분이 필요함
      • 비검사 예외는 오히려 그 전에서 잡거나 잡지 말아야 함 (관심사 분리 : 책임 분리)
      • 정말 복구가 어려운 Runtime 예외가 발생하였을 때에만 Transaction을 사용
    • 이미 이벤트 처리를 통한 break로 Transaction의 기능이 가능하므로 Transactional 어노테이션을 제거하거나, 또는 비검사 예외 처리를 상위 Controller에서 수행해야 함
    • 필자는 오류 처리를 상위 Controller에서 처리하기 위해 DML만을 Service층에 남김
    @Transactional public void 계좌생성(AccountRequest.SaveDTO saveDTO, int userId) { // 공백 처리 // // 1. 계좌번호 확인 // Account account = accountRepository.findByNumber(saveDTO.getNumber()); // // 2. 있으면 exception (계좌번호는 PK : Unique) // if (account != null) throw new RuntimeException("이미 계좌가 존재합니다."); // // 3. 없으면 생성 accountRepository.save(saveDTO.getNumber(),saveDTO.getPassword(),saveDTO.getBalance(), userId); }
     
    Share article
    Contents
    1. Transaction의 범위Solution

    Sxias ㆍ a32176740@gmail.com

    RSS·Powered by Inblog