[안드로이드 Jetpack Compose Paging3 시리즈] Room Database 세팅하기 #7

2024. 2. 25. 11:30·안드로이드/Compose Paging3
반응형

1. RemoteMediator 구현을 위해 Room Database 세팅

안녕하세요. 이번 포스팅에서는 Jetpack Compose Paging3 라이브러리에서 RemoteMediator를 구현하기 위해 Room Database 세팅을 진행하겠습니다. 지난 포스팅에서 설명했듯이, RemoteMediator는 Paging3 라이브러리로 불러온 데이터를 로컬 데이터베이스에 저장한다고 말씀드렸습니다. 그래서 먼저 Room Database를 세팅한 후, RemoteMediator를 구현해야 합니다.

Room Database 세팅을 위한 파일 생성
Room Database 세팅을 위한 파일 생성

2. Data Layer에 데이터베이스 관련 클래스 및 인터페이스 생성

Data Layer에 Room 데이터베이스 구성을 위한 파일들을 생성하겠습니다. 어렵게 생각하지 말고 간단하게 생각하면 쉽습니다. 데이터베이스가 구성되기 위해서는 Database, Table, DAO, DTO 등이 필요합니다. 저는 에러를 피하고 자동완성을 활용하기 위해 역방향으로 클래스 및 인터페이스를 생성하겠습니다.

아래 코드를 보면 RemoteKey 관련된 파일을 생성한 것을 확인할 수 있는데, 제가 사용하는 API가 page를 파라미터로 받아서 데이터를 돌려주기 때문에 마지막 페이지를 저장하기 위해서 만들었습니다.

만약, page 기반이 아닌 마지막 아이템 ID를 기준으로 페이징 처리를 하는 cursor 기반의 API라면 RemoteKey 저장은 하지 않아도 됩니다. RemoteMediator에서 마지막 아이템을 조회할 수 있기 때문입니다.

2-1. DTO(Data Transfer Object) 만들기

DTO는 계층 간에 데이터를 주고받기 위해서 사용하는 객체입니다. 그래서 DTO는 로직을 갖지 않는 data class 역할만 합니다. Room 데이터베이스에서는 data class에 @Entity 어노테이션을 추가해서 테이블을 생성할 수 있습니다. 여기서는 테이블을 만들 때 사용한 data class가 곧 DTO의 역할도 하게 됩니다.

// MovieDbData.kt
@Entity(tableName = "movies")
data class MovieDbData(
    @PrimaryKey val id: Int,
    val description: String,
    val image: String,
    val backgroundUrl: String,
    val title: String,
    val category: String,
)

fun MovieDbData.toDomain() = MovieEntity(
    id = id,
    title = title,
    description = description,
    image = image,
    category = category,
    backgroundUrl = backgroundUrl
)
// MovieRemoteKeyDbData.kt
@Entity(tableName = "movies_remote_keys")
data class MovieRemoteKeyDbData(
    @PrimaryKey(autoGenerate = true) val id: Int = 0,
    val prevPage: Int?,
    val nextPage: Int?
)

2-2. DAO(Data Access Object) 만들기

DAO는 데이터베이스에 접근해서 데이터를 저장하거나 가져오는 역할을 하는 객체입니다. Room 라이브러리에서는 interface로 정의하면 됩니다. 아래 MovieDao의 pagingSource 함수를 보면 반환타입이 PagingSource인 것을 확인할 수 있습니다. Room에서 PagingSource를 반환하게 되면 Pager 객체가 해당 테이블을 페이징 된 데이터 소스로 사용할 수 있습니다.

// MovieDao.kt
@Dao
interface MovieDao {
    @Query("SELECT * FROM movies ORDER BY category, id")
    fun pagingSource(): PagingSource<Int, MovieDbData>
    
    @Query("SELECT * FROM movies ORDER BY category,id")
    fun getMovies(): List<MovieDbData>
    
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun saveMovies(movies: List<MovieDbData>)
    
    @Query("DELETE FROM movies")
    suspend fun clearMoviesExceptFavorites()
}
// MovieRemoteKeyDao.kt
@Dao
interface MovieRemoteKeyDao {
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun saveRemoteKey(keys: MovieRemoteKeyDbData)

    @Query("SELECT * FROM movies_remote_keys WHERE id=:id")
    suspend fun getRemoteKeyByMovieId(id: Int): MovieRemoteKeyDbData?

    @Query("DELETE FROM movies_remote_keys")
    suspend fun clearRemoteKeys()

    @Query("SELECT * FROM movies_remote_keys WHERE id = (SELECT MAX(id) FROM movies_remote_keys)")
    suspend fun getLastRemoteKey(): MovieRemoteKeyDbData?
}

