๊นจ์•Œ ๊ฐœ๋… ๐Ÿ“‘/Android

[Android] Room - AutoMigration ๊ธฐ์ดˆ

interfacer_han 2024. 5. 6. 21:00

Room ๊ฒŒ์‹œ๊ธ€ ์‹œ๋ฆฌ์ฆˆ


#1 ๊ฐœ์š”

#1-1 ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์Šคํ‚ค๋งˆ (Database Schema)

 

[Android] Room - Entity, DAO, Database

#1 ์ด์ „ ๊ธ€ [Android] Room - ๊ธฐ์ดˆ, INSERT์™€ DELETE ์—ฐ์Šต #1 Room ์†Œ๊ฐœ Room์„ ์‚ฌ์šฉํ•˜์—ฌ ๋กœ์ปฌ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋ฐ์ดํ„ฐ ์ €์žฅ | Android Developers Room ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋” ์‰ฝ๊ฒŒ ๋ฐ์ดํ„ฐ๋ฅผ ์œ ์ง€ํ•˜๋Š” ๋ฐฉ๋ฒ• ์•Œ์•„๋ณด

kenel.tistory.com

๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์Šคํ‚ค๋งˆ๋Š” Table์˜ ๊ฐฏ์ˆ˜๋‚˜ ๊ฐ ํ…Œ์ด๋ธ”์— ์žˆ๋Š” Column์˜ ๊ฐฏ์ˆ˜์™€ ํƒ€์ž… ๋“ฑ์„ ์˜๋ฏธํ•œ๋‹ค. ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์œ ์ง€๋ณด์ˆ˜ํ•˜๋‹ค๊ฐ€, ์–ด๋–ค Table์— ์ƒˆ๋กœ์šด Column์„ ์ถ”๊ฐ€ํ•ด์•ผํ•  ํ•„์š”์„ฑ์ด ์ƒ๊ฒผ๋‹ค๊ณ  ํ•ด๋ณด์ž. ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ Room์œผ๋กœ ๊ตฌํ˜„ํ–ˆ๋‹ค๋ฉด, @Entity์— ์ƒˆ๋กœ์šด @ColumnInfo๋ฅผ ์ถ”๊ฐ€ํ–ˆ์„ ๊ฒƒ์ด๋‹ค. ๋˜, @Database์˜ version ์†์„ฑ์˜ ๊ฐ’๋„ +1 ํ•ด์ฃผ์—ˆ์„ ๊ฒƒ์ด๋‹ค. (์œ„ ๊ฒŒ์‹œ๊ธ€ ์ฐธ์กฐ)
 

#1-2 ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์Šคํ‚ค๋งˆ ๋ณ€๊ฒฝ์˜ ์–ด๋ ค์›€

ํ•˜์ง€๋งŒ, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์Šคํ‚ค๋งˆ๋ฅผ ์•„๋ฌด ๋Œ€์ฑ…์—†์ด ๋ณ€๊ฒฝํ•˜๋ฉด (์ƒˆ๋กœ ์ถ”๊ฐ€ํ•œ ์ปฌ๋Ÿผ 1์— null์ด ๋“ค์–ด๊ฐ€๋ฉด ์•ˆ๋˜๋Š” ๊ฒฝ์šฐ) ์œ„์™€ ๊ฐ™์ด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ๋ฌด๊ฒฐ์„ฑ์ด ๊นจ์งˆ ์ˆ˜ ์žˆ๋‹ค. ์ด๋•Œ, ๋ฌด๊ฒฐ์„ฑ์„ ์œ ์ง€ํ•˜๋Š” ์‰ฝ๊ณ  ๊ฐ„ํŽธํ•œ ๋Œ€์ฑ…์œผ๋กœ ์“ธ๋งŒํ•œ ๊ฒƒ์ด Room์˜ AutoMigration ๊ธฐ๋Šฅ์ด๋‹ค.
 

#1-3 AutoMigration์˜ ์—ญํ• 

