프로필사진

Go, Vantage point

가까운 곳을 걷지 않고 서는 먼 곳을 갈 수 없다.


Github | https://github.com/overnew/

Blog | https://everenew.tistory.com/





티스토리 뷰

반응형

 

 

 

* 김영한님의 스프링 DB 2편 강좌를 수강하며 정리한 글입니다. *

 

스프링 DB 2편 - 데이터 접근 활용 기술 - 인프런 | 강의

백엔드 개발에 필요한 DB 데이터 접근 기술을 활용하고, 완성할 수 있습니다. 스프링 DB 접근 기술의 원리와 구조를 이해하고, 더 깊이있는 백엔드 개발자로 성장할 수 있습니다., - 강의 소개 | 인

www.inflearn.com

 

 

 

이전 글에서는 JdbcTemplate의 활용법에 대해서 정리하였다.

 

 

 

테스트 데이터베이스의 분리

 

 

@SpringBootTest는 상위 패키지에서 @SpringBootApplication을 찾아서 자동으로 설정 정보를 사용한다.

데이터베이스를 사용해 테스트를 하다 보면 DB에 남은 데이터로 인해 영향을 받을 수 있다.

 

테스트에는 외부의 변수가 개입하지 않는 격리성이 중요하다.

테스트와 로컬 서버가 같은 DB를 사용하기 때문에 문제가 있다.

이를 해결하기위해 테스트 DB를 분리해보자.

 

 

가장 간단한 방법은 테스트 전용 DB를 만드는 것이다.

h2에 새로운 testcase 전용 DB를 생성하고 test의 application.properties에 세팅을 해주자.

 

spring.datasource.url=jdbc:h2:tcp://localhost/~/testcase
spring.datasource.username=sa
spring.datasource.password=

 

또한 테스트는 반복적인 수행에도 동일한 결과를 내야 한다.

따라서 테스트에서 등록한 데이터는 반드시 clear해 두어야 한다.

단, 테스트 코드의 마지막에 DELETE 쿼리 문을 넣는 것은 오류 발생 시 실행이 되지 않을 수 있기 때문에 적절하지 않다.

 

이럴 때 사용하는 것이 지금까지 배운 트랜잭션이다.

 

 

 

테스트에서의 트랜잭션 활용

 

트랜잭션은 DB에 commit하지 않은 경우 임시로만 저장이 되기 때문에 반영되지 않는다.

데이터를 반영하지 않기 위해 직접 rollback 하는 방법도 있다.

 

이를 위해 이전에 정리한 transactionManager를 사용한다.

@Autowired      //스프링 부트가 적절한 manager 구현체를 자동 주입 해줌
PlatformTransactionManager transactionManager;
TransactionStatus status;

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

@AfterEach
void afterEach() {
    //트랜잭션 롤백하기
    transactionManager.rollback(status);
}

 

 

같은 커낵션을 이용하는 구조

 

 

매번 실행 전에 트랜잭션을 시작하면 트랜잭션 매니저의 동기화 매니저의 커낵션을 가져와 사용한다.

따라서 트랜잭션 종료 전까지 같은 커낵션을 이용하기 때문에 같은 트랜잭션을 이용한다.

테스트 후 트랜잭션을 롤백하면 서로의 데이터는 영향을 주지 않는다.

 

 

 

@Transactional

 

트랜잭션을 간단히 적용해주는 @Transactional에 대해서도 저번 글에 정리하였다.

위의 테스트 격리성과 반복성을 완벽히 지원해주는 것이 이 어노테이션이다.

 

기본 로직에 적용되면  에러가 없을 때는 commit, 에러가 없을때는 rollback 자동으로 수행해 주었다.

테스트 코드에 적용 시에는 테스트 코드를 트랜잭션 안에서 실행한 후, 자동으로 rollback을 수행해 준다.

 

@Transactional은 각 메서드에만 적용할 수도 있고, 클래스에 적용시 모든 테스트 메서드가 실행 전에 트랜잭션이 시작된다.

 

만약 테스트에서도 commit을 수행하고 싶다면 @Commit 어노테이션을 클래스 또는 메서드에 적용해주자.

같은 기능인 @Rollback(value = false)를 적용할 수도 있다.

 

 

 

임베디드 모드 DB

 

테스트 만을 위한 DB를 생성해도 되지만, H2는 자바로 개발되어 JVM에서 동작할 수 있다.

따라서 애플리케이션에 내장될 수 있고 이를 임베디드 모드라고 한다.

물론 JVM 메모리에서 동작하기 때문에 어플리케이션 종료 시 데이터가 사라지지만, 테스트에는 적합하다.

 

@Bean
@Profile("test")   //테스트의 dataSource는 자동 주입이 아닌 데이터베이스 직접 등록
public DataSource dataSource(){
   DriverManagerDataSource dataSource = new DriverManagerDataSource();
   dataSource.setDriverClassName("org.h2.Driver");    //구현체 선언
   dataSource.setUrl("jdbc:h2:mem:db;DB_CLOSE_DELAY=-1"); // h2:mem는 Jvm에서 동작시키게 함
   dataSource.setUsername("sa");
   dataSource.setPassword("");
   return dataSource;
}

 

이런 임베디드 DB는 테이블이 전혀 생성되지 않은 초기 상태이기 때문에 매번 테스트마다 생성해주긴 힘들다.

하지만 스프링 부트는 어플리케이션 로딩 시점에 SQL 스크립트를 실행해서 초기화시켜주는 기능을 제공한다.

 

resources/schema.sql 파일에 초기화 SQL 구문을 넣어두면 생성시점에 자동으로 실행된다.

 

 

사실, 스프링 부트는 DB 설정이 없을 때 임베디드 DB를 사용한다.

따라서 URL과 같은 세팅을 하지 않으면 임베디드 DB가 자동 실행된다.

 

 

 

반응형

'개발 > Spring DataBase' 카테고리의 다른 글

[Spring DB] 9. JPA  (0) 2022.07.27
[Spring DB] 8. MyBatis  (0) 2022.07.26
[Spring DB] 6. 프로필과 JdbcTemplate  (0) 2022.07.24
[Spring DB] 5. 런타임 예외의 활용  (0) 2022.07.21
[Spring DB] 4. 스프링의 트랜잭션 매니저  (0) 2022.07.19
댓글
반응형
인기글
Total
Today
Yesterday
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
글 보관함