본문 바로가기

Dev/안드로이드

Cannot figure out how to save this field into database. You can consider adding a type converter for it. 오류 및 Room과 Enum 타입

 

 평소처럼 Room을 사용 중이었는데, DB에 내가 만든 Entity의 필드를 저장할 수 없다는 오류가 떴다. 분명히 나는 DB에서 기본적으로 지원하는 타입의 필드들만 사용한 것 같은데 좀 당황스러웠다.

 

문제가 된 Entity

 

 의심되는 것은 물론 Date 타입이었다. 예전에 MySql을 이용할 때는 타임스탬프를 넣을 수 있었던 것 같은데, 내가 잘못 기억하는 것인지 Room에서만 지원하지 않는 것인지 좀 헷갈렸다. 그래서 혹시나 해서 공식 문서를 뒤적거리다 보니까 이런 게 떡하니 적혀있었다.

 

Android Developers

 

 TypeConverter를 사용해야 하는 복잡한 데이터 타입으로, Date를 예시로 들고 있다... 처음엔 그냥 직접 리눅스 시간으로 변환해서 넣고 타입을 Long으로 바꿀까하다가, 그래도 공식 문서 권장사항은 따라야지 싶어서 TypeConverter를 적용하기로 했다.

 

class RoomConverters {
    @TypeConverter
    fun fromTimeStamp(value: Long?): Date? {
        return value?.let { Date(it) }
    }

    @TypeConverter
    fun dateToTimeStamp(date: Date?): Long? {
        return date?.time
    }
}

 

 TypeConverter는 공식 문서에 있는 것처럼 그대로 만들었고, 이를 어노테이션으로 등록해서 빌드하니 문제 없이 실행되었다.

 

 

 그런데 위 문제와는 별개로 공식 문서를 읽다보니 눈에 띄는 단락이 하나 있었는데,  Room 2.3 이후로 enum 타입에 대한 기본 type converter를 제공한다는 내용이었다.

Android Developers
헛수고가 돼버렸다..

 

 enum은 당연히 지원하지 않을 줄 알고, 따로 util로 상태를 나타내는 enum과 Int 값으로 상호변환하는 컨버터를 만들고(Room에서 쓰는 TypeConverter 형태는 아님) 그에 맞춰서 Dao 로직도 다 구성해뒀는데 삽질이 되었다.

 

CommonsWare
CommonsWare

 

 실제로 찾아보니까 enum 클래스를 String으로 컨버팅 하는 TypeConverter를 자동으로 생성한다는 것을 알 수 있었고, entity 내의 타입도 내가 만든 enum 클래스 그대로 사용하도록 해봤는데 멀쩡하게 빌드가 되었다..

 비즈니스 로직에서 쓰이는 모델 내에 있는 enum을 그대로 사용할 수 있는 형태가 좀 더 직관적일 것 같아서 기존 코드를 모두 수정했다. SELECT 쿼리의 WHERE절도 맞춰서 다 바꿔주었다..

 

 

 이번 케이스를 통해 두 가지는 확실하게 머리에 넣었다.

1. Room에서는 Date 타입을 필드에 그대로 사용할 수 없다.

2. Enum 클래스는 필드에 그대로 사용할 수 있으며, String 값으로 컨버팅된다.