SQLite 대신 Room 사용해보기

Darby·2024년 1월 23일

앱개발 후기

목록 보기
2/4

이번에 소개할 기술은 Room 입니다.

AAC의 하나인 Room은 기존에 SQLite를 좀 더 쉽게 쓸 수 있게 만든거라고 생각하시면 됩니다.

주요 구성 요소
Room에는 세 가지 주요 구성요소가 있습니다.

  • 데이터베이스를 보유하고 앱의 지속형 데이터에 대한 기본 연결을 위한 기본 액세스 지점 역할을 하는 데이터베이스 클래스 입니다.
  • 앱 데이터베이스의 테이블을 나타내는 Data Entity입니다 .
  • 앱이 데이터베이스의 데이터를 쿼리, 업데이트, 삽입 및 삭제하는 데 사용할 수 있는 메서드를 제공하는 데이터 액세스 개체(DAO) 입니다.

Google Document에 있는 내용입니다.

Room에서 필요한 3가지 요소를 나타낸 것 입니다.

DataBase, Data Entity, DAO가 있습니다.

간단하게 알아보겠습니다.

1.데이터 베이스

@Database(
    entities = [LikeCharacterVo::class, RecentSearchVO::class],
    version = 2,
    exportSchema = false
)
abstract class AppDatabase : RoomDatabase() {
    abstract fun likeCharacterDao(): LikeCharacterDao

    abstract fun recentSearchDao(): RecentSearchDao
}

entities는 간단히 말하면 Table의 역할을 합니다.

version은 변경사항이 생길 때 하나씩 올려주면됩니다. 올리지 않고 빌드를 한다면 에러를 마주칠 것입니다.

exportSchema는 Room의 스키마를 폴더로 내보내도록 지시할 수 있습니다.


2.엔티티

@Entity(tableName = "like_table", indices = [Index(value = ["nickName"], unique = true)])
data class LikeCharacterVo(
    @PrimaryKey(autoGenerate = true)
    val id : Long = 0,
    val nickName: String,
    val imgUrl: String,
    val level : String
)

이번에 메이플스토리 관련 앱을 만들면서 쓰던 캐릭터 즐겨찾기의 엔티티 구조입니다.

우선 Table Name을 정해주고 indices 속성에 nickName필드를 unique 고유 속성으로 만든 엔티티입니다. 만일 닉네임이 같은 경우 추후 Insert를 하게 되면 에러가 난다거나 덮어쓰기를 한다거나 개발자가 정해준 방식을 취할 것 입니다. 하지만 제가 만든 앱은 메이플에서 닉네임을 생성할 때 중복이 방지되므로 저는 덮어쓰기 방식을 채택했습니다. 나머지 필드들은 자기가 넣어주고 싶은 필드들을 넣어주시면 됩니다.

@PrimaryKey(autoGenerate = true)
    val id : Long = 0

이 부분은 보통 index로 많이 쓰는 부분입니다. 자동으로 카운트가 됩니다.


3.DAO (Data Access Objects)

@Dao
interface LikeCharacterDao {
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertLickCharacter(likeCharacterVo: LikeCharacterVo)

    @Query("SELECT * FROM like_table")
    fun getAllLikeCharacter(): LiveData<List<LikeCharacterVo>>


    @Query("DELETE FROM like_table WHERE nickName = :nickName")
    suspend fun deleteData(nickName: String)

    @Query("SELECT * FROM like_table WHERE nickName = :name")
    fun getCharacterByName(name : String): LikeCharacterVo?
}

즐겨찾기 Dao입니다.

Dao는 테이블에 접근하려고 하는 object? 정도 라고 생각하시면 편할 것 같습니다.

사실 Update도 만들어야 하지만 insert를 할 때

onConflict = OnConflictStrategy.REPLACE

Insert에 옵션을 주면 해당 옵션은 중복값이 있을 때 교체를 한다는 뜻입니다.

그래서 저는 따로 Update는 만들지 않았습니다.


@Module
@InstallIn(SingletonComponent::class)
object DatabaseModule {
    @Singleton
    @Provides
    fun provideAppDatabase(@ApplicationContext context: Context): AppDatabase {
        return Room.databaseBuilder(
            context,
            AppDatabase::class.java,
            "LikeCharacterDatabase"
        ).build()
    }

    @Provides
    fun provideLikeCharacterDao(database: AppDatabase): LikeCharacterDao {
        return database.likeCharacterDao()
    }

}

DB객체는 싱글톤으로 구현하는 걸 추천하고 있습니다. 공식문서를 참조해주세요.

@HiltViewModel
class LikeCharacterViewModel @Inject constructor(private val likeCharacterRepository: LikeCharacterRepository) : ViewModel() {
    private val _characterData = MutableLiveData<List<LikeCharacterVo>>()
    val characterData: LiveData<List<LikeCharacterVo>> get() = _characterData

    fun insertLikeCharacter(name: String, imgUrl: String, level : String) {
        viewModelScope.launch {
            try {
                val likeCharacterVo = LikeCharacterVo(nickName = name, imgUrl = imgUrl, level = level)
                likeCharacterRepository.insertCharacter(likeCharacterVo)
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }
    }

    fun deleteLikeCharacter(name: String) {
        viewModelScope.launch {
            try {
                likeCharacterRepository.deleteUser(name)
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }
    }

    fun getAllList() {
        likeCharacterRepository.getAllCharacterList().observeForever {
            _characterData.value = it
        }
    }

    suspend fun isExistCharacter(name: String): Boolean {
        return withContext(Dispatchers.IO) {
            likeCharacterRepository.isExistCharacter(name)
        }
    }

}

그리고 viewModel로 만들어서 원하는 곳에서 가져다 쓰면 됩니다.

해당 링크를 통해 Room에 대해 더 자세히 알아보시면 좋을 것 같습니다.

profile
성장하는 개발자가 되자

0개의 댓글