AutoMigration์€ ๋ง ๊ทธ๋Œ€๋กœ ์ž๋™(auto)์œผ๋กœ, ์Šคํ‚ค๋งˆ ๋ฒ„์ „์„ ์ด์ฃผ(migration)์‹œ์ผœ์ฃผ๋Š” ๊ธฐ๋Šฅ์ด๋‹ค. ์•Œ์•„์„œ ์ตœ์‹  ๋ฒ„์ „์˜ ์Šคํ‚ค๋งˆ์™€ ๊ทธ ์ง์ „ ๋ฒ„์ „์˜ ์Šคํ‚ค๋งˆ๋ฅผ ๋น„๊ตํ•˜์—ฌ ๋ฌด๊ฒฐ์„ฑ์ด ๊นจ์งˆ๋งŒํ•œ ๋ถ€๋ถ„์„ ์•Œ์•„์„œ ๋ณด์™„ํ•œ๋‹ค. ํ”„๋กœ๊ทธ๋ž˜๋จธ๊ฐ€ ๋จธ๋ฆฌ๋ฅผ ์ฅ์–ด๋œฏ์œผ๋ฉฐ SQL๋ฌธ์„ ์ณ์ค„ ํ•„์š”๊ฐ€ ์—†๋‹ค. ์ฐธ๊ณ ๋กœ, AutoMigration์€ 2.4.0-alpha01 ๋ฒ„์ „ ์ด์ƒ์˜ Room์—์„œ๋งŒ ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.
 

#2 AutoMigration ์‚ฌ์šฉํ•˜๊ธฐ

#2-1 ์กฐ๊ฑด

Room์ด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์Šคํ‚ค๋งˆ์˜ ๋ณ€๊ฒฝ์„ ๊ฐ์ง€ํ•˜๋ฉด์„œ, ๋™์‹œ์— ์ตœ์‹  ๋ฒ„์ „์˜ ์Šคํ‚ค๋งˆ์™€ ๊ทธ ์ง์ „ ๋ฒ„์ „์˜ ์Šคํ‚ค๋งˆ๋ฅผ ๋น„๊ตํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•œ๋‹ค. ๊ทธ๋ ‡๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด์„  ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์Šคํ‚ค๋งˆ๋ฅผ ๋ฒ„์ „ ๋ณ„๋กœ ๊ด€๋ฆฌํ•  ํ•„์š”๊ฐ€ ์žˆ๋‹ค. @Database ์–ด๋…ธํ…Œ์ด์…˜์˜ ์†์„ฑ exportSchema๋ฅผ true๋กœ ์„ค์ •ํ•˜๊ณ  (๊ธฐ๋ณธ๊ฐ’๋„ true๊ธด ํ•˜๋‹ค), ๋ฒ„์ „ ๋ณ„ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์Šคํ‚ค๋งˆ๊ฐ€ ์ €์žฅ๋  ๊ณต๊ฐ„๋„ ๋ช…์‹œ์ ์œผ๋กœ ์„ค์ •ํ•ด์ค€๋‹ค. ๊ทธ๋ฆฌ๊ณ  AutoMigration์ด ์ง„ํ–‰๋  ์ด์ „ ๋ฒ„์ „๊ณผ ์ดํ›„ ๋ฒ„์ „์„ ๋ช…์‹œํ•œ๋‹ค. ๋งˆ์ง€๋ง‰์œผ๋กœ, AutoMigration์„ ์–ด๋–ป๊ฒŒ ์ง„ํ–‰ํ•  ๊ฒƒ์ธ๊ฐ€๋ฅผ ์„ค์ •ํ•œ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ์–ด๋–ค ํ…Œ์ด๋ธ”์— ์ƒˆ๋กœ์šด Column์„ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒฝ์šฐ๋ผ๋ฉด, ํ•ด๋‹น Column์— ๋Œ€์‘๋˜๋Š” @ColumnInfo์˜ ์†์„ฑ defaultValue๋ฅผ ํŠน์ • ๊ฐ’์œผ๋กœ ์ดˆ๊ธฐํ™” ํ•จ์œผ๋กœ์จ, ํ•ด๋‹น ์ปฌ๋Ÿผ ์ถ”๊ฐ€ ์ „์— ์‚ฝ์ž…๋˜์–ด์žˆ๋˜ Record๋“ค์ด ํ•ด๋‹น defaultValue๋ฅผ ๋”ฐ๋ฅด๋„๋ก ๋งŒ๋“ ๋‹ค.
 

#2-2 ์ˆ˜์ •ํ•  ์•ฑ

 

