RoomDB Migration

이영준·2022년 11월 1일
0

앱에서 기능을 추가하고 변경하는 경우 Room 항목 클래스와 기본 데이터베이스 테이블을 수정하여 이러한 변경사항을 반영해야 합니다. 앱 업데이트로 인해 데이터베이스 스키마가 변경될 때는 기기 내 데이터베이스에 있는 사용자 데이터를 유지하는 것이 중요합니다.
https://developer.android.com/studio/inspect/database?utm_source=android-studio

안드로이드 디벨로퍼에서 room DB사용에서 강조하는 내용은 바로 앱 업데이트로 인한 db의 변화에서도 기존의 내부 데이터들이 온전하게 유지되어야 한다는 점이다. 때문에 Migration에 대한 대비가 되어있어야 한다.

초기 설정

plugins {
    id 'com.android.application'
    id 'org.jetbrains.kotlin.android'
    id 'kotlin-kapt'
}

kotlin-kapt가 plugin에 있다는 가정 하에

defaultconfig 내에

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

위 내용을 포함시켜준다. gradle sync를 하고, Project로 보기 방식을 바꾸면


app 내의 schemas 폴더가 만들어진 것을 볼 수 있고, 여기 안에

{
  "formatVersion": 1,
  "database": {
    "version": 1,
    "identityHash": "6d260d58aa8d20b5eeb6ae71f3a68c8b",
    "entities": [
      {
        "tableName": "student_info",
        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_name` TEXT NOT NULL)",
        "fields": [
          {
            "fieldPath": "id",
            "columnName": "student_id",
            "affinity": "INTEGER",
            "notNull": true
          },
          {
            "fieldPath": "name",
            "columnName": "student_name",
            "affinity": "TEXT",
            "notNull": true
          }
        ],
        "primaryKey": {
          "columnNames": [
            "student_id"
          ],
          "autoGenerate": true
        },
        "indices": [],
        "foreignKeys": []
      }
    ],
    "views": [],
    "setupQueries": [
      "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
      "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '6d260d58aa8d20b5eeb6ae71f3a68c8b')"
    ]
  }
}

우리가 작성한 엔티티의 스키마가 생성된 것을 볼 수 있다.

Entity 변경

이전에 생성한 Student Entity를 보자

@Entity(tableName = "student_info")
data class Student(
    @PrimaryKey(autoGenerate = true)
    @ColumnInfo(name = "student_id")
    val id : Int,

    @ColumnInfo(name = "student_name")
    var name : String
)

이렇게 만든 개체에 값을 넣은 다음, entitiy에 이메일도 넣고 싶어 변경을 해보았다.

@Entity(tableName = "student_info")
data class Student(
    @PrimaryKey(autoGenerate = true)
    @ColumnInfo(name = "student_id")
    val id : Int,

    @ColumnInfo(name = "student_name")
    var name : String,

    @ColumnInfo(name = "student_email")
    var email: String
)

Database 변경

@Database(entities = [Student::class], version = 1)
abstract class StudentDatabase : RoomDatabase() {

    abstract val subscriberDAO: StudentDAO

    companion object {
        @Volatile
        private var INSTANCE: StudentDatabase? = null
        fun getInstance(context: Context): StudentDatabase {
            synchronized(this) {
                var instance = INSTANCE
                if (instance == null) {
                    instance = Room.databaseBuilder(
                        context.applicationContext,
                        StudentDatabase::class.java,
                        "student_data_database"
                    ).build()
                    INSTANCE = instance
                }
                return instance
            }
        }
    }
}

기존의 데이터베이스 파일이다. 여기서

@Database(entities = [Student::class], version = 1)

버전을 바꿔주어

@Database(
    entities = [Student::class],
    version = 2,
    autoMigrations = [AutoMigration(from = 1, to = 2)]
)

위처럼 작성해준다.

이후 build를 새로 하면 project의 schema 폴더에 json 스키마 파일이 추가되면서 새로운 데이터를 이어서 넣을 수 있다.

profile
컴퓨터와 교육 그사이 어딘가

0개의 댓글