본문 바로가기
프로그래밍 놀이터/안드로이드, Java

[android] 기초 - Room 에 대해 알아보자

by 돼지왕 왕돼지 2020. 8. 17.
반응형

 

android room tutorial

-

Room 은 SQLite 의 추상화 layer 를 제공하는 lib 으로, SQLite 의 모든 기능을 사용하면서 더 견고한 db 접근을 할 수 있게 해준다.

 

 

-

Room 이 많은 부분을 케어해주기 때문에, SQLite 대신에 Room 을 사용하는 것이 강추된다.

 

 

-

Room 에는 3가지 컴퍼넌트가 있다.

 

1. Database

     DB holder 를 가지고 있으며, 앱의 relational 한 영구적인 data 에 접근하는 채널이 된다.

    @Database 로 annotate 된 class 는 다음 조건을 충족시켜야 한다.

        RoomDatabase 를 상속하는 abstract class 가 되도록 한다.

        db 에 들어갈 entity 들을 annotation 으로 정의해준다.

        @Dao 로 annotate 된 class 를 return 하는 argument 가 없는 abstract method 를 가져야 한다.

    Runtime 에 Room.databaseBuilder() 또는 Room.inMemoryDatabaseBuilder() 를 통해 DB instance 를 얻을 수 있다.

 

2. Entity

    DB 안의 Table 을 정의한다.

 

3. DAO

    DB 를 접근하는 method 들을 가진다.

 

 

-

데이터에 접근하기 위해서는 Room 를 통해서 DAO 를 가져오고, 그 DAO 를 통해 데이터에 접근한다.

 

android room structure

 

 

 

Declaring dependencies

 

-

Google Maven repo 가 필요하다.

Room 에 대한 dependency 는 Room migration testing 과 Room RxJava 를 포함한다.

 

 

-

dependencies{
    def room_version = "2.2.6" // version 은 알아서
    
    implementation "androidx.room:room-runtime:$room_version"
    annotationProcessor "androidx.room:room-compiler:$room_version"
    // kotlin 은 annotationProcessor 대신 kapt 를 사용한다.
    // kapt "androidx.room:room-compiler:$room_version"
    
    // optional - Kotlin extensions and Coroutine support for Room
    implementation "androidx.room:room-ktx:$room_version"
    
    // optional - RxJava support for Room
    implementation "androidx.room:room-rxjava2:$room_version"

    // optional - Test helpers
    testImplementation "androidx.room:room-testing$room_version"
}

 

 

-

kotlin 기반 앱은 annotationProcessor 대신 kapt 를 사용하도록 해야 한다.

이를 위해서 kotlin-kapt plugin 을 추가해야 한다.

( kapt 는 Kotlin Annotation Processing Tool 의 약자 )

 

 

-

@Entity 
data class User(
    @PrimaryKey
    val uid: Int,
    
    @ColumnInfo(name = "first_name")
    val firstName: String:?,
    
    @ColumnInfo(name = "last_name") 
    val lastName:String? 
)
    
@Dao
interface UserDao{
    @Query("SELECT * FROM user") 
    fun getAll(): List<User> 
    
    @Query("SELECT * FROM user WHERE uid IN (:userIds)") 
    fun loadAllByIds(userIds:IntArray): List<User> 
    
    @Query("SELECT * FROM user WHERE first_name LIKE :first AND last_name LIKE :last LIMIT 1") 
    fun findByName(first:String, last:String): User 
    
    @Insert 
    fun insertAll(vararg users:User) 
    
    @Delete 
    fun delete(user:User) 
} 

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

 

 

-

val db = Room.databaseBuilder(appContext, AppDatabase::class.java, "database-name")
                    .build()

 

 

-

앱이 single process 로 동작한다면, AppDatabase object 를 만들 때 singleton design pattern 을 따르는 것이 좋다.

각각의 RoomDatabase instance 는 생성하는 데 상당히 많은 비용이 들고, multiple instance 를 만들 이유가 거의 없다.

 

만약 multiple process 로 동작한다면, database builder 를 만들 때 enableMultiInstanceInvalidation() 을 호출해주는 것이 좋다.

이렇게 하면 AppDatabase 는 각각의 process 에 하나씩 instance 를 갖게 되고, shared db file 을 invalidate 하게 되면, 이 invalidation 은 자동으로 다른 process 의 AppDatabase instance 에 전파된다.

 

 

-

참고 자료

https://developer.android.com/jetpack/androidx/releases/room

https://developer.android.com/training/data-storage/room/index.html

 

 

반응형

댓글