DevLog ๐Ÿ˜ถ

[Spring] Database Initialization : schema.sql๊ณผ data.sql ๋ณธ๋ฌธ

Back-end/Spring

[Spring] Database Initialization : schema.sql๊ณผ data.sql

dolmeng2 2023. 4. 15. 16:03

๐ŸŒฑ ๋ฌธ์ œ ์ƒํ™ฉ

ํŽ˜์–ด ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ์ง„ํ–‰ํ•˜๋ฉด์„œ, ๋ถ„๋ช… ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ๊ฐ๊ฐ์„ ์‹คํ–‰ํ–ˆ์„ ๋•Œ๋Š” ์ž˜ ๋Œ์•„๊ฐ”๋Š”๋ฐ ์ „์ฒด๋ฅผ ์‹คํ–‰ํ•˜๋‹ˆ๊นŒ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์˜ค๋ฅ˜๋ฅผ ๋งŒ๋‚ฌ์—ˆ๋‹ค.

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSourceScriptDatabaseInitializer' defined in class path resource [org/springframework/boot/autoconfigure/sql/init/DataSourceInitializationConfiguration.class]: Invocation of init method failed; nested exception is org.springframework.jdbc.datasource.init.ScriptStatementFailedException: Failed to execute SQL script statement #1 of URL [file:/Users/jw/Documents/wooteco/level2/jwp-racingcar/build/resources/main/data.sql]: CREATE TABLE RACE_RESULT ( `race_result_id` BIGINT ( 20 ) UNIQUE NOT NULL AUTO_INCREMENT, `trial_count` int NOT NULL, `winners` VARCHAR ( 50 ) NOT NULL, `created_at` DATETIME NOT NULL default current_timestamp, PRIMARY KEY ( `race_result_id` ) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE =utf8mb4_general_ci; nested exception is org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "RACE_RESULT" already exists; SQL statement:

๋Œ€์ถฉ ์ฝ์–ด๋ณด๋ฉด, ์ด๋ฏธ ํ…Œ์ด๋ธ”์ด ์กด์žฌํ•˜๋Š”๋ฐ ์™œ ๋˜ ํ…Œ์ด๋ธ”์„ ์ƒ์„ฑํ•˜๋ƒ๋Š” ๊ฒƒ์ด๋‹ค.

๋‹น์‹œ data.sql ํŒŒ์ผ์€ ์•„๋ž˜์™€ ๊ฐ™์ด ์ž‘์„ฑ๋˜์–ด ์žˆ์—ˆ๋‹ค.