2-3. MovieDatabase 만들기

위에서 생성한 Table, DTO, DAO를 이용해서 Database 클래스를 만들겠습니다. Database도 마찬가지로 @Database 어노테이션을 추가해서 생성할 수 있습니다. 이때, entities 프로퍼티에 위에서 만든 Table인 MovieDbData, MovieRemoteKeyDbData를 넣어줍니다.

// MovieDatabase.kt
@Database(
    entities = [MovieDbData::class, MovieRemoteKeyDbData::class],
    version = 1,
    exportSchema = false
)
abstract class MovieDatabase: RoomDatabase() {
    abstract fun movieDao(): MovieDao
    abstract fun movieRemoteKeyDao(): MovieRemoteKeyDao
}

3. Room Database 내용 정리

이번 포스팅에서는 안드로이드 Jetpack Compose Paging3 라이브러리의 RemoteMediator 구현을 위해서 Room database에 필요한 클래스 및 인터페이스를 정의했습니다.

MovieDao를 보면 PagingSource를 반환하는 pagingSource 함수를 만들었는데, Pager 객체를 생성할 때 pagingSourceFactory로 해당 함수를 제공하면 Paging3 라이브러리가 해당 테이블을 페이징 된 데이터 소스로 사용할 수 있습니다.

다음 포스팅에서는 RemoteMediator를 구현하고 Pager 객체를 생성하겠습니다.

저작자표시 비영리 변경금지 (새창열림)

'안드로이드 > Compose Paging3' 카테고리의 다른 글

[안드로이드 Jetpack Compose Paging3 시리즈] RemoteMediator 구현하기 #9  (0) 2024.02.27
[안드로이드 Jetpack Compose Paging3 시리즈] Local Data Source 생성하기 #8  (0) 2024.02.26
[안드로이드 Jetpack Compose Paging3 시리즈] RemoteMediator 파헤치기 #6  (0) 2024.02.24
[안드로이드 Jetpack Compose Paging3 시리즈] LazyVerticalGrid 구현 및 Navigation #5  (0) 2024.02.23
[안드로이드 Jetpack Compose Paging3 시리즈] LazyColumn 구현 #4  (0) 2024.02.22
'안드로이드/Compose Paging3' 카테고리의 다른 글
  • [안드로이드 Jetpack Compose Paging3 시리즈] RemoteMediator 구현하기 #9
  • [안드로이드 Jetpack Compose Paging3 시리즈] Local Data Source 생성하기 #8
  • [안드로이드 Jetpack Compose Paging3 시리즈] RemoteMediator 파헤치기 #6
  • [안드로이드 Jetpack Compose Paging3 시리즈] LazyVerticalGrid 구현 및 Navigation #5
코딩덕
코딩덕
안드로이드, 리액트 등의 개발 노하우와 최신 AI 기술을 다루는 기술 블로그입니다. 실무 중심의 경험을 바탕으로 마주한 문제와 해결 과정을 체계적으로 기록하며, 개발자에게 실질적으로 도움 되는 프로그래밍 팁과 인사이트를 쉽고 명확하게 공유하고자 합니다.
  • 코딩덕
    개발자가 들려주는 IT 이야기
    코딩덕
  • 전체
    오늘
    어제
    • 분류 전체보기 (66)
      • 안드로이드 (62)
        • 멀티 모듈 (11)
        • 클린 아키텍처 (11)
        • 트러블 슈팅 (5)
        • 코틀린 (3)
        • 코루틴 (2)
        • Compose (1)
        • Compose UI (6)
        • Compose Dialog (8)
        • Compose Paging3 (11)
        • Compose State (2)
        • Util (1)
      • Github (3)
        • PR Template (2)
        • AI Code Review (1)
      • 리액트 (1)
        • NextJs (1)
  • 블로그 메뉴

    • 홈
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    jsonadapter
    sealed class
    OnBackPressedDispatcher
    클린 아키텍처
    코틀린
    Dialog
    ViewModel
    ScrollView
    flow
    Clean Architecture
    UI Layer
    트러블슈팅
    Gradle
    MutableState
    dynamic json
    enum class
    Jetpack Compose
    LazyRow
    multi module
    데이터 레이어
    멀티 모듈
    코루틴
    pager
    pr template
    Usecase
    recyclerview
    paging3
    ai code review
    Github
    안드로이드
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
코딩덕
[안드로이드 Jetpack Compose Paging3 시리즈] Room Database 세팅하기 #7
상단으로

티스토리툴바