[Android] Room - ๊ธฐ์ดˆ, INSERT์™€ DELETE ์—ฐ์Šต

#1 Room ์†Œ๊ฐœ Room์„ ์‚ฌ์šฉํ•˜์—ฌ ๋กœ์ปฌ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋ฐ์ดํ„ฐ ์ €์žฅ | Android Developers Room ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋” ์‰ฝ๊ฒŒ ๋ฐ์ดํ„ฐ๋ฅผ ์œ ์ง€ํ•˜๋Š” ๋ฐฉ๋ฒ• ์•Œ์•„๋ณด๊ธฐ developer.android.com SQLite๋Š” ๋ชจ๋ฐ”์ผ ๊ธฐ๊ธฐ๋ฅผ ์œ„ํ•œ

kenel.tistory.com

์œ„ ๊ฒŒ์‹œ๊ธ€์˜ ์™„์„ฑ๋œ ์•ฑ์„ ๊ธฐ๋ฐ˜์œผ๋กœ, AutoMigration์„ ์ง„ํ–‰ํ•ด๋ณธ๋‹ค.
 

#2-3 ๊ตฌ๋ฒ„์ „ ์Šคํ‚ค๋งˆ์— Record ๋„ฃ๊ธฐ

๋จผ์ €, EditText์— ๊ฐ’์„ ์ž…๋ ฅํ•˜๊ณ  Button์„ ๋ˆŒ๋Ÿฌ์„œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— Record๋ฅผ ์ ๋‹นํžˆ ๋„ฃ์–ด๋‘์ž. ํ•˜๋‹จ Bar์— ์žˆ๋Š” [App Inspection]์„ ํด๋ฆญํ•ด์„œ ๋“ค์–ด๊ฐ„ Record๋ฅผ ๊ฐ„ํŽธํ•˜๊ฒŒ ๊ตฌ๊ฒฝํ•  ์ˆ˜ ์žˆ๋‹ค. AutoMigration์ด ์ง„ํ–‰๋  ๋•Œ ์ด Record๊ฐ€ ์–ด๋–ป๊ฒŒ ๋ณ€๊ฒฝ๋˜๋Š”์ง€ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•œ ์ž‘์—…์ด๋‹ค.
 

#2-4 @Database์˜ ์†์„ฑ exportSchema๋ฅผ true๋กœ ์„ค์ • (UserDatabse.kt)

...

@Database(
    entities = [User::class],
    version = 1,
    exportSchema = true,
)
abstract class UserDatabase : RoomDatabase() {

    ...
}

@Database ์†์„ฑ๋“ค์„ ์„ค๋ช…ํ•˜๋Š” ๊ณต์‹ ๋ฌธ์„œ
 

#2-5 ๋ชจ๋“ˆ ์ˆ˜์ค€ build.gradle์— room.schemaLocation ๋””๋ ‰ํ† ๋ฆฌ ์„ค์ •

plugins {
    ...
}

android {
    ...

    defaultConfig {
        ...
    }

    kapt {
        arguments {
            arg("room.schemaLocation", "$projectDir/schemas")
        }
    }

    buildTypes {
        ...
    }
    compileOptions {
        ...
    }
    kotlinOptions {
        ...
    }
    
    ...
}

dependencies {

    ...
}

room์€ ์–ด๋…ธํ…Œ์ด์…˜(@)์— ๊ธฐ๋ฐ˜ํ•˜์—ฌ ์ž‘๋™ํ•œ๋‹ค. ๋”ฐ๋ผ์„œ, ์–ด๋…ธํ…Œ์ด์…˜ ์ฒ˜๋ฆฌ๊ธฐ์— ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์Šคํ‚ค๋งˆ๋ฅผ ์ €์žฅํ•  ๊ณต๊ฐ„์˜ ์ฃผ์†Œ(value)๋ฅผ ์•Œ๋ ค์ค€๋‹ค. ํ•ด๋‹น value์˜ ํ‚ค๋Š” "room.schemaLocation"์ด๋‹ค.
 

#2-6 ํ”„๋กœ์ ํŠธ ๋นŒ๋“œ