CREATE TABLE RACE_RESULT
(
    `race_result_id` BIGINT(20) UNIQUE NOT NULL AUTO_INCREMENT,
    `trial_count`    int               NOT NULL,
    `winners`        VARCHAR(50)       NOT NULL,
    `created_at`     DATETIME          NOT NULL default current_timestamp,
    PRIMARY KEY (`race_result_id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_general_ci;

CREATE TABLE CAR
(
    `car_id`         BIGINT(20) UNIQUE NOT NULL AUTO_INCREMENT,
    `name`           VARCHAR(10)       NOT NULL,
    `position`       int               NOT NULL,
    `race_result_id` BIGINT(20),
    PRIMARY KEY (`car_id`),
    UNIQUE uk_car_name_race_result_id (`name`,`race_result_id`),
    FOREIGN KEY (`race_result_id`) REFERENCES RACE_RESULT (`race_result_id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_general_ci;

์‚ฌ์‹ค ์ฒ˜์Œ์—๋Š” ์™œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ๋Š”์ง€ ์ดํ•ดํ•  ์ˆ˜๊ฐ€ ์—†์—ˆ๋‹ค. 

๊ฐœ๋ณ„ ํ…Œ์ŠคํŠธ๋Š” ์ž˜ ๋Œ์•„๊ฐ”๊ธฐ ๋•Œ๋ฌธ์— ํ…Œ์ŠคํŠธ๋งˆ๋‹ค ํ…Œ์ด๋ธ”์„ ์ƒ์„ฑํ•˜๊ณ , ํ…Œ์ŠคํŠธ๊ฐ€ ๋๋‚˜๋ฉด ํ•ด๋‹น ํ…Œ์ด๋ธ”์€ drop ์‹œํ‚ค๋Š” ํ˜•ํƒœ์ด๊ธฐ ๋•Œ๋ฌธ์— ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธฐ์ง€ ์•Š์„ ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ–ˆ๋‹ค. + data.sql์ด ์ •ํ™•ํ•˜๊ฒŒ ๋ญ˜ ํ•˜๋Š” ์นœ๊ตฌ์ธ์ง€๋„ ์ดํ•ดํ•˜์ง€ ๋ชปํ–ˆ๋‹ค ๐Ÿ˜…

๊ทธ๋ž˜์„œ ์ด๋ฅผ ๊ณ„๊ธฐ๋กœ ํ•œ ๋ฒˆ ์ฐพ์•„๋ณด๊ณ ์ž ํ•œ๋‹ค.

 


 

โœ”๏ธ Spring Boot Data Initialization

์Šคํ”„๋ง ๋ถ€ํŠธ์—์„œ๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ดˆ๊ธฐํ™”๋ฅผ ์œ„ํ•œ ๋‹ค์–‘ํ•œ ๋ฐฉ๋ฒ•๋“ค์„ ์ œ๊ณตํ•œ๋‹ค.

์ด๋ฒˆ ๋ฏธ์…˜์—์„œ๋Š” ๊ธฐ๋ณธ SQL ์Šคํฌ๋ฆฝํŠธ๋ฅผ ํ™œ์šฉํ•˜์˜€์ง€๋งŒ, JPA๋ฅผ ํ™œ์šฉํ•  ๋•Œ๋Š” ์–ด๋–ป๊ฒŒ ํ•˜๋Š”์ง€ ๊ถ๊ธˆํ•ด์„œ ๊ฐ™์ด ์ž‘์„ฑํ•ด๋ณด๊ณ ์ž ํ•œ๋‹ค.

 

๐ŸŒฑ JPA / Hibernate

JPA๋Š” DDL์„ ์ƒ์„ฑํ•  ๋•Œ 2๊ฐ€์ง€ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜๋Š”๋ฐ, ์„œ๋ฒ„๊ฐ€ start ๋  ๋•Œ ํ•ด๋‹น ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์–ด๋–ค ์‹์œผ๋กœ ์—ฐ์‚ฐ์„ ์‹คํ–‰ํ• ์ง€ ์ง€์ •ํ•ด์ค„ ์ˆ˜ ์žˆ๋‹ค. application.yml (application.properties)์— ์ •์˜ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์˜ต์…˜์„ ์‚ฌ์šฉํ•œ๋‹ค.

spring.jpa.generate-ddl (boolean)
spring.jpa.hibernate.ddl-auto (enum)

generate-ddl์˜ ๊ฒฝ์šฐ spring.jpa.hibernate.ddl-auto ์†์„ฑ์„ ์‚ฌ์šฉํ• ์ง€ ๋ง์ง€ ๊ฒฐ์ •ํ•˜๋Š” ์˜ต์…˜ ๊ฐ’์ด๊ธฐ ๋•Œ๋ฌธ์— true, ํ˜น์€ false๋กœ ์ง€์ •ํ•ด์ค„ ์ˆ˜ ์žˆ๋‹ค. JPA๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ @Entity + @Table, @Column ๊ฐ™์€ ์–ด๋…ธํ…Œ์ด์…˜์„ ํ™œ์šฉํ•ด์„œ ์ง์ ‘ ํ…Œ์ด๋ธ” create ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ž‘์„ฑํ•˜์ง€ ์•Š๋”๋ผ๋„ ์ฝ”๋“œ์—์„œ ์„ค์ •ํ•œ ์ •๋ณด๋Œ€๋กœ ํ…Œ์ด๋ธ”์„ ์ƒ์„ฑํ•ด์ค„ ์ˆ˜ ์žˆ๋‹ค.

 

๋งŒ์•ฝ generate-ddl ๊ธฐ๋Šฅ์„ false๋กœ ํ•˜๊ฒŒ ๋œ๋‹ค๋ฉด ์ž๋™ ์ดˆ๊ธฐํ™”๋ฅผ ํ•˜์ง€ ์•Š๊ฒŒ ๋˜๋ฉฐ, true๋ฅผ ํ•˜๊ฒŒ ๋˜๋ฉด ์–ด๋–ค ์‹์œผ๋กœ ์ดˆ๊ธฐํ™”๋ฅผ ํ•  ๊ฑด์ง€ ddl-auto๋กœ ์„ค์ •ํ•œ๋‹ค. (๊ทผ๋ฐ ddl-auto๋ฅผ ์ง€์ •ํ•˜๊ฒŒ ๋˜๋ฉด generate-ddl์„ true๋กœ ๋ช…์‹œ์ ์œผ๋กœ ์ง€์ •ํ•˜์ง€ ์•Š์•„๋„ ์•Œ์•„์„œ ๋งŒ๋“ค์–ด์ฃผ๊ธฐ๋Š” ํ•œ๋‹ค.)

 

+ ์ž๋™ ์ดˆ๊ธฐํ™”๋ผ๊ณ  ํ•ด์„œ ์ข‹์„ ๊ฒƒ ๊ฐ™์ง€๋งŒ... ์šด์˜ ํ™˜๊ฒฝ์—์„œ๋Š” ๋Œ€๋ถ€๋ถ„ false๋กœ ํ•˜๋Š” ๊ฒŒ ์ข‹๋‹ค. (์˜ˆ์ƒ์น˜ ๋ชปํ•œ ๋ฒ„๊ทธ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜๋„ ์žˆ์Œ - ์ด๋ฏธ ์šด์˜ ์ค‘์ธ ์„œ๋น„์Šค์˜ db๋ฅผ ๊ฑด๋“œ๋Š” ๊ฑด ์‹ฌ๊ฐํ•œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค.) ์›ฌ๋งŒํ•˜๋ฉด DB ํ…Œ์ด๋ธ”์„ ๊ฑด๋“œ๋Š” ์ž‘์—…์€ ๊ทธ๋ƒฅ ์ง์ ‘ ํ…Œ์ด๋ธ”์— ์ฟผ๋ฆฌ๋ฅผ ๋‚ ๋ฆฌ๋Š” ๊ฒŒ ์ข‹๋‹ค๊ณ  ์ƒ๊ฐํ•œ๋‹ค. 

 

ddl-auto์˜ ๊ฒฝ์šฐ ์–ด๋–ค ์†์„ฑ์„ ์‚ฌ์šฉํ• ์ง€ ์ง€์ •ํ•ด์ค„ ์ˆ˜ ์žˆ๋‹ค.

update: ๊ธฐ์กด์˜ ์Šคํ‚ค๋งˆ๋ฅผ ์œ ์ง€ํ•˜๋ฉด์„œ ๋ณ€๊ฒฝ๋œ ๋ถ€๋ถ„์— ๋Œ€ํ•ด์„œ๋งŒ ์—…๋ฐ์ดํŠธ
validate: ์—”ํ‹ฐํ‹ฐ์™€ ํ…Œ์ด๋ธ”์ด ์ •์ƒ์ ์œผ๋กœ ๋งคํ•‘์ด ๋˜์—ˆ๋Š”์ง€๋งŒ ํ™•์ธ
create: ๊ธฐ์กด์— ์กด์žฌํ•˜๋Š” ์Šคํ‚ค๋งˆ๋ฅผ ์‚ญ์ œํ•˜๊ณ  ์ƒˆ๋กœ ์ƒ์„ฑ
create-drop: ์Šคํ‚ค๋งˆ๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ข…๋ฃŒ ์‹œ ์‚ญ์ œ 
none: ์•„๋ฌด๋Ÿฐ ์ดˆ๊ธฐํ™” ๋™์ž‘์„ ํ•˜์ง€ ์•Š์Œ

๊ฐœ์ธ์ ์œผ๋กœ ๋กœ์ปฌ ํ™˜๊ฒฝ์—์„œ๋Š” update, ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ์—์„œ๋Š” create-drop, ๊ฐœ๋ฐœ ํ™˜๊ฒฝ์—์„œ๋Š” validate ์ •๋„๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒŒ ์ข‹์„ ๊ฒƒ ๊ฐ™๋‹ค. ํŠนํžˆ create์˜ ๊ฒฝ์šฐ ์›ฌ๋งŒํ•˜๋ฉด ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๊ฒŒ ์ข‹๋‹ค. ์ฐธ๊ณ ๋กœ, ๊ธฐ๋ณธ๊ฐ’์˜ ๊ฒฝ์šฐ create-drop์ด๊ธฐ ๋•Œ๋ฌธ์— ๋งŒ์•ฝ ๋ณธ์ธ์ด ์ž‘์„ฑํ•œ ํ…Œ์ด๋ธ”์ด DB์— ๋ฐ˜์˜๋˜์ง€ ์•Š์•˜๋‹ค๋ฉด ํ•ด๋‹น ์˜ต์…˜์ด ์ง€์ •๋˜์–ด ์žˆ์ง€ ์•Š์€์ง€ ํ™•์ธํ•ด๋ณด์ž.

 

create๋‚˜ create-drop์œผ๋กœ ์˜ต์…˜์ด ์„ค์ •๋˜์–ด ์žˆ์„ ๊ฒฝ์šฐ, classpath์— ์กด์žฌํ•˜๋Š” import.sql์ด๋ผ๋Š” ํŒŒ์ผ์„ ์ฝ์–ด์„œ ์‹คํ–‰ํ•œ๋‹ค. ์ฐธ๊ณ ๋กœ ์ด๊ฑด Spring์ด๋ž‘ ๊ด€๋ จ ์—†์ด Hibernate์˜ ๊ธฐ๋Šฅ์ด๋ผ๊ณ  ํ•œ๋‹ค. (ํ…Œ์ŠคํŠธํ•  ๋•Œ ์กฐ์‹ฌํ•˜๋ผ๊ณ  ์ ํ˜€์žˆ๋‹ค...)

 

+ JDBC์—์„œ๋Š” JDBC url์— ๋‚˜ํƒ€๋‚œ Connection type์— ๋”ฐ๋ผ์„œ ๊ฐ์ง€ํ•œ๋‹ค๊ณ  ํ•œ๋‹ค.

 


 

๐ŸŒฑ Basic SQL Scripts

์Šคํ”„๋ง ๋ถ€ํŠธ๋Š” JDBC DataSource๋‚˜ R2DBC ConnectionFactory์˜ DDL script๋ฅผ ํ†ตํ•ด ์Šคํ‚ค๋งˆ๋ฅผ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•˜๊ณ , DML script๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ์ด๋ฅผ ์ดˆ๊ธฐํ™”ํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๋•Œ, ์ด๋Ÿฌํ•œ ์ดˆ๊ธฐํ™” ๊ณผ์ •์€ classpath์— ์กด์žฌํ•˜๋Š” schema.sql๊ณผ data.sql์„ ํ†ตํ•ด ๋กœ๋“œ๋œ๋‹ค! ๋ณดํ†ต ํ…Œ์ด๋ธ” ์ƒ์„ฑ ๊ฐ™์€ DDL์˜ ๊ฒฝ์šฐ schema.sql์„, CRUD ๊ฐ™์€ ๊ธฐ๋Šฅ์€ data.sql์„ ํ™œ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ •์„์ด๋‹ค.

 

๊ผญ ์ด๋ฆ„์ด ์ด๋ ‡๊ฒŒ ์ง€์ •๋  ํ•„์š”๋Š” ์—†์œผ๋ฉฐ, ์Šคํ”„๋ง๋ถ€ํŠธ๋Š” schema-${platform}.sql์ด๋‚˜ data-${platform}.sql์„ ์ฐพ์•„์„œ ์ฝ๋Š”๋‹ค.

platform ๊ฐ’์˜ ๊ฒฝ์šฐ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ application.yml์˜ spring.sql.init.platform ์˜ต์…˜์„ ํ†ตํ•ด ์ง€์ •์ด ๊ฐ€๋Šฅํ•˜๋ฉฐ, ํŠน์ • ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ™˜๊ฒฝ์— ๋Œ€ํ•ด์„œ ๋‹ค๋ฅธ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ํ™œ์šฉํ•˜๊ณ  ์‹ถ์„ ๋•Œ ์œ ์šฉํ•˜๋‹ค. (๋ฌธ๋ฒ•์ด ๋‹ค๋ฅผ ๊ฒฝ์šฐ)

 

ex) spring.sql.init.platform=postgresql => schema-postgresql.sql์— ๋งค์นญ!

 

์•„๋งˆ ์ด๋Ÿฐ ์‹์œผ๋กœ ์‚ฌ์šฉํ•˜์ง€ ์•Š์„๊นŒ ์˜ˆ์ƒ๋œ๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ ์ด๋Ÿฌํ•œ DB ์ดˆ๊ธฐํ™”๋Š” in-memory db๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ๋งŒ ๊ฐ€๋Šฅํ•˜๊ธฐ ๋•Œ๋ฌธ์—, MySQL ๊ฐ™์€ ๋‹ค๋ฅธ ๋ฐ์ด๋ฒ„ํ…Œ์ด์Šค์—์„œ๋„ ์ ์šฉํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด spring.sql.init.mode = always์™€ ๊ฐ™์ด ์„ค์ •ํ•ด์•ผ ํ•œ๋‹ค. ๋ฌผ๋ก , in-memory db์—์„œ๋„ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ์ง€ ์•Š๋‹ค๋ฉด spring.sql.init.mode=never๋กœ ์„ค์ •ํ•˜๋ฉด ๋œ๋‹ค. 

 

๋งŒ์•ฝ ์ž‘์„ฑํ•œ ์Šคํฌ๋ฆฝํŠธ์— ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค๋ฉด, ์„œ๋ฒ„๋Š” ์‹œ์ž‘๋˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ์ด๋Ÿฌํ•œ ๊ฒƒ์— ๋Œ€ํ•ด์„œ๋„ ์กฐ์ •ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด spring.sql.init.continue-on-error๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ œ์–ดํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์ด false์ด๊ธฐ ๋•Œ๋ฌธ์—, ์Šคํฌ๋ฆฝํŠธ์— ์ƒ๊ด€์—†์ด ์„œ๋ฒ„๊ฐ€ ์‹คํ–‰๋˜๊ธฐ๋ฅผ ์›ํ•œ๋‹ค๋ฉด ํ•ด๋‹น ์˜ต์…˜์„ true๋กœ ์„ค์ •ํ•˜์ž.

 


๐ŸŒฑ Hibernate + Script

๋งŒ์•ฝ hibernate ๊ธฐ๋ฐ˜ ์ดˆ๊ธฐํ™”์™€ script ๊ธฐ๋ฐ˜ ์ดˆ๊ธฐํ™”๋ฅผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๋ ค๊ณ  ํ•˜๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผ ํ• ๊นŒ? 

๋ฌผ๋ก , ๋ฒ ์ŠคํŠธ๋Š” ๊ฐ™์ด ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์ด ์ข‹๋‹ค. ํŠนํžˆ FlyWay ๊ฐ™์€ ๊ฒƒ๊ณผ ๊ฐ™์ด ์‚ฌ์šฉํ•˜๋Š” ๊ฑด ์™„์ „ ์ถ”์ฒœํ•˜์ง€ ์•Š๋Š”๋‹ค. (ํ–ฅํ›„ ๋ฆด๋ฆฌ์ฆˆ์—์„œ ์ œ๊ฑฐ๋  ์˜ˆ์ •์ด๋ผ๊ณ  ํ•œ๋‹ค.)

 

๊ธฐ๋ณธ์ ์œผ๋กœ ์Šคํฌ๋ฆฝํŠธ ๊ธฐ๋ฐ˜์˜ DataSource ์ดˆ๊ธฐํ™”๋Š” JPA EntityManagerFactory ๋นˆ์ด ์ƒ์„ฑ๋˜๊ธฐ ์ „์— ์ˆ˜ํ–‰๋œ๋‹ค.

๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์—, ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‹คํ–‰ํ•œ ๋‹ค์Œ ddl-auto ์˜ต์…˜์ด ์ ์šฉ๋˜์–ด ๋งŒ์•ฝ ddl-auto๊ฐ€ create, create-drop์ด๋ผ๋ฉด ์Šคํฌ๋ฆฝํŠธ๋ฅผ ํ†ตํ•ด ์ƒ์„ฑํ–ˆ๋˜ ํ…Œ์ด๋ธ”๋“ค์ด drop ๋˜๊ณ  ๋‹ค์‹œ ์ƒ์„ฑ๋  ์ˆ˜๋„ ์žˆ๋‹ค.

 

ํ•˜์ง€๋งŒ, spring.jpa.defer-datasource-initialization=true๋กœ ์„ค์ •ํ•˜๊ฒŒ ๋œ๋‹ค๋ฉด, DataSource์— ๋Œ€ํ•œ ์ดˆ๊ธฐํ™”๋ฅผ EntityManagerFactory ๋นˆ์ด ์ƒ์„ฑ๋˜๊ณ  ์ดˆ๊ธฐํ™”๋  ๋•Œ๊นŒ์ง€ ์ง€์—ฐ๋œ๋‹ค. 

 

๊ถ๊ธˆํ•ด์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์‹คํ—˜์„ ํ•ด๋ณด์•˜๋‹ค.

@Entity
@Table(name = "user")
public class User {
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "user_id")
    private Long id;

    @Column(name = "user_name", unique = true, nullable = false)
    private String name;
}

