본문 바로가기
Android/이것저것

[Android] 안드로이드 Room으로 로컬 데이터베이스 이용하기

by 일상 속 둔치 2020. 10. 25.

1. Room 이란?

안드로이드에서 데이터를 로컬에 저장하는 방법에는 File, SharedPreference, SQLite 등이 있다.

 

각각의 특징을 간략하게 알아보자면

 

File - 텍스트 파일 등의 파일을 생성하여 파일 입출력으로 관리한다.

SharedPreference - Key, Value 쌍으로 데이터를 관리한다.

SQLite - MySQL, PostgreSQL과 같은 DB 시스템이지만 응용 프로그램에서 사용하는 가벼운 DB이다.

 

 Room은 위의 SQLite와 관련이 있다..!

 

 Room은 SQLite에 대한 추상화 레이어를 제공한다고 공식 문서에 나와있다. 예를 들어, SQLite에서는 모든 Query를 직접 작성했어야 했는데 Room에서는 CRUD와 관련된 기본 추상화 메서드를 제공하여 사용할 수 있다. 이 외에도 DB를 사용하는데 필요한 기능들이 잘 구성되어 있기 때문에 SQLite를 사용할 때보다 간편히 사용할 수 있을 것 같다.

 

 또한 데이터가 변경되었을 시 LiveData, Flow 등을 이용해서 실시간으로 UI에 적용할 수도 있고 데이터 캐싱도 자동 지원해준다. 이런 장점들이 많아서 Room을 사용하는 것을 안드로이드 공식문서에서는 적극 권장하고 있다!

 

https://developer.android.com/training/data-storage/room?hl=ko

 

2. 사용방법

ORM과 비슷하다.

 1) Table과 매핑할 Entity

 2) DB에 엑세스해서 값을 가져올 Dao

 3) Dao를 관리해서 DB에 접근할 Database

3가지를 구현해주면 된다.

 

 1) Entity

@Entity(tableName = "place")
data class Place (
    @PrimaryKey
    @ColumnInfo(name = "place_id") val placeId: Int,
    @ColumnInfo(name = "place_name") val placeName: String
)

 @Entity 어노테이션으로 선언해준다. tableName 속성을 생략하면 클래스명이 기본 테이블 명이되고 바꾸고 싶다면 명시해주면 된다!

 @PrimaryKey로 기본키를 설정할 수 있으며, @ColumnInfo로 속성을 지정할 수 있다! ColumnInfo도 마찬가지로 name속성을 명기하여 속성명을 지정할 수 있으며 생략하면 변수명이 Default로 들어간다.

 이때, @Ignore를 사용하여 클래스에는 포함되나 Table과 매핑되지 않게 선언할 수도 있다.

 

 Room도 결국 SQLite라 RDB이다. 그런데 보통 ORM에서는 Entity가 서로를 참조할 수 있지만 Room에서는 명시적으로 금지하고 있다. 간략하게 이유를 설명하자면 객체를 참조하게 되면 성능상으로 쿼리를 하는데 오랜 시간이 걸리고 UI 반응속도가 느려지기 때문이다.

 

 그렇기 때문에 우리는 참조하는 형태가 아닌 관계를 정의하는 형태로 사용해야한다!

@Entity
data class Character (
    @PrimaryKey
    @ColumnInfo(name = "character_id") val characterId: Int,
    @ColumnInfo(name = "place_belong_id") val placeBelongId: Int,
    @ColumnInfo(name = "character_name") val characterName: String
)

data class PlaceWithCharacter(
    @Embedded val place: Place,
    @Relation(
        parentColumn = "placeId",
        entityColumn = "placeBelongId"
    )
    val characters: List<Character>
)

이렇게 @Relation을 통해 관계를 정의할 수 있고 이 경우는 place와 character가 1:다 매핑이다.

만약 아래 List<Character>를 Character로 지정해준다면 1:1 매핑이다.

 

 2) Dao

@Dao
interface PlaceDao {

    @Insert
    fun insertPlaces(vararg places: Place)
    
    @Update
    fun updatePlaces(vararg places: Place)
    
    @Delete
    fun deletePlaces(vararg places: Place)
    
    @Query("SELECT * FROM place")
    fun loadAllPlaces(): Array<Place>

    @Query("SELECT place_name FROM place WHERE place_id = :id")
    fun findPlaceWithID(id: Int): String
}

 @Dao 어노테이션으로 선언해준다. Insert, Update, Delete에 대해서 기본적으로 정의가 되어있어 간단하게 사용할 수 있다.

 

 Query 같은 경우는 @Query("SQL") 의 형태로 사용할 수 있으며 함수로 넘겨받은 매개변수를 쿼리에 사용하고 싶다면

":변수"로 변수 앞에 콜론(:)을 붙여서 사용할 수 있다.

 

 3) Database

@Database(entities = arrayOf(Place::class, Character::class), version = 2)
abstract class GameInfoDataBase: RoomDatabase(){
    abstract fun placeDao(): PlaceDao
    abstract fun characterDao(): CharacterDao

    companion object {
        private var INSTANCE: GameInfoDataBase? = null

        fun getInstance(context: Context): GameInfoDataBase? {
            if(INSTANCE == null){
                synchronized(GameInfoDataBase::class){
                    INSTANCE = Room.databaseBuilder(context.applicationContext, GameInfoDataBase::class.java, "nowGame.db")
                        .createFromAsset("game.db")
                        .build()
                }
            }
            return INSTANCE
        }
    }
}

Dao를 관리하고 DB를 매핑하는 클래스이다. DB접근을 한개의 객체로 하기 위해 싱글톤으로 관리하고자 하였다.

 

@Database 어노테이션으로 선언해주고 entities에 접근할 Entity(테이블)을 선언해준다. Version은 DB의 변경 사항을 관리하는 버전이다. 주로 Migration을 할 때 버전을 통해 변경사항을 참고한다.

 

 databaseBuilder와 build를 통해 Room DB를 생성하여 DB를 활용할 수 있다. 만약에 이미 SQLite DB파일 이있는 경우 createFromAsset 혹은 createFromFile을 통해 DB 내용을 가져올 수 있다.

 

 + ADD

미리 데이터를 정의하여 사용하고 싶을 때 위의 툴을 사용하는 것도 좋다. SQLite를 다룰 수 있는 툴이다.

 

URL : sqlitebrowser.org/dl/

 

Downloads - DB Browser for SQLite

(Please consider sponsoring us on Patreon 😄) Windows Our latest release (3.12.0) for Windows: Note - If for any reason the standard Windows release does not work (e.g. gives an error), try a nightly build (below). Nightly builds often fix bugs reported

sqlitebrowser.org


 

참고 : developer.android.com/training/data-storage/room?hl=ko

 

Room을 사용하여 로컬 데이터베이스에 데이터 저장  |  Android 개발자  |  Android Developers

Room 라이브러리를 사용하여 더 쉽게 데이터를 유지하는 방법 알아보기

developer.android.com

 

댓글