본문 바로가기

Spring/Spring JPA

[JPA] @Transactional 속성(attribute)

1. Isolation

isolation은 데이터베이스의 트랜잭션 격리 수준을 설정하는 데 사용됩니다. 스프링에서 제공하는 Isolation 값은 java.sql.Connection의 TRANSACTION_* 상수와 매핑됩니다.

격리 수준 종류

Isolation Level 설명 문제 방지 여부
Isolation.DEFAULT 데이터베이스의 기본 격리 수준을 따릅니다. (보통 READ_COMMITTED) 데이터베이스 기본 설정에 따름
Isolation.READ_UNCOMMITTED 가장 낮은 격리 수준으로, 다른 트랜잭션의 커밋되지 않은 변경 사항을 읽을 수 있습니다. Dirty Read 허용
Isolation.READ_COMMITTED 커밋된 데이터만 읽을 수 있습니다. 다른 트랜잭션의 변경 사항이 커밋되기 전까지는 볼 수 없습니다. Dirty Read 방지
Isolation.REPEATABLE_READ 동일 트랜잭션에서 동일한 쿼리를 실행하면 항상 같은 결과를 보장합니다. Dirty Read, Non-repeatable Read 방지
Isolation.SERIALIZABLE 가장 높은 격리 수준으로, 트랜잭션 간 순차적으로 실행되도록 보장합니다. Dirty Read, Non-repeatable Read, Phantom Read 방지

격리 수준별로 방지되는 문제

1. Dirty Read

  • 한 트랜잭션에서 커밋되지 않은 데이터를 다른 트랜잭션이 읽는 상황.
  • READ_COMMITTED 이상에서 방지됩니다.

2. Non-repeatable Read

  • 동일한 쿼리를 두 번 실행했을 때, 다른 트랜잭션의 업데이트로 인해 다른 결과를 읽는 상황.
  • REPEATABLE_READ 이상에서 방지됩니다.

3. Phantom Read

  • 동일한 쿼리를 두 번 실행했을 때, 다른 트랜잭션의 INSERT/DELETE로 인해 결과 행의 수가 달라지는 상황.
  • SERIALIZABLE에서 방지됩니다.
@Transactional(isolation = Isolation.REPEATABLE_READ)
public void someTransactionalMethod() {
    // 트랜잭션 처리 로직
}

 

2. @Transactional의 다른 속성

1) propagation

트랜잭션 전파 행동을 정의합니다. 트랜잭션을 새로 시작하거나 기존 트랜잭션에 참여할지 결정합니다.

Propagation Type 설명
REQUIRED 기본값. 현재 트랜잭션이 존재하면 참여하고, 없으면 새 트랜잭션을 생성합니다.
REQUIRES_NEW 항상 새 트랜잭션을 생성하고, 기존 트랜잭션을 일시 중단합니다.
SUPPORTS 트랜잭션이 존재하면 참여하고, 없으면 트랜잭션 없이 실행합니다.
NOT_SUPPORTED 트랜잭션 없이 실행하며, 기존 트랜잭션을 일시 중단합니다.
MANDATORY 반드시 기존 트랜잭션이 있어야 하며, 없으면 예외를 발생시킵니다.
NEVER 트랜잭션 없이 실행하며, 트랜잭션이 존재하면 예외를 발생시킵니다.
NESTED 중첩 트랜잭션을 생성합니다. (savepoint를 사용하여 롤백 범위를 조정할 수 있음)

2) readOnly

트랜잭션이 읽기 전용임을 선언합니다. 데이터베이스가 최적화하도록 힌트를 제공합니다.

@Transactional(readOnly = true)
public List<User> getUsers() {
    return userRepository.findAll();
}
  • 장점: 읽기 전용 트랜잭션은 변경 작업을 막아 데이터 일관성을 유지하고 성능을 최적화합니다.
  • 주의: readOnly = true 상태에서는 변경 작업(INSERT, UPDATE, DELETE)이 발생하면 예외가 발생할 수 있습니다.

3) timeout

트랜잭션이 몇 초 동안 실행될 수 있는지 제한합니다. 제한 시간이 초과되면 롤백됩니다.

@Transactional(timeout = 5)
public void someTransactionalMethod() {
    // 5초 내에 완료되지 않으면 트랜잭션 롤백
}

4) rollbackFor / noRollbackFor

  • 특정 예외 발생 시 롤백할지 여부를 지정합니다.

롤백 조건 설정

@Transactional(rollbackFor = CustomException.class)
public void someTransactionalMethod() {
    // CustomException 발생 시 롤백
}

롤백하지 않는 조건 설정

@Transactional(noRollbackFor = IllegalArgumentException.class)
public void someTransactionalMethod() {
    // IllegalArgumentException 발생 시 롤백하지 않음
}

5) transactionManager

특정 트랜잭션 관리자를 지정합니다. 주로 복수의 데이터 소스를 사용할 때 유용합니다.

@Transactional(transactionManager = "customTransactionManager")
public void someTransactionalMethod() {
    // 특정 트랜잭션 매니저 사용
}

6) value

@Transactional 애노테이션은 value 속성으로 트랜잭션 설정을 참조할 수도 있습니다.

 

정리

  • isolation은 트랜잭션 격리 수준을 설정하여 데이터 일관성을 보장합니다.
  • 다른 옵션(propagation, readOnly, timeout, rollbackFor 등)을 통해 트랜잭션 동작을 세밀하게 제어할 수 있습니다.
  • 프로젝트에 따라 적절한 설정을 선택하여 성능과 데이터 무결성을 동시에 유지해야 합니다.