|

Room migration에서 no such column 오류는 왜 생길까

Room migration 글 대표 이미지
Room migration에서 no such column 오류가 나는 원인을 엔티티 변경, DB 버전, Migration 등록, schema export 흐름으로 정리합니다.

Room migration에서 no such column 오류가 난다는 것은 코드가 기대하는 컬럼과 실제 기기 안의 SQLite 테이블 구조가 다르다는 뜻입니다. 엔티티에 필드를 추가했다고 기존 사용자 DB에 컬럼이 자동으로 생기지는 않습니다.

이 오류의 핵심은 앱 코드의 최신 Entity와 사용자 기기에 남아 있는 오래된 DB 스키마 사이의 차이입니다. 그래서 해결도 Entity가 아니라 Migration 흐름에서 찾아야 합니다.

Room migration no such column 오류 원인 카드
엔티티 변경, 버전 증가, Migration 등록이 함께 맞아야 no such column 오류를 피할 수 있다.

Room migration에서 no such column은 언제 터질까

가장 흔한 상황은 Entity에 새 필드를 추가한 뒤 앱 버전을 배포했지만, 기존 DB를 새 스키마로 바꾸는 Migration이 빠진 경우입니다. 새로 설치한 사용자는 문제가 없지만, 기존 사용자는 예전 DB 파일을 그대로 갖고 있기 때문에 오류가 납니다.

@Entity
data class Book(
    @PrimaryKey val id: Long,
    val title: String,
    val publishedYear: Int // 새로 추가한 컬럼
)

코드는 publishedYear 컬럼을 읽으려 하지만 기존 테이블에는 그 컬럼이 없습니다. 이때 SQLite는 no such column을 냅니다.

DB version만 올리면 충분할까

version을 올리는 것은 Room에게 스키마가 바뀌었다고 알려주는 일입니다. 하지만 실제 테이블을 어떻게 바꿀지는 Migration에 적어야 합니다. version 증가와 Migration 등록은 함께 가야 합니다.

val MIGRATION_1_2 = object : Migration(1, 2) {
    override fun migrate(db: SupportSQLiteDatabase) {
        db.execSQL("ALTER TABLE Book ADD COLUMN publishedYear INTEGER NOT NULL DEFAULT 0")
    }
}

Room.databaseBuilder(context, AppDatabase::class.java, "app.db")
    .addMigrations(MIGRATION_1_2)
    .build()

컬럼 추가보다 rename이 더 위험한 이유

컬럼을 추가하는 것은 ALTER TABLE ADD COLUMN으로 비교적 단순합니다. 하지만 이름을 바꾸거나 타입을 바꾸거나 컬럼을 삭제하는 경우에는 기존 데이터를 보존하면서 새 테이블로 옮겨야 할 수 있습니다.

  • 새 테이블 생성
  • 기존 테이블에서 필요한 컬럼 복사
  • 기존 테이블 삭제
  • 새 테이블 이름 변경
  • 인덱스와 외래키 재생성

fallbackToDestructiveMigration은 해결책일까

fallbackToDestructiveMigration은 Migration이 없을 때 기존 DB를 버리고 새로 만들 수 있게 합니다. 개발 중에는 편해 보이지만, 실제 사용자 데이터가 있는 앱에서는 매우 조심해야 합니다.

데이터가 서버에서 다시 내려오는 캐시라면 선택지가 될 수 있습니다. 하지만 사용자가 직접 만든 로컬 데이터라면 오류를 숨기는 대신 데이터를 잃게 만들 수 있습니다.

schema export를 켜야 하는 이유

Room migration을 안정적으로 관리하려면 이전 스키마와 새 스키마를 비교할 수 있어야 합니다. schema export를 켜면 버전별 JSON 스키마가 남고, migration test에서 실제 변경을 검증하기 쉬워집니다.

점검 순서

  1. 오류 로그에서 없는 컬럼 이름을 확인한다
  2. 해당 컬럼이 Entity에 언제 추가됐는지 본다
  3. Database version이 올라갔는지 확인한다
  4. startVersion, endVersion에 맞는 Migration이 있는지 확인한다
  5. Room.databaseBuilder에 addMigrations가 등록됐는지 본다
  6. 기존 버전 DB로 migration test를 실행한다

정리

Room migration의 no such column은 대부분 ‘코드는 새 스키마를 기대하지만 실제 DB는 예전 스키마’일 때 생깁니다. Entity 수정, DB version 증가, Migration SQL, addMigrations 등록이 모두 맞아야 합니다.

공식 흐름은 Android Room migration 문서를 기준으로 확인하는 것이 좋습니다. 이전 글인 Room migration은 왜 어렵게 느껴질까와 함께 보면 배포 후 DB 변경의 맥락이 더 잘 잡힙니다.

함께보면 좋은 글