🔥스파르타 TIL (Spring)

Transaction 이란?

승승장규 2025. 3. 14. 23:03

데이터베이스 데이터들의 무결성과 정합성을 유지하기 위한 것으로 데이터를 안전하게 관리하기 위해서 생겨난 개념이다.

여러 작업을 하나의 작업으로 묶어서 처리하는 것으로 Commit, Rollback을 알아보자.

 

트랜잭션의 4가지 특징 ACID 

  • Atomicity (원자성) : 트랜잭션은 모두 실행되거나, 전혀 실행되지 않아야 한다. ex) 송금 과정에서 계좌에 돈이 빠져나갔지만 상대 계좌로 입금이 안되면 안 된다.
  • Consistency (일관성) : 트랜잭션이 완료되면 데이터는 일관된 상태를 유지해야 한다. ex) 은행 계좌에서 100만 원이 빠져나가면, 전체 은행 시스테의 총금액은 변하면 안 된다.
  • Isolation (격리성) : 여러 트랜잭션이 동시에 실행되더라도 서로 영향을 주면 안 된다. ex) 두 명이 동시에 같은 상품을 구매할 때, 재고 초과로 인해 한 명은 실패해야 한다.
  • Durability (지속성) : 트랜잭션이 성공적으로 완료되면 영구적으로 저장되어야 한다. ex) 주문이 완료되면 전원이 꺼져도 주문 내역이 남아 있어야 한다.
-- 트랜잭션 시작
START TRANSACTION;

-- A 계좌에서 100만 원 차감
UPDATE account SET balance = balance - 1000000 WHERE user_id = 'A';

-- B 계좌에 100만 원 추가
UPDATE account SET balance = balance + 1000000 WHERE user_id = 'B';

-- 모든 작업이 성공하면 커밋
COMMIT;

======================================================================

START TRANSACTION;

UPDATE account SET balance = balance - 1000000 WHERE user_id = 'A';

-- 여기서 B 계좌 업데이트에 문제가 생긴다면?
IF ERROR THEN
    ROLLBACK; -- 모든 작업 취소
ELSE
    COMMIT;  -- 성공하면 적용
END IF;

 

이러한 Transaction 환경을 @Transactional 어노테이션으로 쉽게 관리할 수 있다. 

IntelliJ에서 Shift를 두 번 누르고 SimpleJpaRepository를 검색해서 클래스를 확인해 보면 전체 클래스에 @Transactional (readOnly = true) 이 걸려있는 것을 볼 수 있다. 

 

@Transactional(readOnly = true) 적용된 메서드는 트랜잭션을 읽기 전용으로 설정한다는 뜻이다. 이를 통해 JPA에서는 변경 감지를 위한 스냅숏 저장을 생략하여 성능을 최적화할 수 있지만, 해당 설정은 데이터를 조회하는 데 최적화된 것이므로, 데이터 삽입, 수정, 삭제 작업을 수행하지 않는 것이 좋다.

 

밑으로 내려보면

 

자주 사용하는 save() 메서드를 확인할 수 있는데 @Transactional 어노테이션이 걸려있는 메서드가 호출이 되면 해당 메서드 내에 수행되는 모든 데이터베이스 연산들을 하나의 트랜잭션으로 묶는다. 실제로는 @Transactional(readOnly = false)가 default 상태이므로 기존의 @Transactional(readOnly = true) 옵션을 덮어씌운 것이다.

 

우리가 Service에서 Repository를 호출할 때 Repository에 있는 메서드 까지 트랜잭션 환경을 쭉 이어주는데,

Spring에서는 트랜잭션을 제어할 수 있도록 트랜잭션 전파 기능을 제공하고 있다.

 

@Transactional에 propagation이 default값으로 REQUIRED 옵션이 걸려있기 때문에 부모 메서드에 @Transactional이 존재하면 자식 메서드의 @Transcationl 부모 메서드에 합류하게 된다.