JPA에서 트랜잭션 처리 및 데이터베이스 격리 수준

2024. 7. 19. 15:55·개발 노트/Spring
목차
  1. 트랜잭션이란?
  2. JPA와 트랜잭션 처리
  3. @Transactional 어노테이션
  4. @Transactional에서 사용되는 어노테이션
  5. 트랜잭션 전파
  6. 트랜잭션 격리 수준
  7. 격리 수준의 선택
  8. 트랜잭션 롤백
  9. 트랜잭션 처리와 성능 최적화
  10. 트랜잭션 범위 최소화
  11. 캐싱 사용
  12. 마무리
  1.  

트랜잭션이란?

트랜잭션(Transaction)은 데이터베이스의 상태를 변화시키기 위해 수행하는 일련의 연산들을 말한다. 트랜잭션은 데이터의 무결성과 일관성을 보장하기 위해 ACID 속성을 따른다.

  • 원자성(Atomicity): 트랜잭션 내의 모든 작업이 완벽하게 수행되거나 전혀 수행되지 않아야 한다.
  • 일관성(Consistency): 트랜잭션이 성공적으로 완료되면 데이터베이스는 일관성 있는 상태를 유지해야 한다.
  • 격리성(Isolation): 트랜잭션이 실행되는 동안 다른 트랜잭션의 영향을 받아서는 안 된다.
  • 지속성(Durability): 트랜잭션이 완료되면 그 결과는 영구적으로 반영되어야 한다.

 

JPA와 트랜잭션 처리

JPA에서 트랜잭션 관리는 주로 EntityManager를 통해 이루어진다. 하지만 Spring Data JPA를 사용하면 더 간단하게 트랜잭션을 관리할 수 있다. Spring에서는 @Transactional 어노테이션을 사용하여 트랜잭션을 선언적으로 관리할 수 있다.

@Transactional 어노테이션

@Transactional은 트랜잭션 범위를 설정하고 관리하는 데 사용되는 어노테이션이다. 메소드나 클래스 수준에서 적용할 수 있다.

@Service
public class UserService {

    private final UserRepository userRepository;

    @Autowired
    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    @Transactional
    public void updateUser(Long id, String newUsername) {
        User user = userRepository.findById(id).orElseThrow(() -> new RuntimeException("User not found"));
        user.setUsername(newUsername);
        userRepository.save(user);
    }
}
  • @Transactional: 메소드나 클래스에 적용하여 해당 범위 내에서 트랜잭션을 관리한다.

@Transactional에서 사용되는 어노테이션

  1. @Transactional(propagation = Propagation.REQUIRED): 기본 전파 수준으로, 현재 트랜잭션이 존재하면 해당 트랜잭션을 사용하고, 없으면 새로운 트랜잭션을 생성한다.
@Transactional(propagation = Propagation.REQUIRED)
public void saveNewUser(User user) {
    userRepository.save(user);
}
  1. @Transactional(readOnly = true): 읽기 전용 트랜잭션을 설정하여 성능을 최적화한다.
@Transactional(readOnly = true)
public User getUser(Long id) {
    return userRepository.findById(id).orElse(null);
}
  1. @Transactional(rollbackFor = Exception.class): 특정 예외가 발생했을 때 트랜잭션을 롤백한다.
@Transactional(rollbackFor = Exception.class)
public void riskyOperation() throws Exception {
    // 예외가 발생하면 트랜잭션 롤백
}
  1. @Transactional(isolation = Isolation.SERIALIZABLE): 트랜잭션의 격리 수준을 설정한다.
@Transactional(isolation = Isolation.SERIALIZABLE)
public void performCriticalOperation() {
    // 중요한 데이터베이스 작업 수행
}

트랜잭션 전파

트랜잭션 전파는 트랜잭션이 다른 트랜잭션 메소드를 호출할 때 어떻게 동작할지를 정의한다. Spring은 다음과 같은 전파 옵션을 제공한다:

  • REQUIRED (기본값): 현재 트랜잭션이 존재하면 해당 트랜잭션을 사용하고, 없으면 새로운 트랜잭션을 생성한다.
  • REQUIRES_NEW: 항상 새로운 트랜잭션을 생성한다. 기존 트랜잭션은 일시 중단된다.
  • MANDATORY: 현재 트랜잭션이 존재해야 한다. 존재하지 않으면 예외를 발생시킨다.
  • SUPPORTS: 현재 트랜잭션이 존재하면 해당 트랜잭션을 사용하고, 없으면 트랜잭션 없이 실행한다.
  • NOT_SUPPORTED: 트랜잭션 없이 실행한다. 기존 트랜잭션은 일시 중단된다.
  • NEVER: 트랜잭션이 존재하면 예외를 발생시킨다.
  • NESTED: 중첩된 트랜잭션을 생성한다.
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void saveNewUser(User user) {
    userRepository.save(user);
}

 

트랜잭션 격리 수준