๊ฐ„๋‹จํ•œ User๋ผ๋Š” ์—”ํ‹ฐํ‹ฐ๋ฅผ ์ƒ์„ฑํ•˜์˜€๋‹ค.

 

schema.sql

CREATE TABLE user
(
    user_id   BIGINT(20)          NOT NULL AUTO_INCREMENT,
    user_name varchar(255) UNIQUE NOT NULL,
    PRIMARY KEY (user_id)
) ENGINE = InnoDB
  DEFAULT CHARSET = utf8mb4
  COLLATE = utf8mb4_general_ci;

์—”ํ‹ฐํ‹ฐ์™€ ๋™์ผํ•œ ์Šคํ‚ค๋งˆ๋ฅผ ๊ฐ€์ง€๋„๋ก ํ…Œ์ด๋ธ” ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ž‘์„ฑํ•˜์˜€๋‹ค.

 

application.yml

spring:
  datasource:
    // db ์„ค์ •
  sql:
    init:
      mode: always
  jpa:
    hibernate:
      ddl-auto: create
    show-sql: true
    defer-datasource-initialization: true

๊ณผ์—ฐ ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์ •์ƒ์ ์œผ๋กœ ์ž‘๋™๋ ๊นŒ? 

 

 

๐Ÿ’ฌ ddl-auto: create + schema.sql + defer-datasource-initialization: true

