사전 준비 | 트랜잭션

Faithful Dev·2025년 2월 28일

스프링 프레임워크

목록 보기
17/20

트랜잭션(Transaction)이란 데이터베이스에서 논리적인 작업 단위를 묶어서 처리하는 개념이다.
즉, 여러 개의 데이터 변경(SQL 문)이 하나의 트랜잭션 안에서 실행되며, 모든 작업이 성공하면 적용(Commit) 되고, 하나라도 실패하면 전체 취소(Rollback) 되는 방식으로 동작한다.


4가지 특징 (ACID 원칙)

트랜잭션은 ACID(Atomicity, Consistency, Isolation, Durability) 원칙을 따라야 한다.

원자성 (Atomicity)

  • "All or Nothing"
  • 트랜잭션의 연산이 모두 수행되거나, 하나라도 실패하면 전체가 취소됨
  • 예시: 은행 계좌 이체 (A → B) 중 한 단계라도 실패하면 전체 취소

일관성 (Consistency)

  • 트랜잭션이 실행되기 전과 후에 데이터의 일관성이 유지되어야 함
  • 예시: 계좌 이체 후 잔액이 맞지 않는다면, 일관성이 깨진 것

고립성 (Isolation)

  • 여러 트랜잭션이 동시에 실행될 때, 서로 영향을 주지 않아야 함
  • 예시: 쇼핑몰에서 동시에 여러 사용자가 같은 상품을 구매할 때 재고가 꼬이지 않도록 관리

지속성 (Durability)

  • 트랜잭션이 Commit 된 이후에는 시스템 장애가 발생해도 변경 사항이 유지됨
  • 예시: 주문 완료 후 서버가 다운되더라도, 주문 정보가 유지됨

기본 동작 과정

트랜잭션 시작 → SQL 실행 → 성공 or 실패 처리

트랜잭션 시작

START TRANSACTION;

SQL 실행 (데이터 변경)

UPDATE accounts SET balance = balance - 1000 WHERE id = 1; -- A 계좌에서 1000원 차감
UPDATE accounts SET balance = balance + 1000 WHERE id = 2; -- B 계좌에 1000원 추가

트랜잭션 처리

  • 모든 SQL이 정상적으로 실행되면 Commit
COMMIT;
  • 하나라도 실패하면 Rollback
ROLLBACK;

격리 수준 (Isolation Level)

트랜잭션의 고립성(Isolation)을 보장하기 위해 격리 수준을 설정할 수 있다.
격리 수준이 높을수록 동시성이 낮아지고, 낮을수록 동시성은 높아지지만 데이터 충돌 가능성이 커진다.

격리 수준설명문제 발생 가능성
READ UNCOMMITTED커밋되지 않은 데이터 읽기 허용더티 리드(Dirty Read) 발생 가능
READ COMMITTED커밋된 데이터만 읽기 가능반복 가능하지 않은 읽기(Non-repeatable Read) 발생 가능
REPEATABLE READ같은 트랜잭션 내에서 동일한 데이터를 조회하면 항상 같은 결과 반환팬텀 리드(Phantom Read) 발생 가능
SERIALISABLE트랜잭션을 순차적으로 실행 (가장 강력하지만 느림)모든 문제 해결 가능
  • 기본적으로 READ COMMITTED 또는 REPEATABLE READ가 많이 사용됨

예제 (MySQL)

은행 계좌 이체 예제

START TRANSACTION;

UPDATE accounts SET balance = balance - 500 WHERE id = 1;
UPDATE accounts SET balance = balance + 500 WHERE id = 2;

COMMIT;

✅ 모든 쿼리가 성공하면 계좌 이체 완료
❌ 중간에 오류 발생 시 롤백

START TRANSACTION;

UPDATE accounts SET balance = balance - 500 WHERE id = 1;
-- 오류 발생! (예: id = 2 계좌 없음)
UPDATE accounts SET balance = balance + 500 WHERE id = 2;

ROLLBACK;

➡️ 첫 번째 계좌에서 차감된 500원이 원래대로 복구됨


Spring Boot에서 트랜잭션 적용하기

Spring Boot에서는 @Transactional 어노테이션을 사용하여 트랜잭션을 쉽게 관리할 수 있다.

Service 클래스에서 @Transactional 적용

@Service
public class AccountService {
	
    @Autowired
    private AccountRepository accountRepository;
    
    @Transactional
    public void transferMoney(Long fromAccountId, Long toAccountId, int amount) {
    	Account fromAccount = accountRepository.findById(fromAccountId).orElseThrow();
        Account toAccount = accountRepository.findById(toAccountId).orElseThrow();
        
        
        fromAccount.withdraw(amount);
        toAccount.deposit(amount);
        
        accountRepository.save(fromAccount);
        accountRepository.save(toAccount);
	}
}
  • @Transactional이 적용된 메서드는 모든 SQL이 성공해야만 Commit
  • 중간에 예외 발생 시 자동으로 Rollback

장점과 단점

장점

  1. 데이터 일관성 보장 (ACID 원칙)
  2. 오류 발생 시 안전한 Rollback
  3. 멀티 유저 환경에서 데이터 보호
  4. 데이터 처리의 원자성 유지

단점

  1. 오버헤드 발생 (특히 높은 격리 수준에서는 성능 저하 가능)
  2. 데드락(Deadlock) 가능성 (서로 다른 트랜잭션이 자원을 점유하고 대기 상태)
  3. 설정이 복잡할 수 있음 (격리 수준, 동시성 처리 고려 필요)

정리

  • 트랜잭션은 데이터베이스에서 하나의 논리적 작업 단위를 의미
  • 모든 연산이 성공하면 Commit, 하나라도 실패하면 Rollback
  • ACID 원칙(Atomicity, Consistency, Isolation, Durability)을 따라야 함
  • 트랜잭션 격리 수준을 설정하여 동시성 및 데이터 정합성을 조절 가능
  • Spring Boot에서는 @Transactional 어노테이션으로 쉽게 트랜잭션 적용 가능
profile
Turning Vision into Reality.

0개의 댓글