스프링부터 @transactional 사용법스프링 @Transactional 사용법스프링 트랜잭션 롤백 안됨스프링 트랜잭션 설정Spring Boot @Transactional

[Spring Boot] 트랜잭션(Transaction) 가이드

KUKJIN LEE
KUKJIN LEE
2024년 11월 27일
174

Spring Boot에서 트랜잭션(Transaction)은 데이터의 일관성을 보장하고, 여러 작업을 하나의 논리적 단위로 묶어 처리할 수 있도록 지원합니다.

 

트랜잭션(Transaction)이란?

트랜잭션은 데이터베이스에서 일련의 작업 단위를 말하며, 작업이 모두 성공하거나, 실패 시 전부 롤백(rollback)되어야 하는 원자성을 보장합니다. 따라서 Spring Boot만을 위한 내용이 아니라, CS 지식으로 반드시 알고가야 하는 내용 중 일부입니다.

 

트랜잭션의 ACID 속성

  1. Atomicity (원자성): 모든 작업이 성공하거나 실패 시 모두 취소됩니다.

  2. Consistency (일관성): 작업 완료 후 데이터베이스 상태가 일관성을 유지합니다.

  3. Isolation (격리성): 동시에 실행되는 트랜잭션이 서로에게 영향을 미치지 않습니다.

  4. Durability (지속성): 트랜잭션이 완료되면 데이터는 영구적으로 저장됩니다.

 

Spring Boot에서 트랜잭션 설정

Spring Boot는 트랜잭션 관리를 간소화하며, @Transactional 어노테이션을 통해 쉽게 구현할 수 있습니다.

 

의존성 추가

Spring Boot에서 트랜잭션을 사용하려면 기본적으로 JPA나 JDBC 의존성이 필요합니다.

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>

 

@EnableTransactionManagement 활성화

Spring Boot는 기본적으로 트랜잭션 관리를 활성화하지만, @EnableTransactionManagement설정을 통해 커스터마이징 가능합니다.

import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@Configuration
@EnableTransactionManagement
public class TransactionConfig {
    // 커스텀 트랜잭션 설정 (필요 시)
}

 

@Transactional 사용법

Spring Boot에서 트랜잭션 처리를 위해 주로 사용하는 어노테이션입니다.

기본 사용

트랜잭션을 적용하려는 메서드나 클래스에 @Transactional을 추가합니다.

클래스에 적용

클래스 전체의 메서드에 트랜잭션을 적용합니다.

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
@Transactional
public class UserService {
    public void createUser(User user) {
        // 모든 작업이 하나의 트랜잭션 내에서 처리됨
    }
}

메서드에 적용

특정 메서드에만 트랜잭션을 적용합니다.

import org.springframework.transaction.annotation.Transactional;
@Transactional
public void updateUser(User user) {
    // 트랜잭션 처리 로직
}

 

트랜잭션 속성

기본 설정으로 충분합니다. 특별한 이유가 없다면 기본 `@Transactional` 어노테이션으로 충분합니다. 이펙티브 수준을 원하시는 게 아니라면 그냥 읽고 넘어가도 좋습니다.

주요 속성

  • propagation: 트랜잭션 전파 방식.

  • isolation: 트랜잭션 격리 수준.

  • timeout: 트랜잭션 제한 시간.

  • readOnly: 읽기 전용 여부.

@Transactional(
    propagation = Propagation.REQUIRED,
    isolation = Isolation.READ_COMMITTED,
    timeout = 5,
    readOnly = false
)
public void processTransaction() {
    // 트랜잭션 내 처리
}

 

전파(Propagation) 옵션

트랜잭션의 전파 방식을 설정하여 기존 트랜잭션과의 관계를 정의합니다.

옵션

설명

REQUIRED

기본 값. 기존 트랜잭션이 있으면 참여, 없으면 새로 시작.

REQUIRES_NEW

항상 새로운 트랜잭션을 시작. 기존 트랜잭션은 보류.

NESTED

기존 트랜잭션 내에서 중첩 트랜잭션을 시작.

SUPPORTS

기존 트랜잭션이 있으면 참여, 없으면 트랜잭션 없이 실행.

NOT_SUPPORTED