์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.

EntityManagerFactory์ด ๋จผ์ € ์ƒ์„ฑ๋˜๊ณ  ์ดˆ๊ธฐํ™”๊ฐ€ ๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์—, @Entity๊ฐ€ ๋ถ™์€ ํด๋ž˜์Šค์˜ ์ •๋ณด์— ๋”ฐ๋ผ์„œ ํ…Œ์ด๋ธ”์„ ์ƒ์„ฑํ–ˆ์„ ๊ฒƒ์ด๋‹ค. ๊ทธ๋ฆฌ๊ณ , ๊ทธ ๋‹ค์Œ schema.sql์— ์žˆ๋Š” ๋‚ด์šฉ์œผ๋กœ ํ…Œ์ด๋ธ”์„ ์ดˆ๊ธฐํ™”ํ•˜๋ ค๊ณ  ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ด๋ฏธ ํ…Œ์ด๋ธ”์ด ์กด์žฌํ•œ๋‹ค๋ฉด ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•œ ๊ฒƒ์ด๋‹ค.

 

 

๐Ÿ’ฌ ddl-auto: create + schema.sql + defer-datasource-initialization: false

๊ทธ๋ ‡๋‹ค๋ฉด, defer-datasource-initialization ์˜ต์…˜์„ ๋„๋ฉด ์–ด๋–ป๊ฒŒ ๋™์ž‘ํ• ๊นŒ?

