BE/Spring

[Spring] @Transactional 어노테이션 역할

콩다영 2024. 4. 26.
728x90

 

Transactional 어노테이션의 역할

Transactional 어노테이션은 데이터베이스 트랜잭션을 관리하는 데 사용됩니다.

트랜잭션은 여러 개의 데이터베이스 작업을 원자적인 단위로 묶어주는 기을 제공하여 데이터 일관성과 안전성을 보장합니다. Transactional 어노테이션을 사용하면 트랜잭션의 시작, 종료, 롤백 등을 자동으로 처리할 수 있습니다.

 

 

트랜잭션 경계 설정

: Transactional 어노테이션이 적용된 메서드나 클래스의 실행을 트랜잭션으로 감싸기 때문에

해당 메서드나 클래스의 실행트랜잭션의 시작과 종료를 정의합니다.

이는 데이터베이스 작업이 완전하게 실행되거나 아예 실행되지 않도록 보장합니다.

 

 

롤백 처리

: 메서드 실행 중 예외가 발생하면 자동으로 롤백되어 이전 상태로 복원됩니다.

이는 데이터베이스 작업 중에 오류가 발생했을 때 데이터의 무결성을 보존하기 위해 중요한 역할을 합니다.

 

 

 

 

▼ 적용 방법

  • 메서드 레벨 적용 : '@Transactional' 어노테이션을 메서드에 직접 적용하여 해당 메서드의 실행을 트랜잭션으로 관리합니다.
  • 클래스 레벨 적용 : 클래스 전체에  '@Transactional' 어노테이션을 적용하여 클래스 내 모든 메서드에 대해 트랜잭션을 설정할 수 있습니다.
  • 트랜잭션 매니저 설정 : Transactional 어노테이션을 사용하기 위해서는 적절한 트랜잭션 매니저가 설정되어 있어야 합니다.

 주의 사항

  • 트랜잭션 범위 : 트랜잭션의 범위를 과도하게 확장하면 성능 문제가 발생할 수 있습니다.
  • 중첩 트랜잭션 : 중첩된 트랜잭션은 부가적인 오버헤드를 초래할 수 있으므로 주의해야 합니다.

 


▼ 속성 설정

 

▶ Isolation 레벨 

트랜잭션 격리 수준을 지정합니다.

격리 수준은 여러 트랜잭션이 동시에 실행될 때 발생할 수 있는 문제를 제어하는 데 사용됩니다.

 

1. DEFAULT : 기본 격리 수준을 사용. 데이터베이스의 기본 격리 수준이 적용.

2. READ_UNCOMMITTED : 커밋되지 않은 다른 트랜잭션의 변경 사항을 읽을 수 있다.

3. READ_COMMITTED : 다른 트랜잭션이 커밋한 변경 사항만 읽을 수 있다.

4. REPEATABLE_READ : 같은 쿼리를 반복 실행해도 결과가 일관성 있게 유지.

5. SERIALIZABLE : 동시에 여러 트랜잭션이 실행되지 않도록 모든 트랜잭션을 순차적으로 실행.

 

[ 예시 ]

@Transactional(isolation = Isolation.READ_COMMITTED)
public void updateUserEmail(Long userId, String newEmail) {
    // 메서드 내용
}

 

 

 

▶ Propagation 설정

메서드가 이미 실행 중인 트랜잭션을 참여할지, 새로운 트랜잭션을 시작할지를 결정합니다.

 

1. REQUIRED : 현재 실행 중인 트랜잭션이 있는 경우 해당 트랜잭션에 참여하고, 그렇지 않은 경우 새로운 트랜잭션을 시작합니다.
2. REQUIRES_NEW : 항상 새로운 트랜잭션을 시작합니다.
3. MANDATORY : 현재 실행 중인 트랜잭션이 없는 경우 예외가 발생합니다.
4. NESTED : 현재 실행 중인 트랜잭션 내에서 중첩된 트랜잭션을 시작합니다.

    외부 트랜잭션이 롤백되면 내부 트랜잭션도 롤백됩니다.
5. SUPPORTS : 현재 실행 중인 트랜잭션이 있는 경우 해당 트랜잭션에 참여하고,

    그렇지 않은 경우 트랜잭션 없이 실행합니다.
6. NOT_SUPPORTED : 현재 실행 중인 트랜잭션이 있는 경우 해당 트랜잭션을 일시 중지시키고,

   메서드를 트랜잭션 없이 실행합니다.

 

[ 예시 ]

@Transactional(propagation = Propagation.REQUIRES_NEW)
public void updateUserEmail(Long userId, String newEmail) {
    // 메서드 내용
}

 

 

 

▶ 롤백 규칙

어떤 종류의 예외가 발생했을 때 롤백이 수행될지를 설정합니다. 롤백할 예외의 클래스를 명시할 수 있습니다.

@Transactional(rollbackFor = {SQLException.class, MyCustomException.class})
public void updateUserEmail(Long userId, String newEmail) throws MyCustomException {
    // 메서드 내용
}

 

 

 

 

≫ 실제 예시

- Spring Framework : Spring에서 Transactional 어노테이션은 데이터베이스 트랜잭션을 관리하기 위해 널리 사용됩니다.

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class UserService {

    @Autowired
    private UserRepository userRepository;

    @Transactional
    public void createUser(String username, String email) {
        User user = new User(username, email);
        userRepository.save(user);
    }

    @Transactional(rollbackFor = Exception.class)
    public void updateUserEmail(Long userId, String newEmail) throws Exception {
        User user = userRepository.findById(userId).orElseThrow(() -> new Exception("User not found"));
        user.setEmail(newEmail);
        // Some business logic here
        if (!isValidEmail(newEmail)) {
            throw new Exception("Invalid email format");
        }
        userRepository.save(user);
    }

    private boolean isValidEmail(String email) {
        // Validation logic here
        return email.contains("@");
    }
}

위 코드에서는 UserService 클래스 내에 두 개의 메서드가 있습니다.

 

 

1. createUser

: 새로운 사용자를 생성하는 메서드입니다. '@Transactional' 어노테이션이 적용되어 있어,

메서드가 실행될 때 트랜잭션을 시작하고, 메서드 실행이 완료되면 트랜잭션을 커밋합니다.

따라서 'createUser' 메서드 내의 모든 작업은 하나의 트랜잭션 내에서 실행됩니다.

 

 

2. updateUserEmail

: 사용자의 이메일 주소를 업데이트하는 메서드.

'@Transactional(rollbackFor = Exception.class)' 어노테이션이 적용되어 있어, 예외가 발생할 경우에만 롤백됩니다.

이 메서드에서는 사용자를 조회하고 이메일을 업데이트하는 작업을 수행하며, 중간에 예외가 발생하면 롤백됩니다.

 

 

 

 

 

 이런 식으로 속성을 설정하여 Transactional 어노테이션을 더욱 세밀하게 제어할 수 있습니다.

 

 

728x90
반응형

'BE > Spring' 카테고리의 다른 글

[Spring] Spring MVC 구조 간단하게 이해하기  (0) 2020.06.30

댓글