Room

h_hi·2021년 5월 15일
0

AAC

목록 보기
8/8

안드로이드의 내부 DB 로 자주 사용되는 Room, Realm, SQLite 를 비교하고 Room 에 대해 좀 더 자세히 알아보겠습니다.

Room VS SQLite

Room은 SQLite 에 대한 추상화 레이어를 제공하여 원활한 데이터베이스 액세스를 지원하며 ORM 방식입니다. SQLite 와 비교하여 Room 의 장점들은 다음과 같습니다.

  • 컴파일 타임에서 에러 처리
  • Boiler plate code( 예) getter, setter ) 필요 없음
  • schema 변경 시 자동 업데이트
  • Rxjava 를 위한 Observable 제공

Room VS Realm

그렇다면 현재 많이 사용되는 Room 과 Realm 을 비교해 보겠습니다. Realm 은 안정성이 좋고, 처리 속도가 빨라 대용량 데이터 처리에 좋습니다. 그러나, 내부 라이브러리가 커 용량을 많이 차지 합니다. 또한, SQL 쿼리를 사용했다면 러닝 커브가 있습니다.
큰 용량의 데이터 처리가 아닌 경우라면 Room 또한 좋습니다.

Room 이란..?

Room은 SQLite에 대한 추상화 레이어를 제공하여 원활한 데이터베이스 액세스를 지원하는 동시에 SQLite를 완벽히 활용합니다. 앱은 Database 를 사용하여 Dao 를 가져오고, 가져온 Dao 로 Entity 들을 Database 에 저장하고 변경합니다.

Room 의 구성

  • Database : Dao 를 포함한 액세스 포인트 역할
  • Entity : 테이블 구조 정의 예) 칼럼 명, 칼럼 타입
  • Dao(Database Access Object) : db 접근 메소드들(예) insert, delete) 을 정의

Room 구현

build.gradle 파일에 다음의 dependency 를 추가합니다.

  def room_version = "2.3.0"
  implementation "androidx.room:room-runtime:$room_version"
  kapt "androidx.room:room-compiler:$room_version"

Entity

@Entity
data class User (
    @PrimaryKey val uId : Int,
    @ColumnInfo(name = "first_name") val firstName: String?,
    @ColumnInfo(name = "last_name") val lastName: String?,
    @Ignore val isChecked: Boolean
)

@Entity(tableName = "테이블 이름")
테이블 이름을 지정할 수 있습니다. 기본값은 클래스명 입니다.
@PrimaryKey
PrimaryKey 를 지정합니다.
@ColumnInfo
칼럼 명을 지정합니다. 기본 값은 변수명입니다.
@Ignore
DB 에 저장하긴 싫지만 이 클래스 내에 있어야 하는 변수에 사용합니다.

Dao

@Dao
interface UserDao {
    @Query("SELECT * FROM user")
    fun getAll() : List<User>

    @Query("SELECT * FROM user WHERE uId IN (:userIds)")
    fun getAllByIds(userIds: IntArray) : List<User>

    @Insert
    fun insertAll(vararg users: User)

    @Delete
    fun delete(user: User)
}

@Query
Query 문을 작성합니다. 쿼리에 매개변수를 전달하려면 :변수명 방식으로 사용합니다.

Database

@Database(entities = [User::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
    abstract fun userDao(): UserDao

    companion object {
        private var INSTANCE: AppDatabase? = null
        fun getInstance(context: Context): AppDatabase? {
            if (INSTANCE == null) {
                synchronized(AppDatabase::class) {
                    INSTANCE = Room.databaseBuilder(
                        context.applicationContext,
                        AppDatabase::class.java,
                        "user.db"
                    ).build()
                }
            }

            return INSTANCE
        }
    }
}

Database 는 RoomDatabase() 를 상속받는 abstract 클래스여야 합니다. @Database 어노테이션에는 해당 database 와 관련된 Entity 의 목록을 나열해야 합니다. 또한, 클래스 내에는 arguments 가 0개인 @Dao 를 반환하는 abstract 메소드를 포함해야 합니다.
런타임 시 Room.databaseBuilder() 또는 Room.inMemoryDatabaseBuilder() 를 호출하여 Database 인스턴스를 가져올 수 있습니다. Database 객체를 Singleton 으로 생성합니다.

TypeConverter

Room 에 Primitive type 이 아닌 값을 저장하기 위해서는 TypeConverter 를 사용하여 Room 에게 특정 타입을 데이터베이스에 저장하고, 가져오는 방법을 알려주어야 합니다.
TypeConverter 클래스를 생성하고, 생성한 클래스를 Database 클래스에 추가하여 사용합니다.

TypeConverter class

class UserTypeConverters {

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

    @TypeConverter
    fun toDate(millisSinceEpoch: Long?): Date? {
        return millisSinceEpoch?.let {
            Date(it)
        }
    }

    @TypeConverter
    fun toUUID(uuid: String?): UUID? {
        return UUID.fromString(uuid)
    }

    @TypeConverter
    fun fromUUID(uuid: UUID?): String? {
        return uuid?.toString()
    }
}

DataBase Class

@Database(entities = [Crime::class], version = 1)
@TypeConverters(UserTypeConverters::class)
abstract class AppDatabase : RoomDatabase() {
}

Room 비동기 처리

DB 에 데이터를 처리하는 일은 시간이 많이 걸리 수 있기 때문에 메인스레드에서 처리할 수 없습니다. 그래서 백그라운드 스레드에서 처리를 해주어야 합니다. 비동기 처리의 방법에는 AsyncTask, Rxjava, coroutin 등 다양한 방법이 있습니다. 이번에는 코루틴을 사용해 보겠습니다.

	val db = AppDatabase.getInstance(applicationContext)

        lifecycleScope.launch(Dispatchers.IO) {
            db!!.userDao().insertAll(User(0, "han", "hi", true))
        }

Reference

슬기로운 개발생활[안드로이드 Room 사용법]
안드로이드 developers[Room을 사용하여 로컬 데이터베이스에 데이터 저장]

profile
안드로이드, flutter 개발자

0개의 댓글