refactor(db): ObjectBox 제거 및 Room으로 마이그레이션

- 최상위/app Gradle에서 ObjectBox 플러그인 제거
- PlaybackTracking을 Room Entity/DAO/Database로 전환
- Repository를 Room 기반으로 수정 및 Koin DI 주입 변경
This commit is contained in:
2025-10-22 16:25:32 +09:00
parent bc581d763b
commit 9b825ee244
8 changed files with 81 additions and 44 deletions

View File

@@ -8,7 +8,6 @@ plugins {
id 'kotlin-parcelize'
id 'org.jlleitschuh.gradle.ktlint'
id 'io.objectbox'
id 'com.google.firebase.crashlytics'
}
@@ -65,7 +64,7 @@ android {
}
debug {
minifyEnabled true
minifyEnabled false
debuggable true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
applicationIdSuffix '.debug'

View File

@@ -1,16 +1,16 @@
package kr.co.vividnext.sodalive.audio_content
import androidx.annotation.Keep
import io.objectbox.annotation.Entity
import io.objectbox.annotation.Id
import androidx.room.Entity
import androidx.room.PrimaryKey
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
@Entity
@Entity(tableName = "playback_tracking")
@Keep
data class PlaybackTracking(
@Id
@PrimaryKey(autoGenerate = true)
var id: Long = 0,
var contentId: Long,
var totalDuration: Int,

View File

@@ -1,29 +1,21 @@
package kr.co.vividnext.sodalive.audio_content
import kr.co.vividnext.sodalive.common.ObjectBox
import kr.co.vividnext.sodalive.audio_content.db.PlaybackTrackingDao
class PlaybackTrackingRepository(private val objectBox: ObjectBox) {
class PlaybackTrackingRepository(private val dao: PlaybackTrackingDao) {
fun savePlaybackTracking(data: PlaybackTracking): Long {
return objectBox.playbackTrackingBox.put(data)
return dao.insert(data)
}
fun getPlaybackTracking(id: Long): PlaybackTracking? {
val query = objectBox.playbackTrackingBox
.query(PlaybackTracking_.id.equal(id))
.build()
val playbackTracking = query.findFirst()
query.close()
return playbackTracking
return dao.getById(id)
}
fun getAllPlaybackTracking(): List<PlaybackTracking> {
return objectBox
.playbackTrackingBox
.all
return dao.getAll()
}
fun removeAllPlaybackTracking() {
objectBox.playbackTrackingBox.removeAll()
dao.deleteAll()
}
}

View File

@@ -0,0 +1,22 @@
package kr.co.vividnext.sodalive.audio_content.db
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import kr.co.vividnext.sodalive.audio_content.PlaybackTracking
@Dao
interface PlaybackTrackingDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insert(entity: PlaybackTracking): Long
@Query("SELECT * FROM playback_tracking WHERE id = :id LIMIT 1")
fun getById(id: Long): PlaybackTracking?
@Query("SELECT * FROM playback_tracking")
fun getAll(): List<PlaybackTracking>
@Query("DELETE FROM playback_tracking")
fun deleteAll()
}

View File

@@ -0,0 +1,35 @@
package kr.co.vividnext.sodalive.audio_content.db
import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
import androidx.room.TypeConverters
import kr.co.vividnext.sodalive.audio_content.PlaybackTracking
import kr.co.vividnext.sodalive.common.Converter
@Database(entities = [PlaybackTracking::class], version = 1)
@TypeConverters(Converter::class)
abstract class PlaybackTrackingDatabase : RoomDatabase() {
abstract fun playbackTrackingDao(): PlaybackTrackingDao
companion object {
@Volatile
private var INSTANCE: PlaybackTrackingDatabase? = null
fun getDatabase(context: Context): PlaybackTrackingDatabase {
return INSTANCE ?: synchronized(this) {
val instance = Room.databaseBuilder(
context.applicationContext,
PlaybackTrackingDatabase::class.java,
"playback_tracking_database"
)
.fallbackToDestructiveMigration()
.allowMainThreadQueries()
.build()
INSTANCE = instance
instance
}
}
}
}

View File

@@ -1,14 +0,0 @@
package kr.co.vividnext.sodalive.common
import android.content.Context
import io.objectbox.BoxStore
import kr.co.vividnext.sodalive.audio_content.MyObjectBox
import kr.co.vividnext.sodalive.audio_content.PlaybackTracking
class ObjectBox(context: Context) {
private var store: BoxStore = MyObjectBox.builder()
.androidContext(context.applicationContext)
.build()
val playbackTrackingBox = store.boxFor(PlaybackTracking::class.java)
}

View File

@@ -15,6 +15,8 @@ import kr.co.vividnext.sodalive.audio_content.comment.AudioContentCommentListVie
import kr.co.vividnext.sodalive.audio_content.comment.AudioContentCommentReplyViewModel
import kr.co.vividnext.sodalive.audio_content.comment.AudioContentCommentRepository
import kr.co.vividnext.sodalive.audio_content.curation.AudioContentCurationViewModel
import kr.co.vividnext.sodalive.audio_content.db.PlaybackTrackingDao
import kr.co.vividnext.sodalive.audio_content.db.PlaybackTrackingDatabase
import kr.co.vividnext.sodalive.audio_content.detail.AudioContentDetailViewModel
import kr.co.vividnext.sodalive.audio_content.main.banner.AudioContentMainBannerViewModel
import kr.co.vividnext.sodalive.audio_content.main.curation.AudioContentMainCurationViewModel
@@ -67,23 +69,24 @@ import kr.co.vividnext.sodalive.audition.role.AuditionRoleDetailViewModel
import kr.co.vividnext.sodalive.chat.character.CharacterApi
import kr.co.vividnext.sodalive.chat.character.CharacterTabRepository
import kr.co.vividnext.sodalive.chat.character.CharacterTabViewModel
import kr.co.vividnext.sodalive.chat.character.newcharacters.NewCharactersAllViewModel
import kr.co.vividnext.sodalive.chat.character.newcharacters.NewCharactersRepository
import kr.co.vividnext.sodalive.chat.character.comment.CharacterCommentApi
import kr.co.vividnext.sodalive.chat.character.comment.CharacterCommentListViewModel
import kr.co.vividnext.sodalive.chat.character.comment.CharacterCommentReplyViewModel
import kr.co.vividnext.sodalive.chat.character.comment.CharacterCommentRepository
import kr.co.vividnext.sodalive.chat.character.detail.detail.CharacterDetailRepository
import kr.co.vividnext.sodalive.chat.character.detail.detail.CharacterDetailViewModel
import kr.co.vividnext.sodalive.chat.character.detail.gallery.CharacterGalleryRepository
import kr.co.vividnext.sodalive.chat.character.detail.gallery.CharacterGalleryViewModel
import kr.co.vividnext.sodalive.chat.character.newcharacters.NewCharactersAllViewModel
import kr.co.vividnext.sodalive.chat.character.newcharacters.NewCharactersRepository
import kr.co.vividnext.sodalive.chat.original.OriginalWorkApi
import kr.co.vividnext.sodalive.chat.original.OriginalWorkRepository
import kr.co.vividnext.sodalive.chat.original.OriginalWorkViewModel
import kr.co.vividnext.sodalive.chat.talk.TalkApi
import kr.co.vividnext.sodalive.chat.talk.TalkTabRepository
import kr.co.vividnext.sodalive.chat.talk.TalkTabViewModel
import kr.co.vividnext.sodalive.chat.talk.room.chatTalkRoomModule
import kr.co.vividnext.sodalive.chat.original.OriginalWorkApi
import kr.co.vividnext.sodalive.chat.original.OriginalWorkRepository
import kr.co.vividnext.sodalive.chat.original.OriginalWorkViewModel
import kr.co.vividnext.sodalive.common.ApiBuilder
import kr.co.vividnext.sodalive.common.ObjectBox
import kr.co.vividnext.sodalive.explorer.ExplorerApi
import kr.co.vividnext.sodalive.explorer.ExplorerRepository
import kr.co.vividnext.sodalive.explorer.ExplorerViewModel
@@ -204,7 +207,8 @@ class AppDI(private val context: Context, isDebugMode: Boolean) {
private val otherModule = module {
single { GsonBuilder().create() }
single { ObjectBox(get()) }
single { PlaybackTrackingDatabase.getDatabase(get()) }
single<PlaybackTrackingDao> { get<PlaybackTrackingDatabase>().playbackTrackingDao() }
}
private val networkModule = module {
@@ -368,8 +372,8 @@ class AppDI(private val context: Context, isDebugMode: Boolean) {
viewModel { CharacterDetailViewModel(get()) }
viewModel { CharacterGalleryViewModel(get()) }
viewModel { TalkTabViewModel(get()) }
viewModel { kr.co.vividnext.sodalive.chat.character.comment.CharacterCommentListViewModel(get()) }
viewModel { kr.co.vividnext.sodalive.chat.character.comment.CharacterCommentReplyViewModel(get()) }
viewModel { CharacterCommentListViewModel(get()) }
viewModel { CharacterCommentReplyViewModel(get()) }
viewModel { NewCharactersAllViewModel(get()) }
viewModel { OriginalWorkViewModel(get()) }
viewModel { kr.co.vividnext.sodalive.chat.original.detail.OriginalWorkDetailViewModel(get()) }