본문 바로가기
Mobile App

[안드로이드] - ShardPreferences, Datastore 차이

by Jman 2023. 1. 27.

왜 Datastore 에 대해 알아보는 걸까?

우리는 안드로이드 개발을 하다보면, 간단한 데이터에 대해 로컬에 저장하여 사용한다.

가볍게 SharedPreferences 를 설명하자면 Key-Value 형태로 값을 저장하여 읽고 쓰는 간단한 방법이다.

데이터는 xml 파일로 로컬 저장소에 저장된다.

 

우리는 왜? Datastore 를 알아볼까 Datastore 는 Kotlin 코루틴 및 Flow 를 사용하여 비동기적이고 일관된 트랜잭션 방식으로 데이터를 저장한다. 그리고 Andorid Developer 사이트에서 Datastore 사용을 권장한다.

또한 SharedPreferences 를 사용하는데에 여러 문제점이 존재한다. 그래서 권장하는 것 같고, 이제는 SharedPreferences 에서 Datastore 로 이전하는 것이 좋다고 한다.

 

SharedPreferences 의 문제점

1. 비동기 API 를 제한적으로 지원한다는 점

기존에 SP(SharedPreferences) 에서는 읽기(Read)에 대해 기존에 값을 읽어오는 것은 동기(sync) API 만을 제공하고, 값에 변화가 있을 때마다 비동기적으로 값을 가져오는 방법으로는 오직 OnSharedPreferenceChangeListener 를 통해서만 콜백을 받을 수 있게 지원하고 있다.

 

또한, 쓰기(Write) 에 대해서는 Editor 를 통해 put 하고 commit() 이 아닌 apply() 라는 함수를 통해 비동기로 write 할 수 있게 제공하고 있다. 이 apply() 도 사실 즉시 비동기 호출을 하는게 아니라 내부 코드를 보면 pending 시켜두었다가 서비스나 액티비티가 onStart, onStop 되는 시점에 백그라운드에서 동작하게 되는데, 이때 fsync() 라는 native 함수가 사실상 Main Thread 를 Block 하기 때문에 자칫 잘못하면 ANR 로 이어질 수 있다고 한다.

 

2. Runtime Exception 에 취약하다.

SP 는 기본적으로 Exception 에 대한 에러 핸들링을 제공하고 있지 않다. 따라서 발생하는 Exception 을 다루기에 어려움을 겪는다.

심지어 apply() 를 통해 pending 된 작업을 처리하다가 에러가 발생할 경우에는 해당 예외를 잡을 방법이 없이 Crach 를 맞이할 수 밖에 없다.

 

3. UI Thread 에 안전하지 않다

SP commit() 함수에서 별도의 Thread 아닌 호출된 Thread 에서 바로 File Write 를 하고 있다.

이는 파일에 쓰는 데이터가 많지 않으면 언뜻 보기에는 문제가 없어보이지만, 저사양 기기에서나 데이터 양이 많아진다면 Main Thread 를 오랫동안 Block 하면서 유저에게 버벅이는 경험을 주거나 ANR 까지도 이어질 수 있다.

 

 

이제는 Datastore 에 대해서 알아볼까?

Jetpack Datastore 는 프로토콜 버퍼를 사용하여 Key-Value 쌍 또는 Typed Object(유형이 지정된 객체)를 저장할 수 있는 데이터 저장소이다.

💡프로토콜 버퍼? 구글의 데이터를 직렬화하기 위한 메커니즘

  • Datastore 는 Kotlin 코루틴 및 Flow 를 사용하여 비동기적으로 일관된 트랜잭션 방식으로 데이터를 저장한다.
  • 소규모 단순 데이터에 적합한 솔루션으로, 복잡한 데이터나 참조 무결성 등을 필요로 할 때는 Room 사용이 적합하다.
  • Key-Value 방식의 Preferences Datastore 와 Protocol buffer 를 사용한 타입이 지정돈 객체를 저장할 수 있는 방식인 Proto Datastore 솔루션 제공

Datastore 는 코루틴 Flow 를 통해서만 제공되기 때문에 기본적으로는 비동기 API 만을 제공한다.

하지만, first() 등을 활용한다면 동기처리로 활용할 수 있다.

 

또한 CorruptionHandler 이나 Flow 의 확장함수 중 catch() 등을 통해서 에러 핸들링을 잘 지원해주고 있고,

모든 무거운 작업은 Dispatchers.IO 에서 작업되기 때문에 UI Thread 에서 얼마든지 사용하더라도 안전하다 할수 있다.

 

SharedPreferences VS Perference Datastore VS Proto Datastore 비교

  SharedPreferences Preference Datastore Proto Datastore
데이터 추출 선언적으로 하나씩 추출 코루틴 Flow 로 데이터 스트림으로  받는다. 코루틴 Flow 데이터 스트림으로 받는다.
동시성 프로그래밍 방식 직접 설계 해야함 코루틴 코루틴
UI 스레드 호출 안정성 ANR 발생 가능 Dispathcers.IO 에서 호출 되도록 강제하여 안전 Dispathcers.IO 에서 호출 되도록 강제하여 안전
강한 일관성 보장하지 않음 보장 보장
타입 보장 보장하지 않음 보장 보장