ํ”„๋กœ์ ํŠธ๋ฅผ ์ปดํŒŒ์ผํ•ด์•ผ ๋น„๋กœ์†Œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์Šคํ‚ค๋งˆ๊ฐ€ ์ƒ๊ธด๋‹ค. ๋”ฐ๋ผ์„œ, ์šฐ์„  ์ปดํŒŒ์ผ(๊ทธ๋ƒฅ ์•ฑ์„ ์‹คํ–‰์‹œํ‚ค๋ฉด ๋œ๋‹ค)ํ•ด์„œ ๊ตฌ๋ฒ„์ „์˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์Šคํ‚ค๋งˆ๋ฅผ ์ €์žฅํ•œ๋‹ค. #2-1์—์„œ AutoMigration์€ ๋น„๊ตํ•  ์ˆ˜ ์žˆ์–ด์•ผ ๋™์ž‘๋œ๋‹ค๊ณ  ํ–ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๊ตฌ๋ฒ„์ „์˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์Šคํ‚ค๋งˆ๋ฅผ ์šฐ์„  ์ €์žฅํ•ด๋‘๋Š” ๊ฒƒ์ด๋‹ค. ํ•ด๋‹น ํŒŒ์ผ์€ ์™ผ์ชฝ Bar์˜ ๋ณด๊ธฐ ๋ชจ๋“œ๋ฅผ [Andorid]์—์„œ [Project Files]๋กœ ๋ณ€๊ฒฝํ•ด์•ผ ๋ณด์ธ๋‹ค.
 

#2-7 ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์Šคํ‚ค๋งˆ ๋ณ€๊ฒฝ ๋ฐ AutoMigration์˜ ํ๋ฆ„ ์„ค์ • (User.kt)

...

@Entity(tableName = "user_data_table")
data class User(

   ...

    @ColumnInfo(name = "user_age", defaultValue = "-1")
    var age: Int
)

์ƒˆ Column์„ ์ถ”๊ฐ€ํ•œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ธฐ๋ณธ๊ฐ’์„ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์œผ๋กœ AutoMigration์˜ ํ๋ฆ„์„ ์ง€์ •ํ•œ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ ์‹ ์ค‘ํ•˜๊ฒŒ ์„ค์ •ํ•ด์•ผ ํ•œ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๋‚˜์ด๊ฐ€ -1์ธ ๊ฒฝ์šฐ๋Š” ์กด์žฌํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ, ๋‚˜์ด๊ฐ€ -1์ธ ์œ ์ €๋Š” ์˜ˆ์ „ ์Šคํ‚ค๋งˆ ๋•Œ ์ž…๋ ฅ๋œ ์œ ์ €๋ผ๊ณ  ํŒ๋ณ„ ๊ฐ€๋Šฅํ•˜๋‹ค. ์ด๋Ÿฌ๋ฉด ํ•ด๋‹น ์œ ์ €๋“ค์—๊ฒŒ๋งŒ ๋‚˜์ด ์ž…๋ ฅ์„ ์ถ”๊ฐ€๋กœ ์š”์ฒญํ•˜๋Š” ์ฐฝ์„ ๋„์šฐ๋Š” ์‹์œผ๋กœ ์•ฑ์„ ์„ค๊ณ„ํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ์ด๋‹ค.
 

#2-8 Database์˜ version ์†์„ฑ ๋ฐ autoMigrations ์†์„ฑ ์„ค์ • (UserDatabase.kt)

...

@Database(
    entities = [User::class],
    version = 2,
    exportSchema = true,
    autoMigrations = [AutoMigration(from = 1, to = 2)]
)
abstract class UserDatabase : RoomDatabase() {

    ...
}

์Šคํ‚ค๋งˆ๊ฐ€ ๋ณ€๊ฒฝ๋˜์—ˆ์œผ๋ฏ€๋กœ version ๊ฐ’์„ 1๋งŒํผ ์˜ฌ๋ฆฐ๋‹ค. ๊ทธ๋ฆฌ๊ณ  autoMigrations ์†์„ฑ์„ ์œ„์™€ ๊ฐ™์ด ์„ค์ •ํ•œ๋‹ค (์ฐธ์กฐ). ์ด ์†์„ฑ์€ ๋ณธ ํ”„๋กœ์ ํŠธ์˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ์ˆ˜ํ–‰๋  ์ˆ˜ ์žˆ๋Š” AutoMigration์˜ ๋ชฉ๋ก์„ ๋ช…์‹œ์ ์œผ๋กœ ์ œ์–ดํ•˜๋Š” ์†์„ฑ์ด๋‹ค.
 

