안드로이드에서 SharedPreferences 대신 DataStore를 쓰는 건 이제 당연해졌지만, KMP 환경에서는 몇 가지 추가로 신경 써야 할 부분이 있습니다. Todo 앱에 로컬 저장소를 붙이면서 겪은 내용을 정리합니다.

Preferences DataStore vs Proto DataStore

  • Preferences DataStore: key-value 저장, 스키마 없음. 멀티플랫폼 지원이 상대적으로 안정적입니다.
  • Proto DataStore: Protocol Buffers 기반 타입 세이프 저장. 강력하지만 KMP에서는 .proto 파일의 멀티플랫폼 코드 생성 설정이 추가로 필요해 초기 진입 장벽이 있습니다.

Todo 앱처럼 단순한 구조라면 Preferences DataStore로 시작하는 걸 권장합니다.

commonMain에서 DataStore 인스턴스 관리하기

DataStore는 파일 경로를 필요로 하는데, 이 경로를 얻는 방식이 플랫폼마다 다릅니다. 그래서 expect/actual 패턴으로 경로 제공 함수를 분리합니다.

// commonMain
expect fun createDataStore(): DataStore<Preferences>
// androidMain
actual fun createDataStore(): DataStore<Preferences> =
    PreferenceDataStoreFactory.createWithPath(
        produceFile = { context.filesDir.resolve("todo.preferences_pb").absolutePath.toPath() }
    )
// iosMain
actual fun createDataStore(): DataStore<Preferences> =
    PreferenceDataStoreFactory.createWithPath(
        produceFile = {
            val documentDirectory = NSFileManager.defaultManager.URLForDirectory(
                directory = NSDocumentDirectory,
                inDomain = NSUserDomainMask,
                appropriateForURL = null,
                create = false,
                error = null,
            )
            (requireNotNull(documentDirectory?.path) + "/todo.preferences_pb").toPath()
        }
    )

iOS 초기화 시 주의점

iOS에서는 NSFileManager로 앱 문서 디렉토리 경로를 가져와야 하는데, 이 과정에서 흔히 겪는 문제가 있습니다.

  • 경로 중복 생성: MainViewController가 여러 번 초기화되는 경우 DataStore 인스턴스도 여러 개 생성될 수 있습니다. 반드시 싱글턴으로 관리해야 하며, Koin의 single { } 스코프로 묶는 게 안전합니다.
  • 샌드박스 경로 변경: iOS는 앱 재설치 시 샌드박스 UUID가 바뀌면서 절대 경로가 달라집니다. 상대 경로 기반 API(NSFileManager가 제공하는 디렉토리 API)를 써야 문제가 없습니다.

자주 만나는 에러

"Multiple DataStores active for the same file" 싱글턴 관리가 안 됐을 때 발생합니다. DI 컨테이너(Koin)에서 single로 등록했는지 다시 확인해야 합니다.

iOS 빌드에서만 발생하는 경로 관련 크래시 안드로이드에서는 잘 되다가 iOS 빌드에서만 크래시가 나는 경우, 대부분 문서 디렉토리 경로를 가져오는 코드에서 옵셔널 언래핑을 제대로 안 한 경우입니다.

마무리

DataStore 자체는 KMP를 잘 지원하지만, "파일 경로를 어떻게 얻는가"라는 플랫폼 디테일에서 문제가 생깁니다. expect/actual로 깔끔하게 분리하고, DI로 싱글턴을 보장하면 대부분의 문제는 피할 수 있습니다.