Room 데이터베이스 미리 채우기

때로 특정 데이터 세트가 이미 로드된 데이터베이스로 앱을 시작하기를 원할 수도 있습니다. 이를 데이터베이스 미리 채우기라고 합니다. Room 2.2.0 이상에서는 API 메서드를 사용하여 초기화 시 기기 파일 시스템의 사전 패키징된 데이터베이스 파일의 콘텐츠로 Room 데이터베이스를 미리 채울 수 있습니다.

앱 애셋에서 미리 채우기

앱의 assets/ 디렉터리 어딘가에 있는 사전 패키징된 데이터베이스 파일에서 Room 데이터베이스를 미리 채우려면 build()를 호출하기 전에 RoomDatabase.Builder 객체에서 createFromAsset() 메서드를 호출합니다.

Kotlin

Room.databaseBuilder(appContext, AppDatabase::class.java, "Sample.db")
    .createFromAsset("database/myapp.db")
    .build()

Java

Room.databaseBuilder(appContext, AppDatabase.class, "Sample.db")
    .createFromAsset("database/myapp.db")
    .build();

createFromAsset() 메서드는 assets/ 디렉터리에서 사전 패키징된 데이터베이스 파일까지의 상대 경로를 포함하는 문자열 인수를 허용합니다.

파일 시스템에서 미리 채우기

앱의 assets/ 디렉터리를 제외한 기기의 파일 시스템 어딘가에 있는 사전 패키징된 데이터베이스 파일에서 Room 데이터베이스를 미리 채우려면 build()를 호출하기 전에 RoomDatabase.Builder 객체에서 createFromFile() 메서드를 호출합니다.

Kotlin

Room.databaseBuilder(appContext, AppDatabase::class.java, "Sample.db")
    .createFromFile(File("mypath"))
    .build()

Java

Room.databaseBuilder(appContext, AppDatabase.class, "Sample.db")
    .createFromFile(new File("mypath"))
    .build();

createFromFile() 메서드는 사전 패키징된 데이터베이스 파일에 File 인수를 허용합니다. Room은 지정된 파일을 직접 열지 않고 파일의 사본을 생성하므로 앱에 파일 읽기 권한이 있는지 확인합니다.

사전 패키징된 데이터베이스가 포함된 이전 처리

사전 패키징된 데이터베이스 파일은 Room 데이터베이스가 대체 이전을 처리하는 방식을 변경할 수도 있습니다. 일반적으로 파괴적인 이전이 사용 설정되었으며 Room에서 이전 경로 없이 이전을 실행해야 할 때 Room은 데이터베이스의 모든 테이블을 삭제하고 타겟 버전용으로 지정된 스키마로 빈 데이터베이스를 생성합니다. 그러나 타겟 버전과 동일한 번호의 사전 패키징된 데이터베이스 파일을 포함하면 Room은 파괴적인 이전을 실행한 후 새롭게 다시 생성된 데이터베이스를 사전 패키징된 데이터베이스 파일의 콘텐츠로 채우려고 시도합니다.

Room 데이터베이스 이전에 관한 자세한 내용은 Room 데이터베이스 이전을 참고하세요.

다음 섹션에서는 이러한 작업이 실제로 어떻게 작동하는지 몇 가지 예를 보여줍니다.

예: 사전 패키징된 데이터베이스를 사용한 대체 이전

다음을 가정해 보겠습니다.

  • 앱이 버전 3에서 Room 데이터베이스를 정의합니다.
  • 기기에 이미 설치된 데이터베이스 인스턴스는 버전 2에 있습니다.
  • 버전 3에 사전 패키징된 데이터베이스 파일이 있습니다.
  • 버전 2에서 버전 3으로의 구현된 이전 경로가 없습니다.
  • 파괴적인 이전이 사용 설정되었습니다.

Kotlin

// Database class definition declaring version 3.
@Database(version = 3)
abstract class AppDatabase : RoomDatabase() {
    ...
}

// Destructive migrations are enabled and a prepackaged database
// is provided.
Room.databaseBuilder(appContext, AppDatabase::class.java, "Sample.db")
    .createFromAsset("database/myapp.db")
    .fallbackToDestructiveMigration()
    .build()

Java

// Database class definition declaring version 3.
@Database(version = 3)
public abstract class AppDatabase extends RoomDatabase {
    ...
}

// Destructive migrations are enabled and a prepackaged database
// is provided.
Room.databaseBuilder(appContext, AppDatabase.class, "Sample.db")
    .createFromAsset("database/myapp.db")
    .fallbackToDestructiveMigration()
    .build();

이 상황에서 일어나는 일은 다음과 같습니다.

  1. 앱에 정의된 데이터베이스는 버전 3에 있고 기기에 이미 설치된 데이터베이스 인스턴스는 버전 2에 있으므로 이전이 필요합니다.
  2. 버전 2에서 버전 3으로의 구현된 이전 계획이 없으므로 이전은 대체 이전입니다.
  3. fallbackToDestructiveMigration() 빌더 메서드가 호출되므로 대체 이전은 파괴적입니다. Room은 기기에 설치된 데이터베이스 인스턴스를 삭제합니다.
  4. 버전 3에 사전 패키징된 데이터베이스 파일이 있으므로 Room은 데이터베이스를 다시 생성하고 사전 패키징된 데이터베이스 파일의 콘텐츠를 사용하여 새로 생성된 이 데이터베이스를 채웁니다. 반면에 사전 패키징된 데이터베이스 파일이 버전 2에 있다면 Room은 이 파일이 타겟 버전과 일치하지 않음을 알고 이 파일을 대체 이전의 일부로 사용하지 않습니다.

