@Transactional 의 충돌 해결방법

박성현·2025년 9월 10일

개발중 학습

목록 보기
26/44

트랜잭션 겹칠 때 생기는 문제 & 해결

최근에 트랜잭션 적용하다가 문제 현상이 보여서 정리해보려고 한다.


1. 상황

@Service
public class ServiceA {
    @Transactional
    public void saveMain() {
        saveData(); // 메인 저장
        serviceB.saveLog(); // 로그 저장
    }
}

@Service
public class ServiceB {
    @Transactional
    public void saveLog() {
        throw new RuntimeException("로그 저장 실패");
    }
}
  • 의도: 주문 저장 + 로그 저장
  • 문제: 로그 저장에서 에러 나면 주문 저장까지 rollback

2. 왜 그럴까?

  • @Transactional 기본 전파 옵션이 REQUIRED라서, 이미 트랜잭션이 있으면 그냥 이어서 실행함
  • saveMain() 트랜잭션 안에 saveLog()도 같이 묶인 상태
  • 결과적으로 로그 실패 → 전체 rollback

3. 해결

로그는 실패해도 메인 트랜잭션에 영향 없도록 독립 트랜잭션으로 만들면 됨.

@Service
public class ServiceB {
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void saveLog() {
        logRepository.save(new LogEntity(...));
    }
}
  • REQUIRES_NEW → 항상 새 트랜잭션 시작, 기존 트랜잭션은 잠시 보류
  • 로그 실패해도 메인 저장은 그대로 commit 됨

4. 적용 예제

@Service
public class ServiceA {
    @Transactional
    public void saveMain() {
        saveData(); // 주문 저장

        try {
            serviceB.saveLog(); // 로그 저장
        } catch (Exception e) {
            // 실패해도 메인 트랜잭션은 유지
            System.out.println("로그 실패, 주문 저장은 그대로");
        }
    }
}

5. 핵심 정리

  1. 기본 REQUIRED는 기존 트랜잭션에 합류 → 한쪽 실패하면 전체 rollback
  2. 별도 처리해야 하는 작업은 REQUIRES_NEW
  3. 트랜잭션 범위와 전파 설정은 미리 설계 필요

profile
개발기록장

0개의 댓글