Room 내용에 대해 정리한 포스팅의 클릭수와 노출수가 상당히 높았다. 그래서 필자가 정리한 내용을 보니 Room에 필요한 내용이 정리되어있지만, 잘 정리되어 있다는 느낌을 받지는 못했다.

필자는 Room에 관한 내용을 더 깔끔하게 정리하여 이 글을 읽는 분들이 더 쉽게 이해할 수 있게 하기 위해 글을 다시 작성하려 한다.

Android Architecture Components(이하 AAC) 중 하나인 Room의 개념에 대해 알아보는 포스팅이다.

ORM

  • 먼저, ORM이 무엇인지 알 필요가 있다.
  • ORM은 Objectg Relational Mapping으로 데이터베이스와 객체 지향 프로그래밍 언어간의 호환되지 않는 데이터를 변환하는 프로그래밍 기법으로 DB 테이블과 매핑되는 객체를 만들고 그 객체에서 DB를 관리하는 것을 의미한다.

Room

  • Room은 ORM 기반의 라이브러리이다.
  • SQLite 위에 추상화 계층을 제공하여 SQLite의 기능을 최대한 활용하는 동시에 데이터베이스에 원활하게 접근할 수 있도록 고안된 라이브러리이다.

사용법

1) Gradle 설정 (androidX 기준)

  • version은 사용하는 시점에 최신 버전을 사용하면 된다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
dependencies {
def room_version = "2.1.0-alpha03"

implementation "androidx.room:room-runtime:$room_version"
annotationProcessor "androidx.room:room-compiler:$room_version" // use kapt for Kotlin

// optional - RxJava support for Room
implementation "androidx.room:room-rxjava2:$room_version"

// optional - Guava support for Room, including Optional and ListenableFuture
implementation "androidx.room:room-guava:$room_version"

// optional - Coroutines support for Room
implementation "androidx.room:room-coroutines:$room_version"

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

2) Room의 구성요소

  • Database

    • Database 접근 지점을 제공하며 DAO를 관리한다.
    • Annotaion 내에 사용할 Entity 목록을 배열로 작성해야 한다.
  • DAO

    • Database에 접근하는데 사용되는 메소드들을 포함하며, Annotation으로 관리된다.
    • Select, Insert, Delete 등 데이터를 쓰거나 읽을 때 사용한다.
  • Entity

    • Database 내의 테이블을 의미한다.

[Database의 특징]

  • Database 접근 지점을 제공하며, DAO를 관리한다.
  • 클래스에 @Database 어노테이션을 붙이며, 아래의 조건을 만족해야 한다.
    • RoomDatabase 클래스를 상속받는 추상 클래스여야 한다.
    • 어노테이션 내에 Database에 들어갈 Entity 목록을 배열로 포함해야 한다.
    • 파라미터가 0개인 추상 메소드를 포함하고 @Dao 어노테이션된 클래스를 반환한다. 이를 통해 RoomDatabase에게 관리 권한을 위임하여 직접적으로 접근하는 것을 막는다.
  • Runtime에 Room.databaseBuilder()를 호출해 데이터베이스 인스턴스를 얻을 수 있다.
  • 인스턴스를 만드는 과정을 많은 비용이 든다. 하지만 접근은 자주하기 때문에 문서에서는 싱글톤 패턴을 이용해 만드는 것을 권장하고 있다.

[DAO(Data Access Object)의 특징]

  • Database에 접근하는데 사용되는 메소드들을 갖고 있으며, 어노테이션으로 관리된다.
  • SELECT, INSERT, DELETE 등 데이터를 읽거나 쓸 때 사용한다.
  • LiveData를 사용하면 Observable Query를 이용할 수 있다.
  • @DAO 어노테이션을 활용하며, interface or abstract class로 작성해야 한다.
1
2
3
4
5
6
7
8
@Dao
interface UserDao{
@Query("SELECT * FROM user")
fun getUsers(): List<UserEntity>

@Insert
fun insert(user: UserEntity)
}

[Entity 특징]

  • Database 내의 테이블을 의미한다. 이름을 지정할 수도 있고, 지정하지 않을 경우 default 값으로 클래스의 이름이 Entity의 이름으로 지정되며, 대소문자를 구분하지 않는다.
  • 컬럼 값도 위의 규칙과 동일하다.
  • 관련 필드 집합을 Entity들로 정의한다.
  • 각 Entity에 대해 항목을 보관하기 위해 연결된 데이터베이스 객체 내에 테이블이 생성된다.
  • 필드를 유지하려면 Room은 필드에 접근할 수 있어야 한다. 따라서 필드를 public으로 만들거나 getter/setter를 제공할 수 있어야 한다. 그렇지 않고 private으로 필드를 만든다면 에러가 발생한다.
1
2
3
4
5
@Entity
data class UserEntity(
val userId: Int = 0,
val name: String=""
)

참고