쿼리가 UI를 차단하지 않도록 Room은 기본 스레드에서 데이터베이스 액세스를 허용하지 않습니다. 이 제한사항은 DAO 쿼리를 비동기식으로 만들어야 함을 의미합니다. Room 라이브러리에는 비동기 쿼리 실행을 제공하는 여러 다양한 프레임워크와의 통합이 포함되어 있습니다.
DAO 쿼리는 세 가지 카테고리로 분류됩니다.
- 원샷 쓰기 쿼리: 데이터베이스에서 데이터를 삽입하거나 업데이트하거나 삭제합니다.
- 원샷 읽기 쿼리: 데이터베이스에서 데이터를 한 번만 읽고 그 시점의 데이터베이스 스냅샷과 함께 결과를 반환합니다.
- 관찰 가능한 읽기 쿼리: 기본 데이터베이스 테이블이 변경될 때마다 데이터베이스에서 데이터를 읽고 이러한 변경사항을 반영하는 새 값을 내보냅니다.
언어 및 프레임워크 옵션
Room은 특정 언어 기능 및 라이브러리와의 상호 운용성을 위한 통합 지원을 제공합니다. 다음 표는 쿼리 유형 및 프레임워크에 기반한 관련 반환 유형을 보여줍니다.
쿼리 유형 | Kotlin 언어 기능 | RxJava | Guava | Jetpack 수명 주기 |
---|---|---|---|---|
원샷 쓰기 | 코루틴(suspend ) |
Single<T> , Maybe<T> ,
Completable |
ListenableFuture<T> |
해당 사항 없음 |
원샷 읽기 | 코루틴(suspend ) |
Single<T> , Maybe<T> |
ListenableFuture<T> |
해당 사항 없음 |
관찰 가능한 읽기 | Flow<T> |
Flowable<T> , Publisher<T> ,
Observable<T> |
해당 사항 없음 | LiveData<T> |
이 가이드에서는 이러한 통합을 사용하여 DAO에서 비동기 쿼리를 구현할 수 있는 세 가지 방법을 보여줍니다.
Flow 및 코루틴을 사용하는 Kotlin
Kotlin은 서드 파티 프레임워크 없이 비동기 쿼리를 작성할 수 있는 언어 기능을 제공합니다.
- Room 2.2 이상에서는 Kotlin의 흐름 기능을 사용하여 관찰 가능한 쿼리를 작성할 수 있습니다.
- Room 2.1 이상에서는
suspend
키워드를 사용하여 Kotlin 코루틴으로 DAO 쿼리를 비동기식으로 만들 수 있습니다.
RxJava를 사용하는 Java
앱에서 Java 프로그래밍 언어를 사용하면 RxJava 프레임워크의 특수 반환 유형을 사용하여 비동기 DAO 메서드를 작성할 수 있습니다. Room은 다음 RxJava 2 반환 유형을 지원합니다.
- 원샷 쿼리의 경우 Room 2.1 이상은
Completable
님,Single<T>
, 및Maybe<T>
반환합니다. - 관찰 가능한 쿼리의 경우 Room은 다음을 지원합니다.
Publisher<T>
님,Flowable<T>
, 및Observable<T>
반환합니다.
또한 Room 2.3 이상에서는 RxJava 3을 지원합니다.
LiveData 및 Guava를 사용하는 Java
앱에서 Java 프로그래밍 언어를 사용하는데 RxJava 프레임워크는 사용하고 싶지 않다면 다음 대안을 사용하여 비동기 쿼리를 작성할 수 있습니다.
- Jetpack의
LiveData
래퍼 클래스를 사용하여 관찰 가능한 비동기 쿼리를 작성할 수 있습니다. - 이
ListenableFuture<T>
드림 래퍼를 사용하여 비동기 원샷 쿼리를 작성합니다.
비동기 원샷 쿼리 작성
원샷 쿼리는 데이터베이스 작업으로, 한 번만 실행되며 실행 시점의 데이터 스냅샷을 가져옵니다. 다음은 비동기 원샷 쿼리를 보여주는 예입니다.
Kotlin
@Dao interface UserDao { @Insert(onConflict = OnConflictStrategy.REPLACE) suspend fun insertUsers(vararg users: User) @Update suspend fun updateUsers(vararg users: User) @Delete suspend fun deleteUsers(vararg users: User) @Query("SELECT * FROM user WHERE id = :id") suspend fun loadUserById(id: Int): User @Query("SELECT * from user WHERE region IN (:regions)") suspend fun loadUsersByRegion(regions: List<String>): List<User> }
Java
@Dao public interface UserDao { @Insert(onConflict = OnConflictStrategy.REPLACE) public Completable insertUsers(List<User> users); @Update public Completable updateUsers(List<User> users); @Delete public Completable deleteUsers(List<User> users); @Query("SELECT * FROM user WHERE id = :id") public Single<User> loadUserById(int id); @Query("SELECT * from user WHERE region IN (:regions)") public Single<List<User>> loadUsersByRegion(List<String> regions); }
Java
@Dao public interface UserDao { // Returns the number of users inserted. @Insert(onConflict = OnConflictStrategy.REPLACE) public ListenableFuture<Integer> insertUsers(List<User> users); // Returns the number of users updated. @Update public ListenableFuture<Integer> updateUsers(List<User> users); // Returns the number of users deleted. @Delete public ListenableFuture<Integer> deleteUsers(List<User> users); @Query("SELECT * FROM user WHERE id = :id") public ListenableFuture<User> loadUserById(int id); @Query("SELECT * from user WHERE region IN (:regions)") public ListenableFuture<List<User>> loadUsersByRegion(List<String> regions); }
관찰 가능한 쿼리 작성
관찰 가능한 쿼리는 읽기 작업으로, 쿼리에서 참조하는 테이블이 변경될 때마다 새 값을 내보냅니다. 이를 사용하여 기본 데이터베이스의 항목이 삽입되거나 업데이트되거나 삭제될 때 표시된 항목 목록을 최신 상태로 유지할 수 있습니다. 다음은 관찰 가능한 쿼리를 보여주는 예입니다.
Kotlin
@Dao interface UserDao { @Query("SELECT * FROM user WHERE id = :id") fun loadUserById(id: Int): Flow<User> @Query("SELECT * from user WHERE region IN (:regions)") fun loadUsersByRegion(regions: List<String>): Flow<List<User>> }
Java
@Dao public interface UserDao { @Query("SELECT * FROM user WHERE id = :id") public Flowable<User> loadUserById(int id); @Query("SELECT * from user WHERE region IN (:regions)") public Flowable<List<User>> loadUsersByRegion(List<String> regions); }
Java
@Dao public interface UserDao { @Query("SELECT * FROM user WHERE id = :id") public LiveData<User> loadUserById(int id); @Query("SELECT * from user WHERE region IN (:regions)") public LiveData<List<User>> loadUsersByRegion(List<String> regions); }
추가 리소스
비동기 DAO 쿼리에 관한 자세한 내용은 다음 추가 리소스를 참고하세요.