- 코딩 공부/Spring

[DB 2편] - 섹션 3. 데이터 접근 기술 - 테스트

방개입니다 2022. 11. 27. 18:02

트랜잭션이 뭔가? 

- 트랜잭션은 데이터베이스의 상태를 변경시키기 위해 수행하는 작업 단위. 

 

데이터베이스를 변경한다는 말은 SELECT, UPDATE, INSERT, DELETE 와 같은 행동을 뜻한다. 

 

이런 트랜잭션은 상황에 따라 여러 개가 만들어질 수 있다. 

그 하나의 트랜잭션은 Commit 되거나 Rollback이 될 수 있다. 

 

트랜잭션의 4가지 특성 

- 원자성 

원자성은 트랜잭션이 DB에 모두 반영되거나, 전혀 반영되지 않거나 ALL or Nothing 

- 독립성 

하나의 트랜잭션은 다른 트랜잭션에 끼어들 수 없고 마찬가지고 독립적 

- 일관성 

작업 처리의 결과가 항상 일관되어야 한다. 즉, 데이터타입이 반환 후와 전이 항상 동일 

- 지속성 

지속성은 트랜잭션이 성공적으로 완료되면 영구적으로 결과에 반영 

 

트랜잭션 관련 코드 

//트랜잭션 관련 코드
@Autowired
PlatformTransactionManager transactionManager;
TransactionStatus status;

@BeforeEach
void beforeEach() {
    //트랜잭션 시작
    status = transactionManager.getTransaction(new
    DefaultTransactionDefinition());
}

@AfterEach
void afterEach() {
//MemoryItemRepository 의 경우 제한적으로 사용
if (itemRepository instanceof MemoryItemRepository) {
((MemoryItemRepository) itemRepository).clearStore();
}
//트랜잭션 롤백
//transactionManager.rollback(status);
}

 

 

 

@Transactional 

스프링이 제공하는 @Trasactional 애노테이션은 로직이 성공적으로 수행되면 커밋하도록 동작한다. 

 

그런데 @Transactional 애노테이션을 테스트에서 사용하면 아주 특별하게 동작한다.

@Transactional 이 테스트에 있으면 스프링은 테스트를 트랜잭션 안에서 실행하고, 테스트가 끝나면 트랜잭션을 자동으로 롤백시켜 버린다. 

 

-> 그러므로 위에 있는 코드가 필요 없이 어노테이션만으로 구현이 가능, 즉 코드의 길이가 짧아지며 사용하기에 편리하다. 

 

 

 

@Trasactional의 장점

테스트가 끝난 후 개발자가 직접 데이터를 삭제하지 않아도 되는 편리함을 제공 

테스트 실행 중에 데이터를 등록하고 중간에 테스트가 강제로 종료되어도 걱정이 없다. 이 경우 트랜잭션을 커밋하지 않기 때문에, 데이터는 자동으로 롤백된다. 

트랜잭션 범위 안에서 테스트를 진행하기 때문에 동시에 다른 테스트가 진행되어도 서로 영향을 주지 않는 장점이 있다. 

@Tracnsactional 덕분에 아주 편리하게 다음 원칙을 지킬 수 있다 

1. 테스트는 다른 테스트와 격리 

2. 테스트는 반복해서 실행할 수 있다. 

 

테스트를 진행하다 강제로 커밋을 하고싶을때에는 @Commit을 클래스 또는 메서드에 붙이면 테스트 종료 후 롤백 대신 커밋이 호출된다. 

@Commuit == @Rollback(value= false) 

 

 

임베디드 모드란? 

h2 데이터베이스는 자바로 개발되어 있고, JVM안에서 메모리 모드로 동작하는 특별한 기능을 제공한다. 그래서 애플리케이션을 실행할 때 H2 데이터베이스도 해당 JVM메모리에 포함해서 함께 싱행할 수 있다. DB를 애플리케이션에 내장해서 함께 실행한다고 해서 임베디드 모드(Embedded Mode)라고 한다. 물론 애플리케이션이 종료되면 임베디드 모드로 동작하는 H2 데이터베이스도 함께 종료되고, 데이터도 모두 사라진다. 자바 메모리와 함께 사용하는 라이브러리처럼 동작. 

 

@Bean
@Profile("test")
public DataSource dataSource() {
    log.info("메모리 데이터베이스 초기화");
    DriverManagerDataSource dataSource = new DriverManagerDataSource();
    dataSource.setDriverClassName("org.h2.Driver");
    dataSource.setUrl("jdbc:h2:mem:db;DB_CLOSE_DELAY=-1");
    dataSource.setUsername("sa");
    dataSource.setPassword("");
    return dataSource;
	}
}