깨알 개념/Android

[Android] Room - AutoMigration 기초

interfacer_han 2024. 5. 6. 21:00

#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 이름의 변경 또는 삭제를 해본다.