[번역][요약] Introduction to Jetpack DataStore | Android Study

hoya·2024년 3월 17일
0

Android Study

목록 보기
19/19
post-thumbnail

해당 글은 안드로이드 개발자 공식 미디엄의 Introduction to Jetpack DataStore
포스팅을 요약 번역한 것으로, 의역 및 오역이 다수 존재할 수 있습니다. 열람에 유의하세요!


DataStore 는 현재 애플리케이션의 상태나 기본적인 설정과 같이 작은 데이터를 안전하고 일관적으로 저장하는 방법을 제공하는 데이터 저장소 API로, 비동기 데이터 저장을 가능하게 만드는 코루틴과 플로우를 기반으로 동작합니다. thread-safe 하고, non-blocking 하게 동작하는 장점이 있으며, 기존에 널리 사용되던 SharedPreferences 의 대체를 목표로 합니다.

DataStore VS SharedPrefernces

SharedPreferences 를 사용하면 다음과 같은 문제를 겪을 가능성이 큽니다.

  1. 재현이 어려운 버그를 경험할 가능성이 높습니다.
  2. 캐칭되지 않은 예외로 인해 데이터의 충돌이 발생할 여지가 있습니다.
  3. 호출 시 UI 스레드가 차단될 가능성이 있습니다.
  4. 전체적으로 데이터가 일관성없이 유지될 수 있습니다.

이러한 문제 상황들을 극복하기 위해, DataStore 의 개발이 시작되었습니다.

Async API

데이터 저장소 API를 사용하는 경우, 대부분의 경우 데이터 수정 시 비동기적으로 콜백을 받아야 하는 경우가 많습니다. 이러한 상황을 기반으로 SharedPreferencesDataStore 를 비교해보겠습니다.

우선 SharedPreferences 도 비동기 기능을 일부 지원합니다. 하지만, OnSharedPreferenceChangeListener 를 통해 변경된 값에 대한 콜백을 받겠다고 명시적으로 지정해야만 합니다. 또한, 이러한 콜백은 UI 스레드에서 호출됩니다.

데이터 저장의 경우 apply() 함수를 통해 비동기적으로 데이터를 저장할 수 있게 지원했지만, 사실은 즉시 비동기 호출을 진행하진 않습니다. 잠시 지연시켜두었다가, 서비스 혹은 액티비티가 Start/Stop 하는 시점에 백그라운드에서 동작합니다. 이 때, fsync() 라는 네이티브 함수가 사실상 UI 스레드를 블락하기 때문에, ANR까지 발생할 가능성이 있습니다.

DataStore 는 데이터 저장, 검색을 위해 코틀린의 Coroutines, Flow 기능을 기반으로 완전한 비동기 API를 제공합니다. 이는 곧, UI 스레드가 차단될 위험을 줄일 수 있다는 것을 의미합니다.

Synchronous work

SharedPreferences 는 기본적으로 동기 작업을 지원합니다. 그러나 데이터를 수정하는 데 사용하는 commit() 함수는 UI 스레드에서 호출되고, 이로 인해 ANR 및 버벅거림으로 이어질 수 있습니다.

DataStore 에서는 위와 같은 상황을 방지하기 위해 동기 작업 자체를 지원하지 않습니다. 기본적으로 Dispatchers.IO 에서 모든 데이터 작업을 수행함으로써 UI 스레드가 차단될 위험 자체를 없애버립니다. 물론, Coroutines 빌더의 도움을 받아 동기 작업과 같이 동작하게 만들 수도 있습니다.

Error handling

SharedPreferences 의 경우 에러 발생 시 곧바로 Runtime Exception 을 발생시키므로, 앱 자체에서 크래쉬가 일어날 확률이 높습니다. 한 가지 예로 잘못된 데이터 유형을 요청할 때 ClassCastException 이 발생하며 곧바로 앱에서 크래쉬가 발생합니다.

DataStoreFlow 에서 제공하는 예외처리 메커니즘을 이용해 데이터를 읽고 쓸 때 발생할 수 있는 크래쉬를 방지합니다.

Type safety

데이터 저장 및 호출을 위해 Map 자료구조를 사용하는 것은 타입 안정성을 보장하지 않습니다. 그러나, Proto DataStore 를 이용하면 데이터 모델의 스키마를 미리 지정하고, 타입 안정성을 확보할 수 있습니다.

Data consistency

SharedPreferences 는 원자성 보장과 같은 기능이 부족하기 때문에, 여러 곳에서 동시에 데이터를 접근하면 서로 다른 데이터를 부여받을 수 있습니다. 특히 SharedPreferences 는 영구 데이터 저장소의 역할을 하기 때문에, 에러가 발생했을 때 많은 곳에 영향을 미칠 수 있습니다.

DataStore 의 경우 완전한 트랜잭션 API를 제공하기 때문에, 원자적으로 데이터를 읽고, 쓰고, 수정할 수 있습니다. 또한, 데이터에 변경사항이 생겼을 경우 해당 변경사항이 모든 화면에 적용된다는 사실을 반영해 변경사항 요청을 먼저 데이터베이스에 반영하고, 반영된 값을 요청자에게 제공하는 메커니즘으로 동작합니다.


Preferences VS Proto DataStore

Preferences DataStore 는 데이터베이스 스키마를 미리 지정하지 않고, Key-Value Pairs 를 기반으로 데이터를 호출하고 작성합니다. SharedPreferences 와는 완전히 별도의 API로, 단순히 데이터를 저장하고 호출하는 용도로 사용하거나, SharedPreference 에서 빠르게 마이그레이션해야 하는 경우 용이하게 활용할 수 있습니다.

Proto DataStore프로토콜 버퍼의 지원을 받아 타입이 지정된 객체를 저장해 타입의 안정성을 보장합니다. enum, list 와 같이 더 복잡한 데이터를 저장해야 하면서, 완전하게 타입의 안정성을 보장받고 싶은 경우 용이하게 활용할 수 있습니다. 또한 코틀린 외에도 자바, C, C++, 파이썬과 같은 언어에서도 사용 가능합니다.


DataStore vs Room

수십 KB보다 큰 복잡한 데이터 세트로 작업해야 하는 경우나 데이터를 부분적으로 업데이트해야 하는 경우 Room 사용을 고려해야 합니다. 서로 다른 테이블에서 공통된 데이터를 다룰 때 참조 무결성을 지키기 위해서도 Room 의 활용을 권장합니다. 하지만 이런 케이스가 아니라 기본 설정, 앱 상태와 같은 작은 데이터를 다룬다면 DataStore 를 선택하는 것이 좋습니다.

profile
즐겁게 하자 🤭

0개의 댓글