Room은 Android Architecture Components(AAC) 중 하나이다. Room에 대해서 저번에 살펴봤지만, 헷갈리고 개념이 정립되어 있지 않아 다시 정리하려고 한다. 이번에는 개념적인 부분보다는 실제로 어떻게 사용을 할 수 있는지에 초점을 맞추려고 한다.

Room의 3가지 주요 구성요소

  • RoomDatabase : 데이터베이스의 holder를 구성하며 관계형 데이터에 대한 연결을 해준다.
  • 조건
    1. RoomDatabase를 extends하는 클래스는 abstract 클래스이다.
    2. annotaion으로 eneities(Table 구조와 mapping되는 clas)를 포함해야 한다.
    3. 클래스 내부에 DAO(Data Access Object)를 포함해야 한다.
  • Entity : 데이터베이스 내의 테이블을 나타낸다.
  • Dao : 데이터베이스에 접근하는 데 사용되는 함수를 정의한다.(Query를 포함한다.)

Entity

  • Entity는 object이자 데이터베이스의 테이블을 나타낸다.
  • Entity 파일의 특징은 class의 변수들이 column이 되어 데이터베이스의 테이블로 된다는 것이다.
  • ColumnInfo로 필드의 이름을 설정하지 않는다면 필드의 이름과 같은 Column 이름으로 생성된다.
  • 이때, 실제 table로 만들고 싶지 않은 필드에는 @Ignore 어노테이션을 선언한다.

Annotation 속성

@Entity(name = “word_table”)
: Entity의 테이블 명을 선언한다.
@PrimaryKey
: 모든 Entity는 PrimaryKey가 필요하다.(값을 구별하기 위한 식별자)
@ColumnInfo(name = “word”)
: 테이블에서 word라는 이름으로 데이터베이스 column 사용

Entity에는 getter 함수가 필수적으로 존재해야 하고 변수들은 public 형태여야 한다.

@Embeded
: 필드로 object를 갖는 경우 사용한다.

  • Annotaion과 관련된 속성은 구글 공식 문서를 참고하거나 블로그의 다른 글을 참고하면 좋을 것 같다.
  • 5일차 [안드로이드] Room

DAO 만들기

  • DAO는 SQL 쿼리를 지정하고 메소드 호출을 연결한다.
  • 쿼리는 별도의 스레드에서 동작하며 메인 스레드에서 동작하지 않는다.(UI - Thread에서는 동작하면 앱에 에러가 난다.)
  • Interface class 혹은 abstract class로 사용한다.
  • @Dao 어노테이션을 지정한다.
  • Dao에서는 데이터베이스에 있는 테이블에서 사용할 쿼리를 지정하고 메소드와 연결을 한다. 단순히 정의만 해놓는다.

주의

AppDatabase object를 생성하는 코드는 비용이 많이 들기 때문에 Singleton으로 구현해야 한다.

Room Database 만들기

  • Room Database는 SQLite 데이터베이스 상위에 있는 데이터베이스 계층을 말한다.
  • Room은 DAO를 이용하여 데이터베이스의 쿼리를 실행한다.
  • 기본적으로 UI 성능 저하를 피하기 위해서 Room에서는 main thread에서 쿼리를 실행할 수 없다.
  • LiveData는 필요할 때 백그라운드 스레드에서 쿼리를 비동기적으로 자동 실행하여 규칙을 적용한다.
  • Room 클래스는 abstract 여야 하며, RoomDatabase를 상속받아야 한다.
  • 일반적으로 RoomDatabase 객체를 생성하는 코드는 비용이 많이 들기 때문에 싱글톤으로 구현해 하나의 객체만 유지한다.

어노테이션
@Database(entities = {Word.class}, version = 1)
: Room Database를 정의한다. entities는 데이터베이스에 사용될 Entity를 나타낸다. version는 추후 데이터베이스의 변경 사항이 있을 시 변경해야 할 사항이다.

Repository 만들기

  • Repository는 여러 데이터에 대한 접근을 할 수 있는 class이다.
  • 주로 로컬 데이터(앱 내장 데이터)를 가져올 지 네트워크에서 데이터를 가져올 지를 다룬다.
  • Dao의 멤버 변수와 word를 넣을 list 변수를 만들어 준다.
  • AsyncTask를 만들어서 Database에 insert 하는 작업을 수행한다.
  • 이유는? UI - Thread에서 수행할 경우 오류가 발생한다.

ViewModel?

내가 참고한 예제에서는 ViewModel을 사용하였다. 하지만, ViewModel에 대한 이해가 잘 되지 않아서 사용하지 않고 예제를 조금 다른 방식으로 수정하였다. 그래도 일단, ViewModel이 무엇인지 간단하게 살펴보자.

  • ViewModel의 역할은 UI에 데이터를 제공하고 변경된 사항들을 업데이트 해준다.
  • 그리고 ViewModel 저장소(Repository)와 UI(Fragment / Activity) 사이에 통신 역할을 한다.
  • 이것은 저장소와 UI를 분리하여 각자의 역할을 명확하게 할 수 있다.

주의

  1. ViewModel에 context를 저장하면 안된다.
    -> 이유는 디바이스가 회전할 때 Activity가 제거되었다가 다시 생성되는데 이때, ViewModel은 제거된 것을 참조하기 때문에 메모리 누수가 발생한다. 그래서 application을 사용하기 위해 extends로 AndroidViewModel을 사용한다.

  2. ViewModel은 프로세스 종료 후 남아있지 않기 때문에 onSaveInstanceState() 함수를 대체하지 않는다.

LiveData??

LiveData는 중요한 개념 중 하나이다. 여기서는 간단하게 Room에서 어떻게 사용되는지만 보고 추후에 공부할 예정이다.

  • observer라는 것을 만들어 실제 변경이 일어나면 UI에 적용한다.
  • ViewModel에서 데이터베이스 호출 없이 코드를 쉽게 테스트할 수 있다.

예제는 Github에 있으니 확인할 수 있다.

참고