RoomDatabase

소정·2025년 5월 7일
0

Kotlin

목록 보기
39/40

[1] 룸데이터베이스란?

[2] 사용방법

1. Gradle 의존성 추가

app 수준 그래이들에서 의존성 추가

plugins {
	id("org.jetbrains.kotlin.kapt")
}


// Room Persistence Library
    implementation("androidx.room:room-runtime:2.6.1")
    kapt("androidx.room:room-compiler:2.6.1") // Kotlin 사용 시
    // annotationProcessor("androidx.room:room-compiler:2.6.1") // Java 사용 시

    // Kotlin Coroutines (Room과 함께 사용하면 편리)
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.0")
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.8.0")

    // 선택 사항: LiveData 지원
    implementation("androidx.room:room-ktx:2.6.1")

2. 엔티티(Entity) 정의

  • 테이블 이름과 테이블에서 쓸 열 정의
  • 각 엔티티는 @Entity 어노테이션으로 표시
  • 최소한 하나의 기본 키(@PrimaryKey)를 정의해야함
@Entity(tableName = "terms-table")
data class TermsModel(
    @PrimaryKey(autoGenerate = true)
    val id : Int = 0,
    val title : String,
    val content : String,
){
    // 보조 생성자를 사용하여 id 없이 객체 생성 가능
    constructor(title: String, content: String) : this(0, title, content)
}
  • @Entity(tableName = "users"): 이 클래스가 users라는 이름의 데이터베이스 테이블에 매핑될 엔티티임을 나타냅니다. 테이블 이름을 지정하지 않으면 클래스 이름이 기본 테이블 이름으로 사용
  • @PrimaryKey(autoGenerate = true): id 필드가 기본 키이며, 데이터베이스에서 자동으로 값을 생성하도록 지정
  • @ColumnInfo(name = "first_name"): firstName 필드의 데이터베이스 컬럼 이름을 first_name으로 지정합니다. 컬럼 이름을 지정하지 않으면 필드 이름이 기본 컬럼 이름으로 사용

3.데이터 접근 객체(DAO: Data Access Object) 정의

  • 데이터베이스와 상호작용하기 위한 인터페이스 또는 추상 클래스를 생성
  • DAO는 데이터베이스에 데이터를 쿼리, 삽입, 수정, 삭제하는 메서드를 정의
@Dao
interface TermsDao {
    @Insert
    suspend fun insertTerms(termsModel: TermsModel)

    @Query("SELECT * FROM 'terms-table'")
    fun selectAllTerms():Flow<List<TermsModel>>

    @Query("SELECT * FROM 'terms-table' WHERE id = :id")
    fun selectByTermsId(id:Int):Flow<TermsModel>

    @Query("DELETE FROM 'terms-table'")
    suspend fun clearTable()
}
  • @Dao: 이 인터페이스가 DAO임을 나타내는 어노테이션
  • 콜론(:) 뒤에 오는 이름은 메서드 파라미터와 매핑됨
  • @Insert(onConflict = OnConflictStrategy.IGNORE): 삽입 충돌이 발생했을 때 기존 데이터를 무시하도록 설정, 다른 전략으로는 REPLACE (기존 데이터 덮어쓰기), ABORT (작업 중단) 등이 있다
  • suspend 키워드는 이 함수가 코루틴 내에서 호출되어야 함을 나타냄

4. Room 데이터베이스 클래스 정의

  • @Database 어노테이션으로 표시된 추상 클래스를 생성
  • 엔티티 목록과 DAO 인스턴스를 제공하는 추상 메서드를 포함해야 한다.
  • RoomDatabase를 상속받아야 한다
@Database(entities = [TermsModel::class], version = 1)
abstract class TermsDB : RoomDatabase(){

    abstract fun termsDao() : TermsDao

