[Spring] Transaction(트렌젝션)

Neo-Renaissance·2024년 12월 26일

@Transactional

1. @Transactional의 역할

스프링에서 @Transactional 어노테이션은 트랜잭션 관리를 활성화하는 데 사용됩니다. 테스트 메서드에 @Transactional을 붙이면 다음과 같은 기능이 적용됩니다:

  • 테스트 메서드 시작 시 트랜잭션이 시작됩니다.
  • 테스트 메서드가 끝난 후 자동으로 트랜잭션이 롤백됩니다.
  • 테스트 환경에서는 데이터베이스 상태를 초기 상태로 유지하기 위해 롤백이 기본 동작으로 설정됩니다.
  • 이를 통해 테스트가 실행된 후 다른 테스트나 실제 코드에 영향을 주지 않도록 보장합니다.

2. 코드에서 @Transactional의 효과

@Test
@Transactional
public void testMember() throws Exception {
	//given
    Member member = new Member();
    member.setUserName("memberA");

    // when
    Long saveId = memberRepository.save(member);
    Member findMember = memberRepository.find(saveId);

    //then
    Assertions.assertThat(findMember.getId()).isEqualTo(member.getId());
	Assertions.assertThat(findMember.getUserName()).isEqualTo(member.getUserName());
}

위 코드에서 @Transactional 어노테이션이 없으면 다음과 같은 문제가 발생할 수 있습니다:

  1. 테스트 데이터가 데이터베이스에 영구적으로 남음
  • memberRepository.save(member) 메서드가 호출되면 데이터베이스에 실제 데이터를 저장합니다.
  • @Transactional이 없으면 트랜잭션이 자동으로 롤백되지 않으므로, 테스트 데이터가 데이터베이스에 남게 됩니다. 이는 다른 테스트 간의 독립성을 해치며, 데이터 누적 문제를 일으킬 수 있습니다.
  1. Hibernate 영속성 컨텍스트와 데이터베이스 동기화 문제
  • 스프링에서 @Transactional은 트랜잭션 범위 내에서 영속성 컨텍스트를 관리합니다.
  • save() 메서드를 호출하면 엔티티는 영속성 컨텍스트에 저장되고, 트랜잭션이 커밋되기 전까지 데이터베이스에 반영되지 않을 수도 있습니다.
  • @Transactional이 없으면 영속성 컨텍스트가 제대로 관리되지 않아 find(saveId) 호출 시 데이터베이스에서 찾지 못하거나, 예상과 다른 동작이 발생할 수 있습니다.
  1. 지연 로딩(Lazy Loading) 관련 오류
  • 테스트 중 @Transactional이 없으면 영속성 컨텍스트가 테스트 메서드 내에서 유지되지 않습니다.
  • 만약 지연 로딩을 사용하는 엔티티라면, 테스트 메서드에서 해당 데이터를 호출하려 할 때 LazyInitializationException이 발생할 수 있습니다.

3. 테스트 환경에서 @Transactional의 기본 동작 변경

기본적으로 테스트에서는 @Transactional이 자동으로 롤백되도록 설정되어 있지만, 실제 데이터베이스에 변경 내용을 적용하고 싶다면 @Commit 어노테이션을 추가하거나 @Rollback(false) 설정을 사용할 수 있습니다.

@Test
@Transactional
@Rollback(false)  // 데이터베이스에 변경 내용을 적용
public void testMemberPersist() {
    // Test logic
}
profile
if (실패) { 다시 도전; } else { 성공; }

0개의 댓글