20140515

Android SQLite upgrade 전략

앱 업데이트하면서 SQLite 스키마 바꿔야 할 일이 또 생김. 그동안 매번 DROP/CREATE 했는데 이제 유저 데이터 유지 필요해서 제대로 마이그레이션 씀.

public class DbHelper extends SQLiteOpenHelper {
    private static final int DB_VERSION = 4;

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVer, int newVer) {
        if (oldVer < 2) {
            db.execSQL("ALTER TABLE item ADD COLUMN category TEXT");
        }
        if (oldVer < 3) {
            db.execSQL("CREATE TABLE favorite (id INTEGER PRIMARY KEY, item_id INTEGER)");
        }
        if (oldVer < 4) {
            // SQLite는 DROP COLUMN이 없다. 테이블 재생성...
            db.execSQL("CREATE TABLE item_new (id INTEGER PRIMARY KEY, title TEXT, category TEXT)");
            db.execSQL("INSERT INTO item_new SELECT id, title, category FROM item");
            db.execSQL("DROP TABLE item");
            db.execSQL("ALTER TABLE item_new RENAME TO item");
        }
    }
}

핵심은 if (oldVer < N) 블록을 누적으로 쌓는거. 버전 1 → 4로 한번에 올라오는 유저도 있으니까 각 단계 다 실행되게 해야 함.

SQLite 한계 몇가지:

  • DROP COLUMN 없음. 테이블 재생성 해야됨
  • PRAGMA foreign_keys는 연결마다 설정. onOpen()에서 매번 켜줘야 함
  • ALTER TABLE로 DEFAULT 바꾸는것도 안됨

migration 실수하면 유저 데이터 날아가서 리뷰테러 맞음. 꼭 이전 버전에서 업글 테스트 해야 함. 이전 apk 깔아서 데이터 넣고 → 새 apk로 업데이트 → 데이터 유지 확인. 귀찮은데 안하면 후회.

onDowngrade는 기본이 예외던짐. 내려가는 상황 없도록 스토어 롤백만 안 건드리면 됨.