티스토리 뷰

개요

기존 android 프로젝트에서 CMP 프로젝트로 변경하며 SharedPreferences를 DataStore로 마이그레이션하게 되었다.

기존 사용자들의 앱에 SharedPreferences로 저장된 기존 데이터들을 DataStore로 위임시킬 수 있다고 한다.

기존 데이터 옮기기

위임 패턴 사용하기(by)

private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(
        name = DATASTORE_FILE_NAME,
        produceMigrations = { context ->
            listOf(SharedPreferencesMigration(context, OLD_PREFS_FILE_NAME))
        },
    )

다음과 같이 기존에 SharedPreferences에 저장된 데이터가 있다면 DataStore를 생성하면서 SharedPreferences에 저장된 데이터를 복사하여 이동시켜준다.

 

이 프로퍼티의 선언은 싱글톤을 보장하기 위해 파일의 최상단이나 application 클래스에서 선언해야한다.

by preferences는 델리게이트(Delegate)방식이다. 이 방식은 PreferenceDataStoreSingletonDelegate 객체를 생성하며 위임을 통해 getValue를 호출하여 DataStore를 생성한다.

다음과 같은 특징이 있다.

  • 싱글톤 보장: 이 방식으로 선언하면 앱전체에서 해당 이름의 DataStore 인스턴스가 단 하나만 존재하도록 라이브러리가 관리해준다.
  • 중복 생성 방지: 만약 이 코드를 일반 class나 Activity 등에서 선언하고 사용할 경우 여러 개의 위임 객체가 생성된다. 이는 IllegalStateException이 발생하며 앱이 종료될 수 있다.

내부 구현

override fun getValue(thisRef: Context, property: KProperty<*>): DataStore<Preferences> {
        return INSTANCE
            ?: synchronized(lock) {
                if (INSTANCE == null) {
                    val applicationContext = thisRef.applicationContext

                    INSTANCE =
                        PreferenceDataStoreFactory.create(
                            corruptionHandler = corruptionHandler,
                            migrations = produceMigrations(applicationContext),
                            scope = scope,
                        ) {
                            applicationContext.preferencesDataStoreFile(name)
                        }
                }
                INSTANCE!!
            }
    }
}

다음 코드는 PreferenceDataStoreSingletonDelegate 의 내부 함수이다. DataStore는 한개만 생성되도록 보장해주지만 PreferenceDataStoreSingletonDelegate 객체가 여러 번 생성될 수 있으므로 반드시 싱글톤으로 생성되도록 해야한다.

androidMain 코드

@BindingContainer
@ContributesTo(AppScope::class)
object DatabaseBindings {
    @Provides
    @SingleIn(AppScope::class)
    fun provideDataStore(application: Application): DataStore<Preferences> =
        PreferenceDataStoreFactory.create(
            migrations = listOf(SharedPreferencesMigration(application, OLD_PREFS_FILE_NAME)),
            produceFile = { application.preferencesDataStoreFile(DATASTORE_FILE_NAME) },
        )
}

내 코드는 위임 방식을 사용하지 않고 PreferenceDataStoreFactory를 통해 직접 생성해주었다.

Metro DI를 사용하고 있기 때문에 @SingleIn 을 통해 싱글톤을 보장해주었다.

'CMP' 카테고리의 다른 글

Ktorfit(Ktor + Retrofit)  (0) 2026.01.21
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2026/02   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
글 보관함