@Transactional

코딩냥이·2024년 9월 10일

Annotation

목록 보기
16/34

@Transactional

@Transactional 어노테이션은 스프링 프레임워크에서 데이터베이스 트랜잭션을 관리하는 데 사용되는 핵심 어노테이션입니다.

기능

  • 메소드나 클래스에 트랜잭션 경계를 설정합니다.
  • 선언적 트랜잭션 관리를 가능하게 합니다.
  • 트랜잭션의 전파 방식, 격리 수준, 타임아웃 등을 설정할 수 있습니다.

사용 방법

기본적인 사용 방법은 다음과 같습니다:

import org.springframework.transaction.annotation.Transactional;
import org.springframework.stereotype.Service;

@Service
public class UserService {

    @Transactional
    public void createUser(User user) {
        // 사용자 생성 로직
    }
}

주요 특징

  1. 선언적 트랜잭션: 코드 변경 없이 트랜잭션 경계를 설정할 수 있습니다.
  2. 메소드 또는 클래스 레벨 적용: 개별 메소드나 클래스 전체에 적용할 수 있습니다.
  3. 다양한 설정 옵션: 트랜잭션의 동작을 세밀하게 제어할 수 있는 여러 옵션을 제공합니다.
  4. 런타임 예외 롤백: 기본적으로 런타임 예외 발생 시 롤백이 수행됩니다.

주요 속성

1. propagation (전파 방식)

트랜잭션의 경계를 어떻게 설정할지 결정합니다.

@Transactional(propagation = Propagation.REQUIRED)
public void someMethod() {
    // 메소드 내용
}

주요 전파 옵션:

  • REQUIRED: 기본값. 활성 트랜잭션이 없으면 새로 생성, 있으면 참여.
  • REQUIRES_NEW: 항상 새로운 트랜잭션을 시작.
  • SUPPORTS: 활성 트랜잭션이 있으면 참여, 없으면 트랜잭션 없이 실행.
  • NOT_SUPPORTED: 트랜잭션 없이 실행, 활성 트랜잭션이 있으면 일시 중지.

2. isolation (격리 수준)

트랜잭션 간의 격리 수준을 설정합니다.

@Transactional(isolation = Isolation.READ_COMMITTED)
public void someMethod() {
    // 메소드 내용
}

주요 격리 수준:

  • DEFAULT: 데이터베이스의 기본 격리 수준 사용.
  • READ_UNCOMMITTED: 커밋되지 않은 데이터 읽기 가능.
  • READ_COMMITTED: 커밋된 데이터만 읽기 가능.
  • REPEATABLE_READ: 동일 데이터를 여러 번 읽을 때 일관성 보장.
  • SERIALIZABLE: 가장 높은 격리 수준, 성능 저하 가능성 있음.

3. timeout

트랜잭션의 제한 시간을 설정합니다.

@Transactional(timeout = 30)
public void someMethod() {
    // 메소드 내용
}

4. readOnly

읽기 전용 트랜잭션을 설정합니다.

@Transactional(readOnly = true)
public User getUser(Long id) {
    // 사용자 조회 로직
}

5. rollbackFor / noRollbackFor

특정 예외에 대해 롤백 동작을 지정합니다.

@Transactional(rollbackFor = CustomException.class)
public void someMethod() throws CustomException {
    // 메소드 내용
}

트랜잭션 동작 원리

  1. 프록시 생성: 스프링은 @Transactional이 적용된 빈에 대해 프록시를 생성합니다.
  2. 트랜잭션 시작: 프록시는 메소드 호출 시 트랜잭션을 시작합니다.
  3. 메소드 실행: 실제 빈의 메소드가 실행됩니다.
  4. 트랜잭션 완료: 메소드 실행이 완료되면 트랜잭션을 커밋하거나 롤백합니다.

주의사항

  1. public 메소드: @Transactional은 기본적으로 public 메소드에만 적용됩니다.
  2. 자가 호출: 같은 클래스 내에서 @Transactional 메소드를 호출할 경우 트랜잭션이 적용되지 않습니다.
  3. 런타임 예외: 기본적으로 런타임 예외에만 롤백이 수행됩니다.
  4. 프록시 방식: 스프링의 기본 AOP 프록시 방식으로 인한 제약사항들이 있습니다.

베스트 프랙티스

  1. 적절한 범위 설정: 트랜잭션 범위를 필요한 만큼만 설정하세요.
  2. 읽기 전용 트랜잭션 활용: 조회 작업에는 readOnly = true를 사용하여 성능을 최적화하세요.
  3. 예외 처리: 비즈니스 예외를 적절히 정의하고 처리하세요.
  4. 전파 속성 이해: 트랜잭션 전파 속성을 잘 이해하고 적절히 사용하세요.
  5. 테스트: 트랜잭션 동작을 검증하는 테스트를 작성하세요.

테스트

@Transactional 어노테이션이 적용된 메소드를 테스트할 때는 다음과 같이 할 수 있습니다:

@SpringBootTest
class UserServiceTest {

    @Autowired
    private UserService userService;

    @Autowired
    private UserRepository userRepository;

    @Test
    @Transactional
    void testCreateUser() {
        User user = new User("test@example.com");
        userService.createUser(user);
        
        User foundUser = userRepository.findByEmail("test@example.com");
        assertNotNull(foundUser);
        assertEquals("test@example.com", foundUser.getEmail());
    }
}

결론

@Transactional 어노테이션은 스프링에서 데이터 일관성과 무결성을 유지하는 데 필수적인 도구입니다. 이를 통해 개발자는 선언적으로 트랜잭션을 관리할 수 있으며, 비즈니스 로직에 더 집중할 수 있습니다. 그러나 그 동작 원리와 제약사항을 잘 이해하고 사용해야 하며, 적절한 설정과 테스트가 중요합니다.

연관 포스팅

@Repository
@Service
@Configuration
@EnableTransactionManagement
@Bean

profile
HelloMeow~!

0개의 댓글