[Kotlin] Room DB

Boknami·2023년 8월 26일
0

코틀린

목록 보기
9/19

🙄 Why Use?

현재 진행 중인 프로젝트에서 앱 내부에 데이터를 저장하고 사용할 일이 생겼다.

1.자동 로그인
회원가입 시 내부 데이터에 정보를 저장하고, 시작 액티비티 부분에 내부 데이터에 id,pw를 서버에 보내고 DB쪽과 일치한다면 바로 메인 화면으로 이동하게끔.

자동 로그인에서 필요한 것은 id,pw 근데 이걸 한 사용자가 다양하게 List적으로 보관할 필요가 없긴해서 이건 그냥 txt파일로 저장하고 불러올 것 같다. 다만 pw저장 시 해시 등에 기법을 사용해야할 것 같다.

2.변하지 않는 데이터 제공
재난 상황이 발생했을 때 가이드라인 데이터를 제공해야하는데 DB나 서버가 가지고 있기 보다는 그냥 앱에 저장된 걸 사용하는 게 편하다는 의견이 있었고 크게 클라이언트쪽에 성능 저하가 발생하거나 그런 일이 없을 것 같아서 클라이언트쪽에서 저장하고 바로 불러오는 형식으로 하려한다.

이건 재난에 따라 홍수, 지진 등에 따라 DB로 표현할 수 있을 것 같긴하다.

😶 What?

내부 데이터를 사용해본 적이 없어서 처음에 SQLite와 Room이 서로 다른 각각 하나의 방식인 줄 알았다.

전혀 그렇지 않고 SQLite를 편하게 사용할 수 있게 하는 것이 Room이다.

🙂 Setting

bulid.gradle.kts (앱 수준)을 열고

  • plugins

plugins {
    id("com.android.application")
    id("org.jetbrains.kotlin.android")
    id ("kotlin-kapt")
}
  • dependencies
// ROOM Database 사용
    implementation("androidx.room:room-runtime:2.4.3")
    annotationProcessor("androidx.room:room-compiler:2.4.3")
    implementation("androidx.room:room-ktx:2.4.3")
    kapt("androidx.room:room-compiler:2.4.3")
    //-> 이건 sync now 한 번 하고 나중에 하는 게 인식이 잘 되는 것 같다! 

😏 RoomDB의 구성!

  • Database
    DB를 생성하고 관리하는 데이터베이스 객체 만들기 위한 추상 클래스

  • Entity
    테이블

  • DAO (Data Access Object)
    DB를 삽입,삭제,조회 등을 정의해놓은 인터페이스.

😎 RoomDB를 사용해보자!

테이블 생성과 CRUD사용 준비

//테이블을 만들자
@Entity
data class User(
    @PrimaryKey val uid: Int,
    @ColumnInfo(name = "first_name") var firstName: String?,
    @ColumnInfo(name = "last_name") var lastName: String?
)

//다오(DB와 상호작용(CRUD)
@Dao
interface UserDao {
    @Query("SELECT * FROM user")
    fun getAll(): List<User>

    @Query("SELECT * FROM user WHERE uid IN (:userIds)")
    fun loadAllByIds(userIds: IntArray): List<User>

    @Query("SELECT * FROM user WHERE first_name LIKE :first AND " +
            "last_name LIKE :last LIMIT 1")
    fun findByName(first: String, last: String): User

    @Insert
    fun insertAll(vararg users: User)

    @Delete
    fun delete(user: User)
}

//DB클래스
@Database(entities = [User::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
    abstract fun userDao(): UserDao
}

DB인스턴스 생성! 사용할 준비 완료

//데이터베이스 인스턴스 생성
        val db = Room.databaseBuilder(
            applicationContext,
            AppDatabase::class.java, "database-name"
        ).build()

        //DAO인스턴스 가져오기..이제 사용하면 된다!
        val userDao = db.userDao()

오류 발생

  1. 실행이 안됌
    GradleException: 'compileDebugJavaWithJavac' task (current target is 1.8) and 'kaptGenerateStubsDebugKotlin' task (current target is 17 )

':app:kaptGenerateStubsDebugKotlin' 작업에 대한 실행에 실패했습니다.
'compileDebugJavaWithJavac' 태스크(현재 대상은 1.8)와 'kaptGenerateStubsDebugKotlin' 태스크(현재 대상은 17) jvm 대상 호환성을 동일한 Java 버전으로 설정해야 합니다.

라고 한다..해당 에러는 타 블로그 분을 참고해서 해결!
https://velog.io/@mraz3068/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-%EC%8A%A4%ED%8A%9C%EB%94%94%EC%98%A4-%EB%B9%8C%EB%93%9C-%EA%B4%80%EB%A0%A8-%EC%98%A4%EB%A5%98JDK-version-17-1.8-11-%EB%AC%B4%ED%95%9C-%EB%B0%98%EB%B3%B5


  1. DB는 메인스레드에서 실행 불가!

위와 같이 바로 메인스레드에서 처리하려면 오류가 난다..메인스레드가 UI와의 작용도 처리해야하고 하니까 아마 다른 스레드 사용을 유도하는 것 같다!

😎 메인스레드 외에서 DB작업

  • 다음 추가
// DB관련 작업은 타 쓰레드에서!!
    implementation ("androidx.lifecycle:lifecycle-runtime-ktx:2.4.0")
    implementation ("androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.0")
    implementation ("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.2")
  • 코드 작성
    혹시나! 이 코드를 따라서 작성하시는 분이 있다면 이렇게 하면 안됩니다!
    처음 실행할 때는 문제 없으나 2번째부터는 이미 DB에 들어간 값이 있는데도 일단 실행하면 insert하도록 코드가 되어있으니 오류발생!! 그렇니까 버튼을 눌렀을 때로 로직을 분리해두던가 하는 게 굿!
//데이터베이스 인스턴스 생성
        val db = Room.databaseBuilder(
            applicationContext,
            AppDatabase::class.java, "testDB-230826"
        ).build()

        //DAO인스턴스 가져오기..이제 사용하면 된다!
        val userDao = db.userDao()

        val user1 = User(uid = 1, firstName = "John", lastName = "Doe")

        // 액티비티의 lifecycleScope 내에서 코루틴 사용
        lifecycleScope.launch(Dispatchers.IO) {
            // IO 스레드에서 사용자 삽입
            userDao.insertAll(user1)

            // IO 스레드에서 사용자 검색
            val users: List<User> = userDao.getAll()

            // 메인 스레드에서 UI 업데이트
            launch(Dispatchers.Main) {
                Log.d("테스트", users.toString())
                inf.text = users.toString()
            }
        }

완성

참고

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

0개의 댓글