์˜ต์…˜์„ ๋„๋ฉด ์ •์ƒ์ ์œผ๋กœ ์‹คํ–‰์€ ๋œ๋‹ค.

๋‹ค๋งŒ, schema.sql์„ ํ†ตํ•ด ์ƒ์„ฑ๋œ ํ…Œ์ด๋ธ”์„ ๋จผ์ € drop ์‹œํ‚ค๊ณ  ddl-auto๋ฅผ ํ†ตํ•ด ์ƒˆ๋กญ๊ฒŒ ํ…Œ์ด๋ธ”์ด ์ƒ์„ฑ๋œ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

 

๊ทธ๋Ÿผ, ์ด ์ƒํ™ฉ์—์„œ data.sql์„ ์ถ”๊ฐ€ํ•ด๋ณด์ž.

 

data.sql

INSERT INTO user(user_name) VALUES ('ํ…Œ์ŠคํŠธ์ด๋ฆ„');

 

๐Ÿ’ฌ ddl-auto: create + schema.sql + data.sql + defer-datasource-initialization: false

๊ฒฐ๊ณผ๋ฅผ ๋ณด์ž. ์•„๋ฌด๊ฒƒ๋„ ์‚ฝ์ž…์ด ๋˜์ง€ ์•Š์€ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

์œ„์—์„œ ๋งํ–ˆ๋˜ ๊ฒƒ์ฒ˜๋Ÿผ, ์˜ต์…˜์„ ๋ˆ ์ƒํƒœ์ด๊ธฐ ๋•Œ๋ฌธ์— datasource์— ๋Œ€ํ•ด์„œ ๋จผ์ € ์ดˆ๊ธฐํ™”๋˜์–ด ํ…Œ์ด๋ธ” ์ƒ์„ฑ ํ›„ insert๊นŒ์ง€ ์ง„ํ–‰ํ•˜์ง€๋งŒ, ddl-auto๋กœ ์ธํ•ด์„œ ๋‹ค์‹œ ๊ธฐ์กด์— ์žˆ๋˜ ํ…Œ์ด๋ธ”์ด drop ๋˜๊ณ  ์žฌ์ƒ์„ฑ๋˜๊ธฐ ๋•Œ๋ฌธ์— ๋ฐ์ดํ„ฐ๊ฐ€ ์‚ฌ๋ผ์ง€๊ฒŒ ๋œ๋‹ค.

 

