OPEN HYPER STEP
← 목록으로 (Java+Spring)
JAVA · 74 / 99
java
CHAPTER 74 / 99
읽기 약 2
FUNCTION

트랜잭션 관리


핵심 개념

@Transactional 동작 원리·전파·격리 수준·롤백 규칙 — 결제 처리의 트랜잭션 설계.

본문

@Transactional 기본

JAVA📋 코드 (25줄)
@Service
@RequiredArgsConstructor
public class PaymentService {
    private final PaymentRepository paymentRepo;
    private final OrderRepository orderRepo;
    private final InventoryRepository inventoryRepo;

    @Transactional
    public Payment processPayment(Long orderId, BigDecimal amount) {
        // 1. 주문 조회
        Order order = orderRepo.findById(orderId)
            .orElseThrow(OrderNotFoundException::new);

        // 2. 재고 차감
        inventoryRepo.decrementStock(order.getProductId(), order.getQuantity());

        // 3. 결제 저장
        Payment payment = Payment.create(order, amount);
        paymentRepo.save(payment);

        // 위 3 단계 모두 같은 트랜잭션
        // 어느 하나 실패하면 모두 롤백
        return payment;
    }
}

전파 (Propagation)

JAVA📋 코드 (31줄)
public enum Propagation {
    REQUIRED,        // 기본 — 트랜잭션 있으면 참여, 없으면 새로 시작
    REQUIRES_NEW,    // 항상 새 트랜잭션 (현재 일시 정지)
    SUPPORTS,        // 있으면 참여, 없어도 OK
    NOT_SUPPORTED,   // 트랜잭션 없이 실행
    MANDATORY,       // 반드시 트랜잭션 안에서 호출
    NEVER,           // 트랜잭션 있으면 예외
    NESTED,          // 중첩 트랜잭션 (savepoint)
}


@Service
public class OrderService {

    @Transactional
    public void placeOrder(Order order) {
        orderRepo.save(order);
        sendNotification(order);  // 이 안에서 별도 트랜잭션
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void sendNotification(Order order) {
        // 부모 트랜잭션과 무관하게 독립 실행
        // 알림 실패해도 주문은 저장
        try {
            notificationRepo.save(...);
        } catch (Exception e) {
            // 알림 실패 로깅만
        }
    }
}

격리 수준 (Isolation)

JAVA📋 코드 (25줄)
public enum Isolation {
    DEFAULT,             // DB 기본값 (PostgreSQL: READ_COMMITTED)
    READ_UNCOMMITTED,    // Dirty read 가능 (거의 안 씀)
    READ_COMMITTED,      // Dirty read 차단
    REPEATABLE_READ,     // Phantom read 가능
    SERIALIZABLE,        // 모든 동시성 문제 차단 (가장 느림)
}


@Service
public class TransferService {

    @Transactional(isolation = Isolation.SERIALIZABLE)
    public void transfer(Long fromId, Long toId, BigDecimal amount) {
        // 동시 송금 시 일관성 보장
        Account from = accountRepo.findByIdForUpdate(fromId);
        Account to = accountRepo.findByIdForUpdate(toId);

        from.withdraw(amount);
        to.deposit(amount);

        accountRepo.save(from);
        accountRepo.save(to);
    }
}

롤백 규칙

JAVA📋 코드 (29줄)
@Service
public class OrderService {

    // 기본 — Unchecked 예외만 롤백 (RuntimeException, Error)
    @Transactional
    public void placeOrder(Order order) {
        // RuntimeException 발생 시 롤백
        // IOException(checked) 발생 시 롤백 X
    }


    // 명시적 — Checked 예외도 롤백
    @Transactional(rollbackFor = {Exception.class})
    public void placeOrderStrict(Order order) {
        // 모든 예외에서 롤백
    }


    // 특정 예외는 롤백 안 함
    @Transactional(noRollbackFor = {NotificationFailedException.class})
    public void placeOrderNotify(Order order) {
        orderRepo.save(order);
        try {
            sendNotification(order);  // 알림 실패해도 주문 유지
        } catch (NotificationFailedException e) {
            // 무시
        }
    }
}

readOnly 최적화

JAVA📋 코드 (27줄)
@Service
@Transactional(readOnly = true)  // 클래스 레벨 — 모든 메서드 readOnly
public class UserQueryService {
    private final UserRepository userRepo;

    public User findById(Long id) {
        return userRepo.findById(id)
            .orElseThrow(UserNotFoundException::new);
    }

    public List<User> findAll() {
        return userRepo.findAll();
    }

    @Transactional  // 메서드 레벨 — readOnly 오버라이드
    public User updateName(Long id, String name) {
        User user = findById(id);
        user.setName(name);
        return user;
    }
}


// readOnly의 효과:
// - JPA dirty checking 생략 (더 빠름)
// - 일부 DB는 읽기 전용 트랜잭션 최적화
// - 의도 명확화 (코드 가독성)

다음 챕터

CH.6 "예외 처리" — @ControllerAdvice 글로벌 처리.


AI 프롬프트
🤖 AI에게 잘 물어보는 법 — 모델·전략별 프롬프트
Claude

무료: Sonnet 4.6 / Pro $20/mo: Opus 4.6

내 Spring 코드의 @Transactional 부분을 분석해서
롤백·격리 수준 적정성와 개선 우선순위를 알려줘.
ChatGPT

무료: GPT-5.5 / Plus $20/mo: GPT-5.5 Pro

@Transactional vs 다른 패턴 비교를
실전 사례 5개로 보여주고 Propagation 옵션 비교를 알려줘.
Gemini

무료: 2.5 Flash / Pro $19.99/mo: 3.1 Pro

내 코드베이스 전체를 분석해서
@Transactional 관련 트랜잭션 누락·과도 위치를 보고해줘.
Grok

무료: Grok 4.1 / SuperGrok $30/mo

2026년 한국 기업의 @Transactional 채택률과
한국 SI/SaaS 트랜잭션 패턴를 솔직히 알려줘.

⭐ 이것만 기억하세요
트랜잭션 관리 이 3가지만 확실히 잡으세요
1.@Transactional은 AOP 프록시 — 외부 호출에서만 동작 (같은 클래스 내부 호출 시 무효)
2.Propagation.REQUIRES_NEW로 독립 트랜잭션, readOnly로 조회 최적화
3.다음 챕터 CH.6에서 예외 처리 — 글로벌 에러 응답 표준화


공유하기
진행도 74 / 99