데이터베이스 트랜잭션 격리 수준은 트랜잭션이 다른 트랜잭션에 얼마나 영향을 받는지를 정의한다. 격리 수준은 다음과 같다:

  • READ UNCOMMITTED: 다른 트랜잭션이 커밋되지 않은 데이터를 읽을 수 있다.
  • READ COMMITTED: 다른 트랜잭션이 커밋한 데이터만 읽을 수 있다.
  • REPEATABLE READ: 트랜잭션이 시작된 이후에 커밋된 데이터만 읽을 수 있다.
  • SERIALIZABLE: 가장 높은 격리 수준으로, 트랜잭션 간에 완전한 격리를 보장한다.
@Transactional(isolation = Isolation.SERIALIZABLE)
public void performCriticalOperation() {
    // 중요한 데이터베이스 작업 수행
}

격리 수준의 선택

  • READ UNCOMMITTED: 성능이 중요하고 일관성이 크게 중요하지 않은 경우 사용.
  • READ COMMITTED: 대부분의 애플리케이션에서 기본으로 사용.
  • REPEATABLE READ: 일관성이 중요한 애플리케이션에서 사용.
  • SERIALIZABLE: 데이터 일관성이 매우 중요한 경우 사용하지만, 성능 저하가 발생할 수 있다.

 

트랜잭션 롤백

@Transactional 어노테이션을 사용하면 특정 예외가 발생했을 때 트랜잭션을 롤백할 수 있다. rollbackFor 속성을 사용하여 롤백할 예외를 지정할 수 있다.

@Transactional(rollbackFor = Exception.class)
public void riskyOperation() throws Exception {
    // 예외가 발생하면 트랜잭션 롤백
}

 

트랜잭션 처리와 성능 최적화

트랜잭션 처리는 데이터베이스 성능에 영향을 미칠 수 있다. 트랜잭션 범위를 최소화하고, 필요한 경우 트랜잭션 격리 수준을 낮추어 성능을 최적화할 수 있다.

트랜잭션 범위 최소화

트랜잭션의 범위를 최소화하여 데이터베이스 잠금 시간을 줄이고 성능을 향상시킬 수 있다. 예를 들어, 필요한 최소한의 코드 블록만 트랜잭션 내에서 실행하도록 한다.

@Transactional
public void updateMultipleUsers(List<User> users) {
    for (User user : users) {
        userRepository.save(user);
    }
}

캐싱 사용

캐싱을 사용하여 동일한 데이터에 대한 반복적인 데이터베이스 접근을 줄일 수 있다. Spring과 Hibernate는 1차 캐시와 2차 캐시를 지원한다.

 

마무리

JPA와 Spring Data JPA를 사용하면 트랜잭션을 쉽게 관리할 수 있다. 트랜잭션 전파, 격리 수준, 롤백 설정 등을 통해 데이터의 일관성과 무결성을 유지하면서 성능을 최적화할 수 있고, 트랜잭션 관리는 데이터베이스와의 상호작용에서 매우 중요한 부분이다. 트랜잭션 관리 기능을 잘 이해하고 활용하는 것이 정말 중요할 것 같다.

'개발 노트 > Spring' 카테고리의 다른 글

JPA에서 N+1 문제  (2) 2024.07.19
Spring Data JPA 이해하기: 주요 구성 요소와 어노테이션  (0) 2024.07.19
JPA 이해하기: 동작 원리와 핵심 구성 요소  (0) 2024.07.19
  1. 트랜잭션이란?
  2. JPA와 트랜잭션 처리
  3. @Transactional 어노테이션
  4. @Transactional에서 사용되는 어노테이션
  5. 트랜잭션 전파
  6. 트랜잭션 격리 수준
  7. 격리 수준의 선택
  8. 트랜잭션 롤백
  9. 트랜잭션 처리와 성능 최적화
  10. 트랜잭션 범위 최소화
  11. 캐싱 사용
  12. 마무리
'개발 노트/Spring' 카테고리의 다른 글
  • JPA에서 N+1 문제
  • Spring Data JPA 이해하기: 주요 구성 요소와 어노테이션
  • JPA 이해하기: 동작 원리와 핵심 구성 요소
악덕
악덕
우당탕탕 개발 블로그
  • 악덕
    버그와 함께 춤을
    악덕
  • 전체
    오늘
    어제
    • 전체 (26)
      • TIL (2)
      • 개발 노트 (19)
        • Java (5)
        • JavaScript (1)
        • Spring (4)
        • Linux (1)
        • DevOps (1)
        • etc. (7)
      • 문제 풀이 (0)
      • 삽질 로그 (3)
      • 기타 (2)
  • 링크

    • GitHub
    • Project.zip
    • 밀로(millo)
  • 태그

    프로그래밍언어
    mysql
    ssl
    JPA
    DevOps
    solid 원칙
    웹개발
    자료형
    springboot
    java persistence api
    gdg
    Til
    Spring Data JPA
    프로그래밍
    OOP
    컨테이너
    java
    Docker
    객체지향 프로그래밍
    자바기초
  • hELLO· Designed By정상우.v4.10.3
악덕
JPA에서 트랜잭션 처리 및 데이터베이스 격리 수준
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.