๊ทธ๋ ‡๋‹ค๋ฉด, ์˜ต์…˜์„ ๋‹ค์‹œ true๋กœ ์„ค์ •ํ•˜๊ณ  ์˜ค๋ฅ˜ ๋ฐœ์ƒ์„ ๋ง‰๊ธฐ ์œ„ํ•ด schema.sql์„ ์ œ๊ฑฐํ•˜์ž.

 

 

๐Ÿ’ฌ ddl-auto: create + data.sql + defer-datasource-initialization: true

์‚ฌ์‹ค ๊ฐ€์žฅ ๋งŽ์ด ์‚ฌ์šฉํ•˜๋Š” ์˜ˆ์‹œ์ผ ๊ฒƒ ๊ฐ™๋‹ค. (๋กœ์ปฌ ํ™˜๊ฒฝ์—์„œ)

๊ฐ„ํŽธํ•˜๊ฒŒ ํ…Œ์ด๋ธ” ์ƒ์„ฑ ํ›„, ์ƒ˜ํ”Œ ๋ฐ์ดํ„ฐ๋ฅผ insert ํ•ด์•ผ ํ•˜๋Š” ์ƒํ™ฉ์ด๋ผ๋ฉด ์œ„์™€ ๊ฐ™์ด ํ™œ์šฉํ•˜๋ฉด ์ข‹์„ ๊ฒƒ ๊ฐ™๋‹ค.

 


 

