핀수로그
  • [Android] Room 살펴보기
    2023년 09월 28일 14시 17분 12초에 업로드 된 글입니다.
    작성자: 핀수
    728x90
    반응형

    이번에 (나름) 해커톤을 진행하면서 만들었던 서비스에 적용하기 위해 Room을 공부하는 시간을 가졌었다.

    이를 기록해보려고 한다!

    Room

    SQLite에 추상화 계층을 제공하여 SQLite를 완벽히 활용하면서 더 견고한 데이터베이스 액세스를 가능하게 한다.

    기존 안드로이드 로컬데이터베이스인 SQLite..에서 좀 더 개선된 라이브러리라고 생각이 되는데

    SQLite를 사용할 때보다 Room을 사용했을 때의 이점은 무엇이 있을까? 왜 더 개선된 것이 나왔을까?

    Room을 사용하면 좋은 점

    SQLite API를 직접 사용하는 것보다 여러 가지 이점이 있다고 한다.

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

    Room의 구성요소

    • 데이터베이스 클래스
      • 데이터베이스를 보유하고 앱의 영구 데이터와의 기본 연결을 위한 기본 액세스 포인트 역할
    • 데이터 항목
      • 앱 데이터베이스의 테이블을 나타냄
    • 데이터 액세스 객체 (DAO)
      • 앱이 데이터베이스의 데이터를 쿼리, 업데이트, 삽입, 삭제하는 데 사용할 수 있는 메서드 제공
    1. 데이터베이스 클래스는 데이터베이스와 연결된 DAO 인스턴스를 앱에 제공
    2. 앱은 DAO를 사용해 데이터베이스의 데이터를 연결된 데이터 항목 객체의 인스턴스로 검색할 수 있게 됨
    3. 앱은 정의된 데이터 항목을 사용해 상응하는 테이블의 행을 업데이트하거나 삽입할 새 행을 만들 수 있음

    종속성 추가

    2023년 8월 9일 기준 버전은 2.5.0이다.

    def room_version = "2.5.0"
    
    implementation "androidx.room:room-runtime:$room_version"
    annotationProcessor "androidx.room:room-compiler:$room_version"
    
    // To use Kotlin annotation processing tool (kapt)
    kapt "androidx.room:room-compiler:$room_version"
    // To use Kotlin Symbol Processing (KSP)
    ksp "androidx.room:room-compiler:$room_version"
    
    // optional - RxJava2 support for Room
    implementation "androidx.room:room-rxjava2:$room_version"
    
    // optional - RxJava3 support for Room
    implementation "androidx.room:room-rxjava3:$room_version"
    
    // optional - Guava support for Room, including Optional and ListenableFuture
    implementation "androidx.room:room-guava:$room_version"
    
    // optional - Test helpers
    testImplementation "androidx.room:room-testing:$room_version"
    
    // optional - Paging 3 Integration
    implementation "androidx.room:room-paging:$room_version"

    구현해보기

    단일 데이터 항목과 단일 DAO가 있는 Room 데이터베이스를 구현해보자.

    데이터 항목

    @Entity
    data class User (
        @PrimaryKey val id: Int,
        // 이름, 아이디, 비밀번호, 이메일, 생성시간, 수정시간
        val name: String,
        val userName: String,
        val password: String,
        val email: String,
        @ColumnInfo(name = "create_time") val createTime: Date,
        @ColumnInfo(name = "update_time") val updateTime: Date,
    )

    각 User 인스턴스는 앱 데이터베이스 User 테이블의 각 행을 의미한다.

    @Entity

    각 Room 항목을 해당 주석이 달른 클래스로 정의함 → 테이블을 의미

    기본 키를 구성하는 하나 이상의 열을 비롯해 데이터베이스의 상응하는 테이블에 있는 각 열의 필드가 포함

    그러니까 위의 User Entity에는 기본키를 비롯해

    이름, 아이디(userName), 비밀번호, 이메일, 생성 시간, 수정 시간이라는 필드가 포함되어 있는 것이다.

     

    보통 클래스의 이름으로 테이블의 이름이 결정되지만, 다르게 설정하고 싶다면

    아래와 같이 지정해주면 된다.

    SQLite의 테이블 및 열 이름은 대소문자를 구분하지 않음을 참고하자.

    @Entity(tableName = "users")
    data class User ()

    @PrimaryKey

    기본 키를 지정한다. 자동 ID를 할당하고 싶으면 아래와 같이 지정하면 된다.

    autoIncrement와 같은 의미로 보인다.

    @PrimaryKey(autoGenerate = true) val id: Int,

    기본 키를 복수로 가지고 싶다면 아래와 같이 지정하면 된다.

    @Entity(primaryKeys = ["firstName", "lastName"])
    data class User(
        val firstName: String?,
        val lastName: String?
    )

    @ColumnInfo

    마찬가지로 필드의 이름을 각 열의 이름으로 결정한다. 다르게 설정하고 싶다면

    아래와 같이 지정해주면 된다.

    @ColumnInfo(name = "update_time") val updateTime: Date

    데이터 액세스 객체 (DAO)

    user 테이블의 데이터와 상호작용하는 데 사용하는 메서드 제공

    DAO를 통해 앱 데이터베이스에 액세스하면 관심사 분리를 유지하는데 탁월하다고 한다.

    추가로 앱을 테스트할 때 데이터베이스 액세스도 더 쉽게 모의 처리할 수 있다고 한다.

    @Dao
    interface UserDao {
        /**
         * 사용자 전체 조회
         */
        @Query("SELECT * FROM user")
        fun getAll(): List<User>
    
        /**
         * 사용자 한 건 보기
         */
        @Query("SELECT * FROM user WHERE id = :userId")
        fun getUserById(userId: Int): User
    
        /**
         * 사용자 추가
         */
        // INSERT INTO user(id, name, username, password, email, createTime, updateTime)
        // VALUE (user.id, user.name, user.username, user.password, user.email, user.createTime, user.updateTime)
        @Insert
        fun insertUser(user: User)
    
        /**
         * 사용자 수정
         */
        // UPDATE user SET email = user.email WHERE id = user.id
        @Update
        fun updateUser(user: User)
    
        /**
         * 사용자 삭제
         */
        // DELETE * FROM user WHERE id = user.id
        @Delete
        fun deleteUser(user: User)
    }

    @Dao

    각 DAO를 인터페이스나 추상 클래스로 정의할 수 있다. (일반적으로 인터페이스를 사용한다고 한다.)

    어떤 경우든 해당 주석을 반드시 달아야 한다.

    @Query

    DAO 메서드의 종류 중 쿼리 메소드에 해당한다.

    해당 주석을 사용해 SQL 문을 작성한다.

    /**
     * 사용자 전체 조회
     */
    @Query("SELECT * FROM user")
    fun getAll(): List<User>

    사용자 한건을 조회해야하는 경우는 어떨까?

    사용자의 아이디를 입력받아야 한다.

    /**
     * 사용자 한 건 보기
     */
    @Query("SELECT * FROM user WHERE id = :userId")
    fun getUserById(userId: Int): User

    :userId 와 같은 방식으로 매개변수를 참조할 수 있다.

    @Insert, @Update, @Delete

    DAO 메서드의 종류 중 편의 메소드에 해당한다.

    코드를 보면 알겠지만 쿼리문을 작성하지 않아도 해당 기능을 수행해준다는 의미이다.

    간단한 경우에 해당하며 복잡한 명령을 수행하기 위해서는 쿼리메소드를 사용해야함을 잊지말자.

    데이터베이스

    데이터베이스를 보유할 AppDatabase 클래스를 정의해야한다.

    AppDatabase는 데이터베이스를 구성을 정의하고 영구 데이터에 대한 앱의 기본 액세스 포인트 역할을 한다.

    @Database(entities = [User::class], version = 1)
    abstract class AppDatabase: RoomDatabase() {
        abstract fun userDao(): UserDao
    }
    • Database 주석이 추가되어야 한다.
      • 연결된 데이터 항목 (테이블)을 모두 나열한 배열을 entities 이름으로 넘겨주어야 한다.
    • RoomDatabase를 확장하는 추상 클래스여야 한다.
    • 데이터베이스와 연결된 각 DAO 클래스에서 데이터베이스 클래스는 인수가 0개이고 DAO 클래스의 인스턴스를 반환하는 추상 메서드를 정의해야 한다.

     

    간략하게 Room에 대해 알아보고, 이를 적용하기 위해서는 어떻게 해야하는지에 대해 살펴보았다.

    공부를 하고 간 덕분에 프로젝트를 진행하면서 원하는 대로 Room을 사용할 수 있었다.

    다음 시간에는 Room과 Hilt를 같이 사용하며 알게 된 것을 기록하려고 한다.

     

     

    우리 존재 화이팅


    공부하며 작성된 글이라 잘못된 정보가 있을 수 있습니다.

    말씀해주시면 수정하겠습니다. 감사합니다.

    References

    아래 글을 참고하여 작성 되었습니다.

     

    Room을 사용하여 로컬 데이터베이스에 데이터 저장  |  Android 개발자  |  Android Developers

    Room 라이브러리를 사용하여 더 쉽게 데이터를 유지하는 방법 알아보기

    developer.android.com

     

    Room 지속성 라이브러리  |  Android 개발자  |  Android Developers

    Room 라이브러리 사용 방법을 알아봅니다.

    developer.android.com

     

    Room 항목을 사용하여 데이터 정의  |  Android 개발자  |  Android Developers

    Room 라이브러리의 일부인 항목을 사용하여 데이터베이스 테이블을 생성하는 방법 알아보기

    developer.android.com

     

    Room DAO를 사용하여 데이터 액세스  |  Android 개발자  |  Android Developers

    Room 라이브러리의 일부인 DAO(데이터 액세스 개체)를 사용하여 데이터베이스 테이블을 수정하는 방법 알아보기

    developer.android.com

     

     
     

     

     

    728x90
    반응형
    댓글