#2-9 ๊ธฐํƒ€ ๋‹ค๋“ฌ๊ธฐ ์ž‘์—…

@Entity์˜ ๋ณ€๊ฒฝ๊ณผ ์—ฐ๊ด€๋œ ๊ธฐ์กด ๋ฐฑ์—”๋“œ ์ฝ”๋“œ๋“ค์„ ์—…๋ฐ์ดํŠธํ•˜๊ณ , ํ”„๋ก ํŠธ์—”๋“œ์—์„  ์‚ฌ์šฉ์ž์˜ ๋‚˜์ด๋ฅผ ์ž…๋ ฅ๋ฐ›์„ EditText๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค. Age๋Š” ๋‚ด๋ถ€์ ์œผ๋กœ Intํ˜•์œผ๋กœ ๊ด€๋ฆฌ๋˜๋Š”๋ฐ ๋ฐ˜ํ•ด, ํ•ด๋‹น ๊ฐ’์„ ์ž…๋ ฅ๋ฐ›๋Š” EditText๋Š” String์œผ๋กœ์„œ ๊ฐ’์„ ๋‹ค๋ฃจ๋ฏ€๋กœ, ์ด ์ฐจ์ด๋ฅผ ์กฐ์ •ํ•˜๋ฉฐ ์–‘๋ฐฉํ–ฅ ๋ฐ์ดํ„ฐ๋ฐ”์ธ๋”ฉ์„ ํ•˜๊ธฐ ์œ„ํ•ด Converter๋ฅผ ์‚ฌ์šฉํ–ˆ๋‹ค. (์ „์ฒด ์ฝ”๋“œ๋Š” #5 ์ฐธ์กฐ)
 

#3 ์ž‘๋™ ํ™•์ธ

๊ธฐ์กด ์Šคํ‚ค๋งˆ์— ์ถ”๊ฐ€๋˜์—ˆ๋˜ Record๋“ค์˜ user_age Column์— -1์ด ํ• ๋‹น๋˜์–ด์žˆ๋Š” ๋ชจ์Šต์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. 4๋ฒˆ์งธ ๋ ˆ์ฝ”๋“œ๋Š” ์ตœ์‹  ์Šคํ‚ค๋งˆ์—์„œ ์ถ”๊ฐ€ํ•œ Record๋‹ค.
 

#4 ์š”์•ฝ

AutoMigration๋Š” ์ง€๋ฃจํ•˜๊ณ  ํŒ์— ๋ฐ•ํžŒ SQL๋ฌธ ์‚ฌ์šฉ์„ ์ƒ๋žตํ•˜๊ฒŒ ๋งŒ๋“ค์–ด์ค€๋‹ค.
 

#5 ์™„์„ฑ๋œ ์•ฑ

 

android-practice/room/AutoMigrationBasics at master ยท Kanmanemone/android-practice

Contribute to Kanmanemone/android-practice development by creating an account on GitHub.

github.com

 

#6 ์ด์–ด์ง€๋Š” ๊ธ€

 

[Android] Room - AutoMigrationSpec

#1 ์ด์ „ ๊ธ€ [Android] Room - AutoMigration ๊ธฐ์ดˆ#1 ๊ฐœ์š”#1-1 ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์Šคํ‚ค๋งˆ (Database Schema) [Android] Room - Entity, DAO, Database#1 ์ด์ „ ๊ธ€ [Android] Room - ๊ธฐ์ดˆ, INSERT์™€ DELETE ์—ฐ์Šต #1 Room ์†Œ๊ฐœ Room์„ ์‚ฌ์šฉํ•˜์—ฌ ๋กœ

kenel.tistory.com

์ด์–ด์ง€๋Š” ๊ฒŒ์‹œ๊ธ€์—์„œ AutoMigrationSpec์„ ์ด์šฉํ•˜์—ฌ Column ์ด๋ฆ„์˜ ๋ณ€๊ฒฝ ๋˜๋Š” ์‚ญ์ œ, Table ์ด๋ฆ„์˜ ๋ณ€๊ฒฝ ๋˜๋Š” ์‚ญ์ œ๋ฅผ ํ•ด๋ณธ๋‹ค.