트랜잭션 없이 실행. 기존 트랜잭션은 보류.

MANDATORY

반드시 기존 트랜잭션에 참여. 없으면 예외 발생.

NEVER

트랜잭션 없이 실행. 기존 트랜잭션이 있으면 예외 발생.

 

격리 수준(Isolation Level)

트랜잭션 간 간섭을 방지하기 위한 격리 수준을 설정합니다.

옵션

설명

DEFAULT

데이터베이스 기본 격리 수준 사용.

READ_UNCOMMITTED

다른 트랜잭션의 미완료 변경 내용 읽기 허용.

READ_COMMITTED

커밋된 데이터만 읽기 허용. (기본)

REPEATABLE_READ

트랜잭션 동안 동일한 데이터 읽기 보장.

SERIALIZABLE

가장 높은 격리 수준. 트랜잭션 순차 실행.

 

실무에서의 트랜잭션 활용

트랜잭션 롤백

Spring Boot에서 예외 발생 시 트랜잭션은 자동으로 롤백됩니다.

  • 기본적으로 RuntimeExceptionError는 롤백됩니다.

  • CheckedException은 기본적으로 롤백되지 않으므로, 명시적으로 설정해야 합니다.

@Transactional(rollbackFor = Exception.class)
public void processTransaction() throws Exception {
    // 작업 수행 중 예외 발생 시 롤백
    throw new Exception("Rollback Test");
}

읽기 전용 트랜잭션

읽기 전용 작업에는 readOnly = true를 설정하여 성능을 최적화할 수 있습니다.

@Transactional(readOnly = true)
public List<User> getUsers() {
    return userRepository.findAll();
}

트랜잭션 관리 주의사항

  1. @Transactional은 public 메서드에서만 동작

    • Spring AOP 기반으로 동작하므로, private 메서드에서는 트랜잭션이 적용되지 않습니다.

  2. 자기 호출(self-invocation) 문제

    • 같은 클래스 내에서 @Transactional이 선언된 메서드를 호출하면 트랜잭션이 적용되지 않을 수 있습니다.

  3. 읽기 전용 설정

    • 읽기 전용 작업에서 쓰기 작업을 수행하면 예외가 발생할 수 있습니다.

  4. DB 락(lock) 주의

    • 높은 격리 수준(예: SERIALIZABLE)은 데드락 가능성을 높일 수 있으므로 주의해야 합니다.

관련 글

[SQL 입문] 필요한 데이터만 콕 집어 가져올 수 있는 WHERE 절

사용자는 테이블에 있는 모든 데이터를 다 보고 싶어 하지는 않습니다. 오히려 특정 항목에 대한 데이터만 가져오고 싶을 때가 훨씬 많습니다. 예를 들어, 어떤 사용자의 이메일이나 ID는 알고 있는데, 그 사람이 언제 우리 앱에 가입했는지 확인하고 싶다고 가정해 봅시다...

2026년 1월 27일10

SQL에서 SELECT란 무엇인가?

데이터베이스를 거대한 서류 보관함이라고 생각하면 됩니다. 보관함 안에는 수많은 데이터가 차곡차곡 쌓입니다. SELECT는 이 보관함에서 "내가 원하는 정보를 찾아줘!"라고 요청하는 명령어입니다. 이 과정을 전문 용어로 '쿼리(Query)'라고 부릅니다. &amp;nbs...

2026년 1월 26일10

[SQL 기초] "언제 하나씩 다 넣어?" 데이터 한 번에 넣기

개발을 하다 보면 데이터베이스(DB)에 샘플 데이터를 대량으로 넣어야 할 때가 있습니다. 메뉴 100개를 추가해야 하는데 INSERT 문을 100번 쓰고 있다면? 너무 비효율적이죠! 오늘은 SQL에서 여러 데이터를 한 번에 넣는 '다중 삽입(Multiple Inse...

2026년 1월 21일13

SQL 데이터 삽입하기

데이터가 없는 데이터베이스는 연료 없는 로켓과 같습니다. 이제 'Missions' 테이블에 새로운 행(row)을 추가하는 방법을 알아보겠습니다. "삽입(Inserting)"은 '데이터 추가'를 의미합니다. 기존 Missions 테이블 ...

2026년 1월 20일12