[TIL] Room Library

박봉팔·2024년 1월 24일
0

Room

어제 알아봤던 Sheard Preference와 같이 로컬에 데이터를 저장할수 있게 만들어준다.
SQLite를 보다 쉽게 사용할 수 있도록 해주는 데이터베이스 객체 매핑 라이브러리 이다.


SQL? SQLite? Query?

Room을 사용하기에 앞서 데이터베이스를 조작하기위해 기본적인 데이터 베이스에 대한 용어의 정리가 필요했다.


- SQLite

관계형 데이터베이스관리 시스템을 제공하는 라이브러리를 말한다.


- SQL (Structured Query Language)

관계형 데이터베이스에서 데이터를 정의, 조작, 제어하기위해 사용하는 표준화된 언어를 말한다.
데이터베이스에 대한 Query를 작성할때 사용한다.
(Kotlin이나 Java와 같은 데이터 베이스 조작에 사용되는 언어라고 생각하면 될 듯하다.)


- Query

데이터 베이스에서 정보를 조작하거나 요청하기 위해 사용되는 문장이나 명령어를 의미한다.


즉, SQL(언어)를 사용하여 SQLite(라이브러리)를 사용해 데이터 베이스에 Query(명령)를 정의해 데이터를 요청하거나 조작한다고 생각하면 쉽다.


그래서 Room은?

결국 Room이란 보다 쉽게 Query를 사용할 수 있도록 해주는 라이브러리라고 할 수 있다.
(SQL을 사용하지 않아도 조작이 가능하게 하는)

Room사용시 장점으로는 크게 두가지를 꼽아볼 수 있는다.


1. 컴파일 타임에 Query를 검증한다.

컴파일 타임에서 검증을 하기때문에 런타임에서 오류가 생기는 것을 방지한다.
즉, 잘못된 Query나 오타를 앱이 구동되기 이전에 알려주기 때문에 안정성을 높일 수 있다.


2. Query결과를 LiveData로 생성할 수 있다.

Query결과를 LiveData로 만들 수 있기떄문에 데이터 베이스가 변동될경우 즉시 UI를 자동으로 업데이트 할 수 있다.


Room의 구성요소

Room라이브러리 사용을 위해서는 3가지의 기본 구성요소가 필요하다.


1. 데이터 베이스 클래스 (@Database)

데이터 베이스를 보유하고 앱의 영구적인 데이터와 연결되는 기본 액세스 포인트 역할을 한다.

abstract classRoomDatabase클래스를 상속해서 선언한뒤, @Database()어노테이션을 사용해 데이터베이스 클래스를 만든다.

@Database()어노테이션은 다양한 매개변수를 가진다.

  • entities: 데이터 베이스에 포함되는 엔티티(테이블)을 나타낸다.

  • exportSchema: true일 경우 스키마를 내보낸다.
    true일경우 스키마를 내보내며, 주로 버전 업그레이드시 유용하게 사용된다.

  • version: 데이터 베이스의 버전을 나타낸다.
    정수값으로 표현되며, 스키마가 변경되면 버전번호를 증가시켜 업그레이드 관리를 할 수 있다.

위의 내용들을 사용해 아래와 같이 어노테이션을 정의할 수 있다.

@Database(
    entities = [Student::class], // Student클래스의 내용을 엔티티로 사용
    exportSchema = false, // 스키마를 내보내지 않음
    version = 1 // 버전 1 (스키마가 변경 될 경우 2로 변경)
)

2. 데이터 항목: 엔티티 (@Entity)

앱 데이터 베이스의 테이블을 나타내는 클래스로, data class로 생성한다.

@Entity(tableName = "student_table")
data class Student(
    @PrimaryKey		// 다른 값과 겹치지 않는 고유한 키를 생성
    @ColumnInfo(name = "student_id") // name프로퍼티에 "student_id"로 전달받은 값을 대입
    val id: Int,
    val name: String
)

@Entity어노테이션을 사용하며 () 안에 테이블의 이름을 적어준다.

data class내부에는 테이블에 사용될 각 항목을 만들어준다.


- 테이블?

테이블이란 데이터 베이스에서 실제로 데이터가 저장되는 구조로, 아래와 같은 표로 이해하면 편하다.

하나의 엔티티는 일반적인 표의 가로 항목의 속성을 말한다고 할 수 있다.


3. 데이터 액세스 객체: Dao(Data Acesse Object) (@Dao)

앱에 데이터 베이스의 데이터를 Query, 업데이트, 삽입, 삭제하는데 필요한 메서드를 제공하는 객체이다.

interface@Dao어노테이션을 사용해서 생성하며, 내부의 메서드에 필요한 어노테이션을 사용해 Query삽입, 삭제를 해주는 메서드를 생성한다.

@Dao
interface MyDao {
	// 삽입을 해주는 메서드 student값을 삽입해주며, 같은 값이 있을 경우 대체해준다.
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertStudent(student: Student)

	// 작성한 Query를 실행 아래의 경우 student_table의 모든 항목을 라이브데이터에 전달한다.
    @Query("SELECT * FROM student_table")
    fun getAllStudent(): LiveData<List<Student>>

	// student_table를 가져와 전달받은 sname의 값과 일치하는 항목을 반환한다.
    @Query("SELECT * FROM student_table WHERE name = :sname")
    suspend fun getStudentByName(sname: String): List<Student>

	// student의 값을 받아 삭제한다.
    @Delete
    suspend fun deleteStudent(student: Student)
}

Room 사용방법

@Database(
    entities = [Student::class],
    exportSchema = false, version = 1
)
abstract class MyDatabase : RoomDatabase() {
    abstract fun getMyDao(): MyDao

    companion object {
        private var INSTANCE: MyDatabase? = null

        fun getDatabase(context: Context): MyDatabase {
            if (INSTANCE == null) {
                INSTANCE = Room.databaseBuilder(context, MyDatabase::class.java, "school_database")
                    .build()
            }
            return INSTANCE as MyDatabase
        }
    }
}

abstract class에 싱글톤 패턴으로 데이터 베이스를 반환하는 메서드를 만들어준다.
매서드 내에서 Room.databaseBuilder를 사용해 매개변수로, 전달받은 context데이터베이스 클래스, 데이터 베이스의 이름을 넣어준뒤 데이터베이스를 build하여 반환해주면 데이터 베이스가 생성된다.

abstract 메서드Dao를 반환할 수 있도록 만들어주면 준비 끝.


 val myDao by lazy { MyDatabase.getDatabase(applicationContext).getMyDao() }

위와 같이 데이터베이스를 생성하고 Dao를 가지고 오면 이제 myDao를 사용해 Query, 삽입, 삭제명령을 사용하는게 가능해진다.


오늘은 어땠나요?

정말 할게 많은데 왜 난 아직도 헤어나오지 못하는가...

알면 알수록 파고드는 나란 사람...

적당히 좀 파줘... 미래의 나...

profile
개발 첫걸음! 가보자구!

0개의 댓글