๐ŸŒฑ ๊ทธ๋ ‡๋‹ค๋ฉด ์ฒ˜์Œ์˜ ๋ฌธ์ œ ์ƒํ™ฉ์€ ์™œ?

์ด๊ฑด ๊ฐœ์ธ์ ์ธ ์ƒ๊ฐ์ด๋ผ ์กฐ๊ธˆ ๋” ์ƒ๊ฐ์ด ์ •๋ฆฌ๋˜๋ฉด ์ˆ˜์ •ํ•  ์˜ˆ์ •์ด๋‹ค. (์•„์ง ํ…Œ์ŠคํŠธ ์ชฝ์˜ ์ •ํ™•ํ•œ ๋™์ž‘ ์›๋ฆฌ๋ฅผ ๋ชจ๋ฅด๊ฒ ๋‹ค...)

 

@SpringBootTest์˜ ๊ฒฝ์šฐ ์‹ค์ œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์˜ฌ๋ฆฌ๊ธฐ ๋•Œ๋ฌธ์— ๋™์ผํ•˜๊ฒŒ data.sql์ด ๋จผ์ € ์ฝ์–ด์™€์„œ ํ…Œ์ด๋ธ”์„ ์ƒ์„ฑํ•˜์˜€์„ ๊ฒƒ์ด๋‹ค.

ํ•˜์ง€๋งŒ ํ…Œ์ŠคํŠธ๋งˆ๋‹ค ์„œ๋ฒ„๋ฅผ ๋„์šฐ๋”๋ผ๋„ ๋ฐ”๋ผ๋ณด๊ณ  ์žˆ๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ž์ฒด๋Š” ๋™์ผํ•  ๊ฒƒ์ด๊ณ  (h2), ํ…Œ์ŠคํŠธ๋Š” ๋™์‹œ์— ์‹คํ–‰๋œ๋‹ค.

 

๊ทธ๋ž˜์„œ @SpringBootTest๊ฐ€ ๋ถ™์€ ์–ด๋–ค ํ…Œ์ŠคํŠธ์—์„œ ์„œ๋ฒ„๋ฅผ ๋„์šฐ๋ฉฐ data.sql์„ ํ†ตํ•ด ํ…Œ์ด๋ธ”์„ ์ƒ์„ฑํ–ˆ๋Š”๋ฐ, ๋˜ ๋‹ค๋ฅธ @SpringBootTest๊ฐ€ ๋ถ™์€ ํ…Œ์ŠคํŠธ๊ฐ€ ์„œ๋ฒ„๋ฅผ ๋„์šฐ๋ฉฐ data.sql์„ ์ฝ์–ด ํ…Œ์ด๋ธ”์„ ์ƒ์„ฑํ•˜๋ ค๊ณ  ๋‚˜๋‹ˆ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ๋˜ ๊ฒŒ ์•„๋‹๊นŒ ์‹ถ๋‹ค.

(๋ณดํ†ต์€ ํ…Œ์ด๋ธ” ์ƒ์„ฑ ์ž์ฒด๋ฅผ ํ…Œ์ŠคํŠธํ•˜๊ธฐ ๋ณด๋‹จ, ํ…Œ์ŠคํŠธ ๋…๋ฆฝ์„ฑ์€ ๋กค๋ฐฑ์„ ํ†ตํ•ด ์ƒ์„ฑ๋œ ํ…Œ์ด๋ธ”์˜ ์ปฌ๋Ÿผ์ด ๋‚จ์ง€ ์•Š๋„๋ก ํ•˜๋Š” ๊ฒŒ ์ผ๋ฐ˜์ ์ด๋‹ˆ๊นŒ...)

 

๊ฐ“ ๋ง๋ž‘์ด๋ž‘ ๋Œ€ํ™”๋ฅผ ๋‚˜๋ˆ„๊ณ  ์ƒ๊ฐ์ด ์ •๋ฆฌ๋˜์—ˆ๋‹ค.

