[Android/Kotlin] Room Database 사용하기

SoyoungLee·2022년 8월 2일
0

안드로이드/코틀린

목록 보기
41/68
post-thumbnail
post-custom-banner

💌 [Android/Kotlin] ROOM Database 사용하기

📌 Room 이란?

  • 안드로이드에서 앱의 데이터를 저장하는 방법은 크게 파일, 데이터베이스, 프리퍼런스로 나뉜다.
    그 중 데이터 베이스 프로그래밍을 이용하여 안드로이드 폰에서 DB를 관리하는 오픈소스 SQLite 가 있다.
  • Room은 SQLite를 완벽히 활용하면서 원활한 데이터베이스 액세스가 가능하도록 SQLite에 추상화 계층을 제공한다.

💜 Room의 이점

  • SQL 쿼리의 컴파일 시간 확인
  • 반복적이고 오류가 발생하기 쉬운 상용구 코드를 최소화하는 편의 주석
  • 간소화된 데이터베이스 이전 경로

📌 설정

build.gradle (:app)

plugins {
	id 'kotlin-kapt'
}

dependencies {
	// ROOM Database 사용
    implementation("androidx.room:room-runtime:2.4.3")
    annotationProcessor("androidx.room:room-compiler:2.4.3")
    kapt("androidx.room:room-compiler:2.4.3")
    implementation("androidx.room:room-ktx:2.4.3")
}

📌 기본 구성 요소

  • Database : 데이터 베이스를 생성하고 관리하는 데이터베이스 객체 만들기 위한 추상 클래스.
  • Entity : 앱 데이터베이스의 테이블.
  • DAO (Data Access Object) : 데이터에 접근할 수 있는 메소드(삽입,삭제,조회 등)를 정의해놓은 인터페이스.

📌 Entity 정의

  • 데이터 베이스의 테이블 행 역할.
  • 반드시 PrimaryKey가 있어야 함. (자동 생성은 autoGenerate = true 속성 추가)
  • 기본적으로 클래스 이름이 테이블명이지만 따로 지정은 @Entity(tableName = " ")을 사용.
@Entity(tableName = "table_bookmark")
data class ParkBookmarkEntity(
    @PrimaryKey
    val parkingCode: String = "",
    val parkingName: String = "",
    val addr: String = "",
    val lat: Double = 0.0,
    val lng: Double = 0.0,
    val tel: String = "",
    val operation_rule_nm: String = "",
    var isSelected:Boolean = false
)

📌 DAO 정의

  • 인터페이스나 추상 클래스로 정의 가능.
  • 일반적으로 인터페이스로 구현. @Dao 어노테이션 필수.
  • 앱 데이터베이스의 데이터와 상호작용하는 메소드를 하나 이상 정의.
@Dao
interface ParkDAO {

    @Query("SELECT * FROM table_bookmark")
    fun getAll(): List<ParkBookmarkEntity>

    // parkingCode 에 해당하는 selected 값 가져오기
    @Query("SELECT isSelected FROM table_bookmark WHERE parkingCode = :parkingCode")
    fun getBookmark(parkingCode: String) : Boolean

    // bookmark 저장 - 중복 값 충돌 발생 시 새로 들어온 데이터로 교체.
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    fun saveBookmark(bookmarkEntity: ParkBookmarkEntity)

    // bookmark 삭제
    @Delete
    fun deleteBookmark(bookmarkEntity: ParkBookmarkEntity)
}

📌 Database 클래스 정의

  • version 은 Entity 의 구조 변경해야 하는 일이 생겼을 때 이전 구조와 현재 구조를 구분해주는 역할.
@Database(entities = [ParkBookmarkEntity::class], version = 1)
abstract class ParkDatabase : RoomDatabase() {
    abstract fun parkDao(): ParkDAO

