DB/sql

임베디드(= 메모리) 데이터 베이스

wooweee 2023. 9. 25. 16:54
728x90

1. test - 임베디드 모드 db

  • 사용 이유
    1. test case를 실행하려고 별도의 db를 설치하고, 운영하는 것이 비효율적
    2. 단순 검증 용도로 사용하므로 test 종료시 db의 data를 모두 삭제해도 된다.
    3. 더해서 test 종료시, db 자체를 날려도 된다.
  • 임베디드 모드
    • H2 db는 java로 개발 되어있고 JVM 안에서 memory 모드로 동작한느 특별한 기능 제공
    • app 실행할 때 H2 데이터베이스도 해당 JVM 메모리에 포함해서 함께 실행 하 수 있다.
    • db를 app에 내장해서 함께 실행한다고 Embedded mode라고 한다.
    • app 종료시, embedded mode로 동장하는 H2 db도 함께 종료되고 data도 모두 사라진다. 
      = java libarary처럼 동작한다.
  • 수동, 자동 공통 적용 부분
    1. db database 관련 설정 등록 하면 안된다.
    2. main/resources/schema.sql 파일에 table 생성 sql 등록이 필요하다.

 

1.1. 메모리 db용 sql 파일 생성 (공통)

  • embedded 용 db기 때문에 매번 사라졌다 생기므로 table 자체가 저장 될 수 없다.
  • repository에 ddl 로 table을 넣을 수도 있지만 번거롭다.
  • 조금 더 편리한 emebedded(=memory) db 용 sql 파일을 생성

  • 경로 : main/resources/schema.sql
-- memory h2는 현재 table이 생성되어있지 않는 상태
-- 해당 file에서 table을 생성 해줄 것
-- 규칙이니깐 걍 따를 것
drop table if exists item CASCADE;
create table item
(
    id        bigint generated by default as identity,
    item_name varchar(10),
    price     integer,
    quantity  integer,
    primary key (id)
);

 

1.2. application.properties database 설정 (공통)

  • 우선 순위 : @SpringBootApplication 내부 @Bean 수동 등록 > @application.properties 수동등록 > 자동등록

  • 수동 모드일 경우는 결국 최상단의 @SpringBootApplication의 main method 내부에서 @Bean을 등록하기 때문에 application.properties의 database 등록이 덮어지지만
  • 자동 모드일 경우, embedded 모드가 수행되지 않게 된다. application.properties에서 database를 수동으로 등록했기 때문

  • 결론 :  헷갈리지 않게 embedded 모드 쓸꺼면 application.properties에서 database 등록 하지 말 것 
spring.profiles.active=test

# db 연결 - test -> testcase 변경
# spring.datasource.url=jdbc:h2:tcp://localhost/~/testcase
# spring.datasource.username=sa

logging.level.org.springframework.jdbc=debug

 

1.3. 임베디드 모드 직접 사용

 

1.3.1. application Class

package hello.itemservice;

@Slf4j
@Import(JdbcTemplateV3Config.class)
@SpringBootApplication(scanBasePackages = "hello.itemservice.web")
public class ItemServiceApplication {
   public static void main(String[] args) {
      SpringApplication.run(ItemServiceApplication.class, args);
   }
   // application.properties의 설정 중 local 환경일 경우 @Bean으로 등록한다.
   @Bean
   @Profile("local")
   public TestDataInit testDataInit(ItemRepository itemRepository) {
      return new TestDataInit(itemRepository);
   }
   @Bean
   @Profile("test")
   public DataSource dataSource() {
      log.info("memory database init");
      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;
   }
}

 

  • embedded용 datasource 및 Driver @Bean 등록 - 핵심 
@Bean
@Profile("test")
public DataSource dataSource() {
  log.info("memory database init");
  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;
}

 

  • @Profile("test") : 프로필이 test일 경우에만 해당 class를 스프링 빈으로 등록
  • jdbc:h2:mem:db : 데이터소스를 만들때 이렇게만 적으면 임베디드 모드로 동작하는 h2 사용가능
  • DB_CLOSE_DELAY=-1 : 임베디드 모드에서 db connection 연결이 모두 끊어지면 db도 종료되는데, 그것을 방지하는 설정
  • datasource와 driver만 잘 설정하면 된다.

 

1.4. test - springboot와 임베디드 모드

 

  • spring boot는 @Bean 등록과정을 자동으로 처리
  • @Bean 제거
  • 수동 모드와 동일하게 작동
package hello.itemservice;

@Slf4j
@Import(JdbcTemplateV3Config.class)
@SpringBootApplication(scanBasePackages = "hello.itemservice.web")
public class ItemServiceApplication {
   public static void main(String[] args) {
      SpringApplication.run(ItemServiceApplication.class, args);
   }
   @Bean
   @Profile("local")
   public TestDataInit testDataInit(ItemRepository itemRepository) {
      return new TestDataInit(itemRepository);
   }
}

 

2. test / main Profile 실험

  • application.properties == AP라고 표현

 

  1. test 패키지 경로에 AP file 자체가 없으면 main의 AP를 properties로 사용
    1. main AP에 datasource 등록이 되어있으면 해당 db를 이용해서 test 수행
    2. main AP에 datasource 등록 없으면 embedded mode db 수행

  2. test 패키지 경로에 AP file 이 있는 경우
    - 내부에 profile 설정 여부와 관계없이 해당 test AP를 이용해서 springboot test 수행
    1. test AP에 datasource 등록이 되어있으면 해당 db를 이용해서 test 수행
    2. test AP에 datasource 등록 없으면 embedded mode db 수행

  3. test class에 @Transactional 존재 여부시, 달라지는 log
    - mem이 나오는 것이 확실이 embedded mode임을 나타내는데 2번의 경우도 db를 실행안해도 test가 정상 동작하므로 embedded 모드라고 추정할 수 있다.

    1. @Transactional 존재 시,
      > [HikariProxyConnection@1631143060 wrapping conn0: url=jdbc:h2:mem:b175c7c8-3ee4-4c58-9773-f0be5b88066d user=SA]

    2. @Transactional 존재 안할 시,
      > com.h2database/h2/1.4.200/f7533fe7cb8e99c87a43d325a77b4b678ad9031a/h2-1.4.200

 

 

 

참고 발행글 : 2023.09.25 - [spring/spring db2] - 3. 데이터 접근 기술 - 테스트