Spring Boot์—์„œ ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ์„ ๊ตฌ์ถ•ํ•  ๋•Œ bean์ด ์—ฌ๋Ÿฌ ๊ฐœ๊ฐ€ ๋“ฑ๋ก๋œ๋‹ค๋ฉด ApplicationContext๊ฐ€ ํ•„์š”ํ•˜๊ณ , ApplicationContext๋Š” ๊ณง ํ…Œ์ŠคํŠธ์—์„œ ์‚ฌ์šฉ๋˜๋Š” bean์œผ๋กœ ๊ตฌ์„ฑ๋œ๋‹ค. ์ด๋•Œ, ํ…Œ์ŠคํŠธ๋งˆ๋‹ค ์ƒˆ๋กœ์šด ApplicationContext๋ฅผ ์ƒ์„ฑํ•œ๋‹ค๋ฉด ๋‹น์—ฐํžˆ ์„ฑ๋Šฅ์ ์œผ๋กœ ์ข‹์ง€ ์•Š์„ ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์—, ๊ฐ™์€ bean์„ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ ์˜ค์—ผ๋˜์ง€ ์•Š์•˜์„ ๊ฒฝ์šฐ ์บ์‹ฑ์„ ํ•˜๊ฒŒ ๋œ๋‹ค. (์บ์‹ฑ์— ๋Œ€ํ•ด์„œ๋„ ํ•œ ๋ฒˆ ์ฐพ์•„๋ด์•ผ๊ฒ ๋‹ค.)

 

๊ทธ๋ž˜์„œ @SpringBootTest ์ž์ฒด์˜ ๋ฌธ์ œ๋ผ๊ธฐ๋ณด๋‹จ, ํ…Œ์ŠคํŠธ์—์„œ ํ•„์š”ํ•œ ๋นˆ์ด ๋‹ฌ๋ผ์กŒ๋‹ค๋“ ์ง€, mock ๋“ฑ์„ ํ†ตํ•œ ์˜ค์—ผ์œผ๋กœ ์ธํ•ด ๊ธฐ์กด์˜ db๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Œ์—๋„ ์ƒˆ๋กœ์šด ApplicationContext๋ฅผ ๊ตฌ์„ฑํ•˜๋Š” ๊ฒฝ์šฐ data.sql์„ ํ•œ ๋ฒˆ ๋” ์ฝ์œผ๋ฉด์„œ ๋™์ผํ•œ db์— ํ•œ ๋ฒˆ ๋” ํ…Œ์ด๋ธ”์„ create ํ•˜๋ฉด์„œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ๋˜ ๊ฒƒ์œผ๋กœ ์ถ”์ธก๋œ๋‹ค!

 

CREATE TABLE IF NOT EXISTS RACE_RESULT
(
    `race_result_id` BIGINT(20) UNIQUE NOT NULL AUTO_INCREMENT,
    `trial_count`    int               NOT NULL,
    `winners`        VARCHAR(50)       NOT NULL,
    `created_at`     DATETIME          NOT NULL default current_timestamp,
    PRIMARY KEY (`race_result_id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_general_ci;

CREATE TABLE IF NOT EXISTS CAR
(
    `car_id`         BIGINT(20) UNIQUE NOT NULL AUTO_INCREMENT,
    `name`           VARCHAR(10)       NOT NULL,
    `position`       int               NOT NULL,
    `race_result_id` BIGINT(20),
    PRIMARY KEY (`car_id`),
    UNIQUE uk_car_name_race_result_id (`name`,`race_result_id`),
    FOREIGN KEY (`race_result_id`) REFERENCES RACE_RESULT (`race_result_id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_general_ci;

๊ทธ๋ž˜์„œ ๊ฒฐ๊ณผ์ ์œผ๋กœ๋Š” IF NOT EXISTS๋ฅผ ๋ถ™์—ฌ์ฃผ์–ด, ์ด๋ฏธ ํ…Œ์ด๋ธ”์ด ์กด์žฌํ•  ๊ฒฝ์šฐ ์ƒ์„ฑํ•˜์ง€ ์•Š๋„๋ก ๋งŒ๋“ค์–ด์ฃผ์—ˆ๋‹ค.

 

์—ญ์‹œ Spring์— ๋Œ€ํ•ด ์•„์ง ๋ชจ๋ฅด๋Š” ๊ฒŒ ๋„ˆ๋ฌด ๋งŽ๋‹ค...

์—ด์‹ฌํžˆ ๊ณต๋ถ€ํ•ด์•ผ๊ฒ ๋‹ค!

Comments