출처: https://docs.spring.io/spring-boot/4.0-SNAPSHOT/how-to/data-initialization.html
SQL 데이터베이스는 스택이 무엇인지에 따라 다양한 방법으로 초기화될 수 있습니다. 물론 데이터베이스가 별도의 프로세스인 경우 수동으로 수행할 수도 있습니다. 스키마 생성을 위해서는 단일 메커니즘을 사용하는 것이 권장됩니다.
Initialize a Database Using Hibernate
spring.jpa.hibernate.ddl-auto
를 설정하여 Hibernate의 데이터베이스 초기화를 제어할 수 있습니다. 지원되는 값은 none
, validate
, update
, create
, create-drop
입니다.
Spring Boot는 임베디드 데이터베이스를 사용하는지 여부에 따라 기본값을 선택합니다. 임베디드 데이터베이스는 Connection
타입과 JDBC url을 확인하여 식별됩니다. hsqldb
, h2
, derby
는 임베디드 데이터베이스이며 나머지는 그렇지 않습니다.
임베디드 데이터베이스가 식별되고 스키마 관리자(Flyway 또는 Liquibase)가 감지되지 않은 경우, ddl-auto
는 기본적으로 create-drop
으로 설정됩니다. 다른 모든 경우에는 none
이 기본값입니다.
인메모리에서 '실제' 데이터베이스로 전환할 때 새 플랫폼에서 테이블과 데이터의 존재를 가정하지 않도록 주의해야 합니다. ddl-auto
를 명시적으로 설정하거나 다른 메커니즘 중 하나를 사용하여 데이터베이스를 초기화해야 합니다.
org.hibernate.SQL
로거를 활성화하여 스키마 생성을 출력할 수 있습니다. 디버그 모드를 활성화하면 자동으로 수행됩니다.
또한 Hibernate가 처음부터 스키마를 생성하는 경우(즉, ddl-auto
속성이 create
또는 create-drop
으로 설정된 경우) classpath의 루트에 있는 import.sql
이라는 파일이 시작 시 실행됩니다. 이는 신중하게 사용하면 데모 및 테스트에 유용할 수 있지만 프로덕션 환경의 classpath에는 사용하지 않는 것이 좋습니다. 이것은 Hibernate 기능입니다(Spring과는 관련이 없습니다).
Initialize a Database Using Basic SQL Scripts
Spring Boot는 JDBC DataSource
또는 R2DBC ConnectionFactory
의 스키마(DDL 스크립트)를 자동으로 생성하고 데이터(DML 스크립트)를 초기화할 수 있습니다.
기본적으로 optional:classpath*:schema.sql
에서 스키마 스크립트를 로드하고 optional:classpath*:data.sql
에서 데이터 스크립트를 로드합니다. 이러한 스키마 및 데이터 스크립트의 위치는 각각 spring.sql.init.schema-locations
및 spring.sql.init.data-locations
를 사용하여 사용자 정의할 수 있습니다.
optional:
접두사는 파일이 존재하지 않아도 애플리케이션이 시작된다는 것을 의미합니다. 파일이 없을 때 애플리케이션 시작이 실패하도록 하려면 optional:
접두사를 제거하세요.
또한 Spring Boot는 optional:classpath*:schema-${platform}.sql
및 optional:classpath*:data-${platform}.sql
파일(있는 경우)을 처리합니다. 여기서 ${platform}
은 spring.sql.init.platform
의 값입니다. 이를 통해 필요한 경우 데이터베이스별 스크립트로 전환할 수 있습니다. 예를 들어, 데이터베이스의 벤더 이름(hsqldb
, h2
, oracle
, mysql
, postgresql
등)으로 설정할 수 있습니다.
기본적으로 SQL 데이터베이스 초기화는 임베디드 인메모리 데이터베이스를 사용할 때만 수행됩니다. 유형에 관계없이 항상 SQL 데이터베이스를 초기화하려면 spring.sql.init.mode
를 always
로 설정하세요. 마찬가지로 초기화를 비활성화하려면 spring.sql.init.mode
를 never
로 설정하세요.
기본적으로 Spring Boot는 스크립트 기반 데이터베이스 이니셜라이저의 fail-fast 기능을 활성화합니다. 이는 스크립트에서 예외가 발생하면 애플리케이션이 시작되지 않는다는 것을 의미합니다. spring.sql.init.continue-on-error
를 설정하여 이 동작을 조정할 수 있습니다.
스크립트 기반 DataSource
초기화는 기본적으로 JPA EntityManagerFactory
빈이 생성되기 전에 수행됩니다. schema.sql
은 JPA 관리 엔터티의 스키마를 생성하는 데 사용될 수 있으며 data.sql
은 이를 채우는 데 사용될 수 있습니다.
여러 데이터 소스 초기화 기술을 사용하는 것은 권장하지 않지만, 스크립트 기반 DataSource
초기화가 Hibernate에 의해 수행된 스키마 생성을 기반으로 할 수 있도록 하려면 spring.jpa.defer-datasource-initialization
을 true
로 설정하세요. 이렇게 하면 EntityManagerFactory
빈이 생성되고 초기화된 후까지 데이터 소스 초기화가 지연됩니다. 그런 다음 schema.sql
을 사용하여 Hibernate에 의해 수행된 스키마 생성에 추가할 수 있으며 data.sql
을 사용하여 채울 수 있습니다.
초기화 스크립트는 한 줄 주석에 --
를, 블록 주석에 /* */
를 지원합니다. 다른 주석 형식은 지원되지 않습니다.
Flyway 또는 Liquibase와 같은 상위 레벨 데이터베이스 마이그레이션 도구를 사용하는 경우 이를 단독으로 사용하여 스키마를 생성하고 초기화해야 합니다. Flyway 또는 Liquibase와 함께 기본 schema.sql
및 data.sql
스크립트를 사용하는 것은 권장되지 않으며 향후 릴리스에서 지원이 제거됩니다.
상위 레벨 데이터베이스 마이그레이션 도구를 사용하여 테스트 데이터를 초기화해야 하는 경우 Flyway 및 Liquibase에 대한 섹션을 참조하세요.
Initialize a Spring Batch Database
Spring Batch를 사용하는 경우 대부분의 인기 있는 데이터베이스 플랫폼에 대한 SQL 초기화 스크립트가 사전 패키지되어 제공됩니다. Spring Boot는 데이터베이스 유형을 감지하고 시작 시 해당 스크립트를 실행할 수 있습니다. 임베디드 데이터베이스를 사용하는 경우 기본적으로 이 작업이 수행됩니다. 다음 예제와 같이 모든 데이터베이스 유형에 대해 활성화할 수도 있습니다:
Properties
spring.batch.jdbc.initialize-schema=always
YAML
spring:
batch:
jdbc:
initialize-schema: "always"
spring.batch.jdbc.initialize-schema
를 never
로 설정하여 초기화를 명시적으로 끌 수도 있습니다.
Use a Higher-level Database Migration Tool
Spring Boot는 두 가지 상위 레벨 마이그레이션 도구를 지원합니다: Flyway와 Liquibase.
Execute Flyway Database Migrations on Startup
시작 시 Flyway 데이터베이스 마이그레이션을 자동으로 실행하려면 적절한 Flyway 모듈을 classpath에 추가하세요.
인메모리 및 파일 기반 데이터베이스는 org.flywaydb:flyway-core
에서 지원됩니다. 그렇지 않으면 데이터베이스별 모듈이 필요합니다. 예를 들어 PostgreSQL에는 org.flywaydb:flyway-database-postgresql
을, MySQL에는 org.flywaydb:flyway-mysql
을 사용하세요. 자세한 내용은 Flyway 문서를 참조하세요.
일반적으로 마이그레이션은 V<VERSION>__<NAME>.sql
형식의 스크립트입니다(<VERSION>
은 '1' 또는 '2_1'과 같이 밑줄로 구분된 버전). 기본적으로 이들은 classpath:db/migration
이라는 디렉토리에 있지만 spring.flyway.locations
를 설정하여 해당 위치를 수정할 수 있습니다. 이것은 하나 이상의 classpath:
또는 filesystem:
위치의 쉼표로 구분된 목록입니다. 예를 들어 다음 구성은 기본 classpath 위치와 /opt/migration
디렉토리 모두에서 스크립트를 검색합니다:
Properties
spring.flyway.locations=classpath:db/migration,filesystem:/opt/migration
YAML
spring:
flyway:
locations: "classpath:db/migration,filesystem:/opt/migration"
특수 {vendor}
플레이스홀더를 추가하여 벤더별 스크립트를 사용할 수도 있습니다. 다음을 가정합니다:
Properties
spring.flyway.locations=classpath:db/migration/{vendor}
YAML
spring:
flyway:
locations: "classpath:db/migration/{vendor}"
db/migration
을 사용하는 대신 위의 구성은 데이터베이스 유형에 따라 사용할 디렉토리를 설정합니다(예: MySQL의 경우 db/migration/mysql
). 지원되는 데이터베이스 목록은 DatabaseDriver
에서 확인할 수 있습니다.
마이그레이션은 Java로도 작성할 수 있습니다. Flyway는 JavaMigration
을 구현하는 모든 빈으로 자동 구성됩니다.
FlywayProperties
는 Flyway 설정의 대부분과 마이그레이션을 비활성화하거나 위치 확인을 끌 수 있는 소수의 추가 속성을 제공합니다. 구성에 대한 더 많은 제어가 필요한 경우 FlywayConfigurationCustomizer
빈을 등록하는 것을 고려하세요.
Spring Boot는 Flyway.migrate()
를 호출하여 데이터베이스 마이그레이션을 수행합니다. 더 많은 제어가 필요한 경우 FlywayMigrationStrategy
를 구현하는 @Bean
을 제공하세요.
Flyway는 SQL 및 Java 콜백을 지원합니다. SQL 기반 콜백을 사용하려면 classpath:db/migration
디렉토리에 콜백 스크립트를 배치하세요. Java 기반 콜백을 사용하려면 Callback
을 구현하는 하나 이상의 빈을 생성하세요. 이러한 빈은 자동으로 Flyway
에 등록됩니다. @Order
를 사용하거나 Ordered
를 구현하여 순서를 지정할 수 있습니다.
기본적으로 Flyway는 컨텍스트의 (@Primary
) DataSource
를 자동 연결하고 마이그레이션에 사용합니다. 다른 DataSource
를 사용하려면 하나를 생성하고 해당 @Bean
을 @FlywayDataSource
로 표시할 수 있습니다. 이렇게 하고 두 개의 데이터 소스를 원하는 경우(예: 기본 자동 구성 DataSource
를 유지함으로써) @Bean
어노테이션의 defaultCandidate
속성을 false
로 설정해야 합니다. 또는 외부 속성에서 spring.flyway.[url,user,password]
를 설정하여 Flyway의 네이티브 DataSource
를 사용할 수 있습니다. spring.flyway.url
또는 spring.flyway.user
를 설정하면 Flyway가 자체 DataSource
를 사용하기에 충분합니다. 세 가지 속성 중 하나라도 설정되지 않은 경우 해당 spring.datasource
속성의 값이 사용됩니다.
Flyway를 사용하여 특정 시나리오에 대한 데이터를 제공할 수도 있습니다. 예를 들어 src/test/resources
에 테스트별 마이그레이션을 배치할 수 있으며 애플리케이션이 테스트를 위해 시작될 때만 실행됩니다. 또한 프로파일별 구성을 사용하여 spring.flyway.locations
를 사용자 정의하여 특정 프로파일이 활성화될 때만 특정 마이그레이션이 실행되도록 할 수 있습니다. 예를 들어 application-dev.properties
에서 다음 설정을 지정할 수 있습니다:
Properties
spring.flyway.locations=classpath:/db/migration,classpath:/dev/db/migration
YAML
spring:
flyway:
locations: "classpath:/db/migration,classpath:/dev/db/migration"
이 설정을 사용하면 dev/db/migration
의 마이그레이션은 dev
프로파일이 활성화될 때만 실행됩니다.
Execute Liquibase Database Migrations on Startup
시작 시 Liquibase 데이터베이스 마이그레이션을 자동으로 실행하려면 org.liquibase:liquibase-core
를 classpath에 추가하세요.
org.liquibase:liquibase-core
를 classpath에 추가하면 애플리케이션 시작 시와 테스트 실행 전 모두 데이터베이스 마이그레이션이 기본적으로 실행됩니다. 이 동작은 main
및 test
구성에서 서로 다른 값을 설정하여 spring.liquibase.enabled
속성을 사용하여 사용자 정의할 수 있습니다. 두 가지 다른 방법을 사용하여 데이터베이스를 초기화하는 것은 불가능합니다(예: 애플리케이션 시작에는 Liquibase, 테스트 실행에는 JPA).
기본적으로 마스터 변경 로그는 db/changelog/db.changelog-master.yaml
에서 읽히지만 spring.liquibase.change-log
를 설정하여 위치를 변경할 수 있습니다. YAML 외에도 Liquibase는 JSON, XML 및 SQL 변경 로그 형식을 지원합니다.
기본적으로 Liquibase는 컨텍스트의 (@Primary
) DataSource
를 자동 연결하고 마이그레이션에 사용합니다. 다른 DataSource
를 사용해야 하는 경우 하나를 생성하고 해당 @Bean
을 @LiquibaseDataSource
로 표시할 수 있습니다. 이렇게 하고 두 개의 데이터 소스를 원하는 경우(예: 기본 자동 구성 DataSource
를 유지함으로써) @Bean
어노테이션의 defaultCandidate
속성을 false
로 설정해야 합니다. 또는 외부 속성에서 spring.liquibase.[driver-class-name,url,user,password]
를 설정하여 Liquibase의 네이티브 DataSource
를 사용할 수 있습니다. spring.liquibase.url
또는 spring.liquibase.user
를 설정하면 Liquibase가 자체 DataSource
를 사용하기에 충분합니다. 세 가지 속성 중 하나라도 설정되지 않은 경우 해당 spring.datasource
속성의 값이 사용됩니다.
컨텍스트, 기본 스키마 등과 같은 사용 가능한 설정에 대한 자세한 내용은 LiquibaseProperties
를 참조하세요.
사용되기 전에 Liquibase
인스턴스를 사용자 정의하려는 경우 Customizer<Liquibase>
빈을 사용할 수도 있습니다.
Use Flyway for Test-only Migrations
테스트 데이터베이스를 채우는 Flyway 마이그레이션을 생성하려면 src/test/resources/db/migration
에 배치하세요. 예를 들어 src/test/resources/db/migration/V9999__test-data.sql
이라는 파일은 프로덕션 마이그레이션 이후에 실행되며 테스트를 실행하는 경우에만 실행됩니다. 이 파일을 사용하여 필요한 테스트 데이터를 생성할 수 있습니다. 이 파일은 uber jar 또는 컨테이너에 패키징되지 않습니다.
Use Liquibase for Test-only Migrations
테스트 데이터베이스를 채우는 Liquibase 마이그레이션을 생성하려면 프로덕션 변경 로그도 포함하는 테스트 변경 로그를 생성해야 합니다.
먼저 테스트를 실행할 때 다른 변경 로그를 사용하도록 Liquibase를 구성해야 합니다. 이를 수행하는 한 가지 방법은 Spring Boot test
프로파일을 생성하고 거기에 Liquibase 속성을 넣는 것입니다. 이를 위해 src/test/resources/application-test.properties
라는 파일을 생성하고 다음 속성을 넣으세요:
Properties
spring.liquibase.change-log=classpath:/db/changelog/db.changelog-test.yaml
YAML
spring:
liquibase:
change-log: "classpath:/db/changelog/db.changelog-test.yaml"
이렇게 하면 테스트를 실행할 때 Liquibase가 다른 변경 로그를 사용하도록 구성됩니다.
이제 src/test/resources/db/changelog/db.changelog-test.yaml
에서 프로덕션 변경 로그를 포함하고 테스트별 변경 세트를 추가해야 합니다:
databaseChangeLog:
- include:
file: db/changelog/db.changelog-master.yaml
- changeSet:
id: test-data
author: test
changes:
- insert:
tableName: my_table
columns:
- column:
name: id
value: 1
- column:
name: name
value: test
이제 테스트를 실행하면 프로덕션 변경 로그가 먼저 실행된 다음 테스트별 변경 세트가 실행됩니다.
Depend Upon an Initialized Database
데이터베이스 초기화는 애플리케이션 시작 중에 수행됩니다. 시작 시 초기화된 데이터베이스에 액세스하려면 데이터베이스 이니셜라이저 역할을 하는 빈과 데이터베이스 초기화가 필요한 빈을 감지하는 것이 중요합니다. 이 섹션에서는 Spring Boot에서 사용하는 감지 메커니즘과 이를 구성하는 방법을 설명합니다.
Detect a Database Initializer
Spring Boot는 다음 유형의 빈을 데이터베이스 이니셜라이저로 자동 감지합니다:
DataSourceScriptDatabaseInitializer
EntityManagerFactory
Flyway
FlywayMigrationInitializer
R2dbcScriptDatabaseInitializer
SpringLiquibase
사용자 정의 데이터베이스 이니셜라이저 빈을 사용하는 경우 @DependsOnDatabaseInitialization
으로 어노테이션을 달아야 합니다. 그러면 다른 빈이 의존할 수 있도록 데이터베이스 이니셜라이저로 감지됩니다. 또는 기본 구성 클래스에서 DatabaseInitializationDependencyConfigurer
의 서브클래스를 선언하고 감지할 데이터베이스 이니셜라이저 빈 유형으로 어노테이션을 달 수 있습니다. 예를 들어 사용자 정의 DataSourceInitializer
빈을 사용하는 경우 다음과 같이 등록할 수 있습니다:
@Configuration(proxyBeanMethods = false)
@DependsOnDatabaseInitialization(DataSourceInitializer.class)
static class DataSourceInitializerDetectionConfiguration
extends DatabaseInitializationDependencyConfigurer {
}
Detect a Bean That Depends On Database Initialization
Spring Boot는 다음 유형의 빈을 데이터베이스 초기화에 의존하는 것으로 자동 감지합니다:
JdbcOperations
NamedParameterJdbcOperations
사용자 정의 빈 유형을 사용하는 경우 @DependsOnDatabaseInitialization
으로 어노테이션을 달아야 합니다. 또는 기본 구성 클래스에서 DatabaseInitializationDependencyConfigurer
의 서브클래스를 선언하고 데이터베이스 초기화에 의존하는 빈 유형으로 어노테이션을 달 수 있습니다.