예: 사전 패키징된 데이터베이스로 구현된 이전

대신 앱이 버전 2에서 버전 3으로의 이전 경로를 구현한다고 가정해 보겠습니다.

Kotlin

// Database class definition declaring version 3.
@Database(version = 3)
abstract class AppDatabase : RoomDatabase() {
    ...
}

// Migration path definition from version 2 to version 3.
val MIGRATION_2_3 = object : Migration(2, 3) {
    override fun migrate(database: SupportSQLiteDatabase) {
        ...
    }
}

// A prepackaged database is provided.
Room.databaseBuilder(appContext, AppDatabase::class.java, "Sample.db")
    .createFromAsset("database/myapp.db")
    .addMigrations(MIGRATION_2_3)
    .build()

Java

// Database class definition declaring version 3.
@Database(version = 3)
public abstract class AppDatabase extends RoomDatabase {
    ...
}

// Migration path definition from version 2 to version 3.
static final Migration MIGRATION_2_3 = new Migration(2, 3) {
    @Override
    public void migrate(SupportSQLiteDatabase database) {
        ...
    }
};

// A prepackaged database is provided.
Room.databaseBuilder(appContext, AppDatabase.class, "Sample.db")
    .createFromAsset("database/myapp.db")
    .addMigrations(MIGRATION_2_3)
    .build();

이 상황에서 일어나는 일은 다음과 같습니다.

  1. 앱에 정의된 데이터베이스는 버전 3에 있고 기기에 이미 설치된 데이터베이스는 버전 2에 있으므로 이전이 필요합니다.
  2. 버전 2에서 버전 3으로의 구현된 이전 경로가 있으므로 Room은 정의된 migrate() 메서드를 실행하여 기기의 데이터베이스 인스턴스를 버전 3으로 업데이트하며, 이미 데이터베이스에 있는 데이터는 보존합니다. Room은 사전 패키징된 데이터베이스 파일을 사용하지 않습니다. Room은 대체 이전의 경우에만 사전 패키징된 데이터베이스 파일을 사용하기 때문입니다.

예: 사전 패키징된 데이터베이스를 사용한 다단계 이전

사전 패키징된 데이터베이스 파일은 여러 단계로 구성된 이전에 영향을 줄 수도 있습니다. 다음과 같은 경우를 생각해 보세요.

  • 앱이 버전 4에서 Room 데이터베이스를 정의합니다.
  • 기기에 이미 설치된 데이터베이스 인스턴스는 버전 2에 있습니다.
  • 버전 3에 사전 패키징된 데이터베이스 파일이 있습니다.
  • 버전 3에서 버전 4로의 구현된 이전 경로가 있지만 버전 2에서 버전 3으로의 이전 경로는 없습니다.
  • 파괴적인 이전이 사용 설정되었습니다.

Kotlin

// Database class definition declaring version 4.
@Database(version = 4)
abstract class AppDatabase : RoomDatabase() {
    ...
}

// Migration path definition from version 3 to version 4.
val MIGRATION_3_4 = object : Migration(3, 4) {
    override fun migrate(database: SupportSQLiteDatabase) {
        ...
    }
}

// Destructive migrations are enabled and a prepackaged database is
// provided.
Room.databaseBuilder(appContext, AppDatabase::class.java, "Sample.db")
    .createFromAsset("database/myapp.db")
    .addMigrations(MIGRATION_3_4)
    .fallbackToDestructiveMigration()
    .build()

Java

// Database class definition declaring version 4.
@Database(version = 4)
public abstract class AppDatabase extends RoomDatabase {
    ...
}

// Migration path definition from version 3 to version 4.
static final Migration MIGRATION_3_4 = new Migration(3, 4) {
    @Override
    public void migrate(SupportSQLiteDatabase database) {
        ...
    }
};

// Destructive migrations are enabled and a prepackaged database is
// provided.
Room.databaseBuilder(appContext, AppDatabase.class, "Sample.db")
    .createFromAsset("database/myapp.db")
    .addMigrations(MIGRATION_3_4)
    .fallbackToDestructiveMigration()
    .build();

이 상황에서 일어나는 일은 다음과 같습니다.

  1. 앱에 정의된 데이터베이스는 버전 4에 있고 기기에 이미 설치된 데이터베이스 인스턴스는 버전 2에 있으므로 이전이 필요합니다.
  2. 버전 2에서 버전 3으로의 구현된 이전 경로가 없으므로 이전은 대체 이전입니다.
  3. fallbackToDestructiveMigration() 빌더 메서드가 호출되므로 대체 이전은 파괴적입니다. Room은 기기의 데이터베이스 인스턴스를 삭제합니다.
  4. 버전 3에 사전 패키징된 데이터베이스 파일이 있으므로 Room은 데이터베이스를 다시 생성하고 사전 패키징된 데이터베이스 파일의 콘텐츠를 사용하여 새로 생성된 이 데이터베이스를 채웁니다.
  5. 기기에 설치된 데이터베이스는 이제 버전 3에 있습니다. 이는 여전히 앱에 정의된 버전보다 낮으므로 또 다른 이전이 필요합니다.
  6. 버전 3에서 버전 4로의 구현된 이전 경로가 있으므로 Room은 정의된 migrate() 메서드를 실행하여 기기의 데이터베이스 인스턴스를 버전 4로 업데이트하며, 버전 3의 사전 패키징된 데이터베이스 파일에서 복사된 데이터는 보존합니다.

추가 리소스

Room 데이터베이스 미리 채우기에 관해 자세히 알아보려면 다음 추가 리소스를 참고하세요.

동영상

블로그