트랜잭션(Transaction)

박채은·2023년 1월 1일
0

Spring

목록 보기
19/35

트랜잭션이란?

  • 여러 개의 작업을 하나의 그룹으로 묶어서 처리하는 처리 단위
  • 물리적으로는 여러 작업이지만, 논리적으로는 하나의 작업으로 인식한다.
  • All or Nothing : 전부 성공하든가, 전부 실패하던가
    -> 데이터의 무결성을 보장
  • 트랜잭션은 부가 기능이므로 AOP의 적용 대상이다.

ACID 원칙 - 트랜잭션의 특징

1. 원자성

  • 작업을 더 이상 쪼갤 수 없다는 성질
  • All or Nothing

2. 일관성

  • 에러 없이 성공한 경우, 데이터는 비즈니스 로직에 따라 일관성있게 저장/변경된다는 성질

3. 격리성

  • 여러 트랜잭션이 실행될 때, 각각 독립적으로 실행된다는 성질

ex) 멀티 태스킹 - 우리는 문서를 작성하면서 노래를 듣고 동시에 여러가지 일을 하고 있는 것처럼 보이지만, 프로세스는 독립적인 task들을 번갈아가면서 실행하고 있는 것

4. 지속성

  • 트랜잭션이 완료되면, 그 결과는 지속되어야 한다는 성질

ex) DB가 종료되어도 데이터는 물리적인 저장소에 계속 저장되어 있어야 한다.


커밋/롤백

커밋

  • 트랜잭션의 모든 작업을 최종적으로 데이터베이스에 반영하는 명령어
  • 커밋 명령을 수행하면, 하나의 트랜잭션은 종료된다.
  • 커밋 명령을 수행하지 않으면, 결과는 DB에 반영되지 않는다.

롤백

  • 트랜잭션을 실패했을 때, 트랜잭션 내에서 수행된 모든 작업을 취소하여 트랜잭션 시작 전의 상태로 돌아가는 것

트랜잭션의 종류

  1. 로컬 트랜잭션 - 단일 데이터베이스에 대한 트랜잭션
  2. 분산 트랜잭션 - 서로 다른 데이터소스를 사용하는 한 개 이상의 데이터베이스를 하나의 트랜잭션으로 묶어서 처리하는 것

트랜잭션의 방식

  1. 선언형 트랜잭션 방식
    1-1) 애너테이션 사용
    1-2) AOP 방식 사용

  2. 프로그래밍 코드 베이스 트랜잭션 방식 -> 트랜잭션은 AOP이기 때문에 해당 방식은 적절하지 않다.

트랜잭션 방식은 두 가지가 있지만, 선언형 트랜잭션 방식을 사용해볼 것이다!


Spring에서의 트랜잭션 처리

  • Spring에서 트랜잭션은 기본적으로 PlatformTransactionManager 인터페이스에 의해 관리된다.
    • JPA를 사용하면, PlatformTransactionManager의 구현 클래스인 JpaTransactionManager를 사용한다.
  • Spring Boot를 사용하면, 트랜잭션 관련된 설정은 Spring Boot가 알아서 해준다.

선언형 트랜잭션

1. 애너테이션 사용

  • @Transactional 애너테이션을 트랜잭션이 필요한 영역에 추가한다.

  • 클래스 레벨에 추가하면, 모든 메서드에 트랜잭션이 적용된다.

  • @Transactional의 우선 순위는 "메소드 > 클래스"이다.

    • @Transactional이 클래스와 메소드 모두에 적용된 경우, 메서드 레벨의 @Transactional이 적용된다.
    • 공통적인 트랜잭션 규칙은 클래스 레벨에, 특별한 트랙잭션 규칙은 메서드에 적용하는 것이 좋다.
  • 조회 메서드에는 @Transactional(readOnly = true)를 붙인다.

💡 조회 메서드에 @Transactional(readOnly = true) 로 설정하는 이유
커밋은 하나의 트랜잭션을 종료하는 것이므로@Transactional(readOnly = true)로 설정해도 커밋은 진행된다.
하지만 커밋 내부의 flush는 작동하지 않는다.
@Transactional(readOnly = true)로 설정하면 커밋은 flush 처리를 하지 않고, 스냅샷도 생성하지 않아 불필요한 동작을 줄이게 된다.

* flush : 영속성 컨텍스트의 변경 내용을 데이터베이스에 반영하는 것

조회 메서드에는 readOnly = true 속성을 주어, JPA가 성능 최적화 과정을 거치도록 해야한다.

  • @Transactional을 사용하면, 트랜잭션 종료 시점에 자동으로 commit이 발생한다.
    • 따라서 Repository.save()를 하지 않아도 내부적으로 처리된다.
    • 하지만 애너테이션과 save()를 같이 써도 문제될 것은 없다.

0개의 댓글