    // 데이터 베이스 객체를 싱글톤으로 인스턴스.
    companion object {
        private var instance: ParkDatabase? = null

        @Synchronized
        fun getInstance(context: Context): ParkDatabase? {
            if (instance == null)
                synchronized(ParkDatabase::class) {
                    instance = Room.databaseBuilder(
                        context.applicationContext,
                        ParkDatabase::class.java,
                        "park.db"
                    )
                        .build()
                }
            return instance
        }

        fun destroyInstance() {
            instance = null
        }
    }
}

📌 사용

  • 서울시 공공데이터의 주차장 데이터를 가져와 맵에 뿌려준 후, 즐겨찾기에 저장하는 기능을 구현해보겠다.
  • 데이터 베이스 작업은 메인 스레드에서 작업할 수 없으므로 코루틴 을 이용한다.
class ParkBottomSheetFragment(val mContext : Context) : BottomSheetDialogFragment() {

	private var db: ParkDatabase? = null

	override fun onCreateView(...): View? {
        super.onCreateView(inflater, container, savedInstanceState)
        
        // 생략
        
        db = ParkDatabase.getInstance(mContext)

}

💜 즐겨찾기 하기

  • 즐겨찾기 버튼을 selector 를 이용하여 UI에 변화를 준다.
  • 즐겨찾기 전
  • 즐겨찾기 후
// 버튼 xml
<androidx.appcompat.widget.AppCompatButton
            android:id="@+id/btn_bookmark"
            android:layout_width="wrap_content"
            android:layout_height="36dp"
            android:background="@drawable/selector_btn_bookmark"
            android:drawableLeft="@drawable/ic_heart"
            android:paddingHorizontal="@dimen/margin_20"
            android:layout_marginEnd="10dp"
            android:text="즐겨찾기"
            android:textColor="@color/white"
            android:textSize="16dp"
            android:textStyle="bold" />
            
// selector
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_selected="false">
        <shape android:shape="rectangle">
            <solid android:color="@color/main_color" />
        </shape>
    </item>
    <item android:state_selected="true">
        <shape android:shape="rectangle">
            <solid android:color="@color/main_purple1" />
        </shape>
    </item>
</selector>
// 즐겨찾기 저장하기
btnBookmark.setOnClickListener {
	// UI 와 상호작용하기 위해 사용.
	CoroutineScope(Dispatchers.Main).launch {
		val temp: Deferred<Boolean> = async(Dispatchers.IO) { // async 로 결과를 반환
			val isBookmarked = db!!.parkDao().getBookmark(data.PARKING_CODE)
			if (isBookmarked) { // 이미 즐겨찾기 되어있으면 삭제
				db!!.parkDao().deleteBookmark(bookmarkData)
				false
                
                
			} else { // 없으면 즐겨찾기 저장
				db!!.parkDao().saveBookmark(bookmarkData)
				true
			}
		}
        			// UI 변경
                    val selected = temp.await() // async 작업이 완료 되고 난 후 호출.
                    it.isSelected = selected
                }
            }

💜 즐겨찾기 리스트 가져오기

// 즐겨찾기 된 데이터 가져오기
btnGetData.setOnClickListener {
		CoroutineScope(Dispatchers.IO).launch { // 코루틴 사용 비동기로 실행.
			val parkData = db!!.parkDao().getAll()
			Utils.Log("db 조회 -> $parkData")
		}
}

💜 즐겨찾기 삭제하기

// 즐겨찾기 삭제하기
btnDeleteData.setOnClickListener {
	CoroutineScope(Dispatchers.IO).launch { // 코루틴 사용 비동기로 실행.
		db!!.parkDao().deleteBookmark(bookmarkData)
			Utils.Log("즐겨찾기 삭제 완료")
		}
}

순서대로 클릭해서 즐겨찾기를 하고, 리스트를 가져오고, 삭제한 후, 잘 찍히는 로그들을 확인할 수 있다.

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

profile
Android Developer..+ iOS 슬쩍 🌱 ✏️끄적끄적,,개인 기록용 👩🏻‍💻
post-custom-banner

0개의 댓글