    companion object {
        @Volatile
        private var INSTANCE:TermsDB?=null

        fun getInstance(context: Context):TermsDB{
            synchronized(this) {
                var instance = INSTANCE

                if (instance==null) {
                    instance = Room.databaseBuilder(
                        context.applicationContext,
                        TermsDB::class.java,
                        "terms_DB"
                    ).fallbackToDestructiveMigration().build()
                    INSTANCE = instance
                }
                return instance
            }
        }
    }
}
  • @Database(entities = [User::class], version = 1, exportSchema = false):
    -> entities = [User::class]: 이 데이터베이스가 관리할 엔티티 목록을 지정, 여러 개의 엔티티가 있다면 쉼표로 구분하여 나열
    -> version = 1: 데이터베이스 스키마의 버전을 나타냅니다. 데이터베이스 구조가 변경될 때마다 이 버전을 증가시켜 Room이 마이그레이션을 처리
    -> exportSchema = false: 스키마 내보내기 기능을 비활성화합니다. 프로덕션 환경에서는 스키마를 내보내어 버전 관리에 활용
  • abstract fun termsDao(): TermsDao : TermsDao 인터페이스의 인스턴스를 반환하는 추상 메서드를 정의. Room은 이 메서드의 구현체를 자동으로 제공함
  • companion object: 데이터베이스 인스턴스를 싱글톤으로 관리하기 위한 동반 객체
  • @Volatile private var INSTANCE: AppDatabase? = null: 앱 전체에서 공유할 데이터베이스 인스턴스를 저장하는 변수. @Volatile은 여러 스레드에서 안전하게 접근할 수 있도록 보장
  • fun getDatabase(context: Context): AppDatabase: 데이터베이스 인스턴스를 가져오는 팩토리 메서드. 싱글톤 패턴을 구현하여 앱 내에서 하나의 데이터베이스 인스턴스만 사용함
  • Room.databaseBuilder(...): Room의 databaseBuilder를 사용하여 데이터베이스 인스턴스를 생성
  • .fallbackToDestructiveMigration(): 마이그레이션 전략이 없을 때 데이터베이스를 삭제하고 새로 생성하는 옵션. 개발 단계에서는 편리하지만, 실제 앱에서는 데이터 손실을 유발할 수 있으므로 주의

5.데이터베이스 사용

  • 액티비티, 프래그먼트, 서비스 등 앱의 다른 컴포넌트에서 AppDatabase의 싱글톤 인스턴스를 가져와 DAO를 통해 데이터베이스에 접근하고 조작
class MainActivity : AppCompatActivity() {
    private lateinit var userDao: UserDao
    private lateinit var db: AppDatabase

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        db = AppDatabase.getDatabase(applicationContext)
        userDao = db.userDao()

        // 데이터 삽입
        lifecycleScope.launch {
            val newUser = User(firstName = "John", lastName = "Doe", age = 30)
            userDao.insert(newUser)
            Log.d("Room", "User inserted with ID: ${newUser.id}")
        }

        // 데이터 조회
        lifecycleScope.launch {
            val users = userDao.getAll()
            Log.d("Room", "All users: $users")

            val userById = userDao.getUserById(1)
            Log.d("Room", "User with ID 1: $userById")
        }

        // 데이터 업데이트
        lifecycleScope.launch {
            val existingUser = userDao.getUserById(1)
            existingUser?.let {
                val updatedUser = it.copy(age = 31)
                userDao.update(updatedUser)
                Log.d("Room", "User updated: $updatedUser")
            }
        }

        // 데이터 삭제
        lifecycleScope.launch {
            val userToDelete = userDao.getUserById(1)
            userToDelete?.let {
                userDao.delete(it)
                Log.d("Room", "User deleted: $it")
            }
        }

        // Flow를 이용한 데이터 관찰
        lifecycleScope.launch {
            userDao.getUsersByAgeDescending().collect { users ->
                Log.d("Room", "Users sorted by age (descending): $users")
                // UI 업데이트 등 수행
            }
        }
    }
}
profile
보조기억장치

0개의 댓글