[번역] Room auto-migrations

2021. 6. 2. 10:08

Room 2.4.0-alpha01 버전부터 지원하는 오토 마이그레이션 기능을 이용해 Room DB 마이그레이션이 좀 더 간편해졌다. 지금까지는 DB 스키마가 변경될 때마다 Migration 클래스를 구현하고 변경 사항을 Room에 정확히 명시해주어야 했다. 대부분의 경우에 이는 복잡한 SQL 쿼리의 작성과 실행에 연관되어 있었다.

 

오토 마이그레이션 기능을 이용하면, 어떤 버전에서 어떤 버전으로 마이그레이션을 원하는지 명시해주기만 하면 Room이 자동으로 컬럼 추가/삭제, 테이블 추가와 같은 간단한 마이그레이션을 진행한다. 좀 더 애매하고 복잡한 경우는 사용자가 구체적인 사항을 명시해주어 마이그레이션을 진행한다. (ex. 컬럼/테이블 이름 변경)

간단한 변경사항 마이그레이션

테이블에 새로운 컬럼을 추가하는 등의 간단한 변경사항으로 인해 버전이 변경되는 경우, 아래와 같이 @Database 어노테이션의 버전을 증가시키고 auto-migrations에 마이그레이션 될 버전 정보를 입력해준다.

@Database(
    version = 2,
    entities = [ Doggos.class ],
    autoMigrations = [
        AutoMigration (from = 1, to = 2)
    ]
)
abstract class DoggosDatabase : RoomDatabase { }

 

DB 버전이 업데이트 될 때마다 AutoMigration을 추가해주면 간단하게 마이그레이션이 가능하다.

@Database(
    version = 3,
    entities = [ Doggos.class ],
    autoMigrations = [
       AutoMigration (from = 1, to = 2),
       AutoMigration (from = 2, to = 3)
    ]
)
abstract class DoggosDatabase : RoomDatabase { }

 

복잡한 변경사항 마이그레이션

테이블 또는 컬럼의 이름이 변경되는 경우 Room은 이름이 변경된건지 삭제된건지 판단하지 못한다. 이러한 경우가 발생했을 때 Room은 컴파일 에러를 발생시키며 사용자에게 AutoMigrationSpec의 구현을 요구한다. AutoMigrationSpec 클래스는 아래 어노테이션 중 하나 이상을 사용하여 구현할 수 있다.

  • @DeleteTable(tableName)
  • @RenameTable(fromTableName, toTableName)
  • @DeleteColumn(tableName, columnName)
  • @RenameColumn(tableName, fromColumnName, toColumnName)

예를 들어, Doggos 테이블을 GoodDoggos로 변경하는 경우 아래와 같이 명시할 수 있다.

@Database(
    version = 2,
    entities = [ GoodDoggos.class ],
    autoMigrations = [
        AutoMigration (
            from = 1, 
            to = 2,
            spec = DoggosDatabase.DoggosAutoMigration::class
        )
    ]
)
abstract class DoggosDatabase : RoomDatabase {   
    @RenameTable(fromTableName = "Doggos", toTableName = "GoodDoggos")
    class DoggosAutoMigration: AutoMigrationSpec {   }
}

 

Migrations vs. Auto-migrations

수동적으로 DB를 마이그레이션 하는 경우, DB 스키마의 변경이 있을 때마다 Room에서 제공하는 Migration 클래스를 이용했었다. 한 테이블을 2개의 다른 테이블로 나눈다고 했을 때, 아래와 같이 테이블을 어떻게 나눌지, 어떤 데이터가 옮겨질지를 정의한 뒤 addMigrations() 함수를 통해 databaseBuilder()에 추가해야 한다.

val MIGRATION_1_2 = object : Migration(1, 2) {
    override fun migrate(database: SupportSQLiteDatabase) {
        ...
    }
}

Room.databaseBuilder(applicationContext, DoggosDatabase::class.java, "doggos-database")
    .addMigrations(MIGRATION_1_2,)
    .build()

 

Migrations와 Auto-migrations의 조합

Room은 Migrations와 Auto-migrations의 혼용을 허용한다. 예를 들어, 버전 1에서 2는 Migration을 이용하고 버전 2에서 3은 Auto-migration을 이용할 수 있다. 만약 동일한 버전에 대해 Migration과 Auto-migration이 정의되어 있으면 Migration이 수행된다.

 

내부적으로 Auto-migration은 Migration 클래스를 구성하고 있으므로, 동일한 마이그레이션 로직이 적용된다. DB에 최초 접근 시, Room은 현재 DB 버전과 @Database에 명시된 버전이 동일한지 확인한다. 버전이 다른 경우 해당 버전으로의 마이그레이션 경로를 찾아 연속적으로 마이그레이션이 수행된다.

테스트

Migrations 또는 Auto-migrations를 테스트하기 위해서는 MigrationTestHelper 테스트 룰을 사용하여 helper.runMigrationsAndValidate() 함수를 호출한다. (자세히 보기)

결론

Auto-migration 기능은 DB 스키마 변경에 쉽게 대응할 수 있도록 도와준다. @Database 내부에 autoMigration 파라미터를 추가하여 대부분의 기본적인 변경사항을 Room 자체적으로 핸들링할 수 있다. 테이블, 컬럼의 삭제나 리네임의 경우 AutoMigrationSpec을 구현해야 하며 나머지 경우는 기존의 Migrations을 사용해야 한다.

 

 

원문보기: Room auto-migrations

+ Recent posts