Preference 가 API level 29 부터 deprecated 가 되었다.
그래서 jetPack DataStore 를 사용하라고 한다.
API 29 부터 deprecated 된것이지만 필자는 이것을 최근에야 알았다.
따라서, DataStore 에 대해서 알아보고자 한다.
우선,
DataStore 는 무엇인가?
프로토콜 버퍼를 사용하여 Key-Value 쌍 또는 유형이 지정된 객체를 저장할 수 있는 데이터 저장소 솔루션 이다.
또한, Preference DataStore, Proto DataStore 의 2가지 존재가 존재한다.
- Preference DataStore : 기존에 Preference 와 마찬가지로, Key 를 사용하여 데이터를 저장하고, 가져온다.
- Proto DataStore : 사용자가 정의한 타입으로 데이터를 저장한다. 이 때, 프로토콜 버퍼를 사용하여 스키마를 정의해야 한다.
여기서 필자는 Proto DataStore 에 대한 사용은 하지 않으려고 한다.
기존에 사용하던 프로젝트에서도 Key-Value 타입의 Preference 를 사용하고 있었기 때문에, 사용할 데이터 타입을 직접 생성하고 사용하는 Proto DataStore 는 사용할 필요가 없으며 Preference DataStore 만 사용해도 충분하다고 생각했기 때문이다.
DataStore 에 대해서 공부하려고 찾아보면, DataStore 의 장점을 보여줄 수 있는 다음과 같은 표를 쉽게 찾아볼 수 있다.
위의 표를 확인해 보면 DataStore 는 크게 이런 특징이 존재한다.
- Flow 를 사용하여 데이터를 읽는다. 즉, 코루틴을 사용해야 한다.
- IO 스레드 밑에서 동작한다.
- runtime Exception 에서 안전하다.
필자는 DataStore 를 Preference가 deprecated 되었기 때문에 사용하려고 생각하였지만, 위와 같은 다양한 장점들이 존재하는 것을 알 수 있다.
그렇다면,
어떻게 사용해야 할까?
DataStore 를 사용하기 위해서는 우선 Gradle 에 라이브러리를 추가해 주어야 한다.
하단의 rxJava2 는 없어도 무관하지만, support 라고 되어있길래 추가시켜보았다. DataStore 를 사용하는 것에는 필요하지 않다.
추가해 주었으면, DataStore 를 생성하여 사용하면 된다.
우선, 위의 코드는 DataStore 의 전체 소스코드이다.
전체 소스코드 부터 넣어두는 이유는, 필자가 DataStore 를 사용해보기 위해서 Android Developer 를 보고 따라해 보았는데 정상적으로 안됐던 부분이 많았기 때문이다.
위의 코드를 3개의 구분으로 나누어서 확인해보자.
DataStore 의 생성부분과 DataStore 에 값을 저장할 때 사용할 Key 값을 설정해 주는 부분이다.
dataStore 에 설정하는 name 값은 해당 DataStore 의 이름을 설정해주는 것이고, 여러가지 매개변수가 추가로 들어갈 수 있지만 필수로 들어가야하는 name 에 대한 값만 넣어주도록 한다.
Key 값을 설정하는 부분은 저장할 value 의 type 에 따라서 다르게 선언을 해주어야 한다.
stringPreferencesKey(name) 형태로 선언되어 있는데, string 부분에 저장할 Value 의 Type 을 넣어주면 된다.
즉, int 타입이라면 intPrefenencesKey(name) 형태로 선언하여 사용하면 되는 것이다.
다음으로 데이터를 저장하는 부분이다.
데이터를 저장할때는 edit() 를 사용하여 아주 간단하게 사용할 수 있다.
하지만, edit() 의 경우 비동기로 작업이 이루어져야 하는 부분이기 때문에 일반적인 함수로 사용할 수 없으며,
suspend 를 사용하여 코루틴 환경에서 해당 함수가 호출되어 값이 저장되도록 해야한다.
stringKey 의 자리에는 상단에 선언한 Key 값을 사용하는 것이고, text 부분에는 저장할 데이터가 들어가면 된다.
마지막 부분인 데이터를 가져오는 부분이다.
반환되는 자료형을 보면 알 수 있겠지만 DataStore 의 큰 특성 중 하나인 Flow 를 통해 데이터가 반환되며, map 을 사용하여 DataStore 에 가지고 있는 값을 key 값을 사용하여 가져오도록 되어있다.
또한, 값을 읽어오는 과정에서 오류가 발생하는 경우가 발생할 수 있으며 이 때는 IOException 이 발생한다.
따라서 catch 를 사용하여 해당 exception 에 대한 처리를 하여 앱이 죽거나 하는 것 없이 빈 값을 전달하도록 구현을 해준다.
값을 가져올 때 우리가 원하는 Data Type 이 아니라 Flow 이기 때문에, dataStoreText 라는 변수를 사용하여 값을 저장하거나 할 수는 없다.
따라서, 사용하는 부분에서 별도의 처리를 해주어야한다는 점을 인지하고 있어야 한다.
위와 같이 DataStore 에 대해 선언을 해주었으면,
생성하는 부분도 확인을 해보야 한다.
필자는 Application 에서 DataStore 를 생성하여 사용하도록 구현해보았다.
Application 단에서 생성하지 않아도 되지만, 필자와 같은 경우에는 Application 단에서 사용하는 Koin 과 같은 것들도 있기 때문에 한번에 처리하기 위해서 이곳에서 생성하도록 하였다.
이곳에서 자세히 봐야 할 부분은 instance 를 가져오는 부분이다.
Application 단에 선언한 DataStore 를 사용하기 위해서는 Application 의 instance 가 필요하기 때문에 getInstance 를 통해 외부에서 해당 instance 를 가져오게 되는 것이고,
getDataStore 를 통하여 외부에서 Application 단에서 생성한 dataStore에 대한 instance 를 가져올 수 있게 되는 것이다.
마지막으로,
DataStore 를 사용하는 부분에 대해서 확인해 보자.
DataStore 에 Set 하는 부분이다.
suspend로 선언한 setDataStoreText() 를 사용하기 위하여 코루틴을 사용하여 비동기적으로 호출한다.
코루틴 혹은 Rx를 사용하여 비동기로 호출하는 것 외에는 별도로 신경써서 작업할 부분은 없다.
DataStore 에서 Get 하는 부분이다.
주석에도 작성을 해두었다시피 동기 처리를 하기위하여 async와 await() 를 사용하였고, 때문에 suspend 를 붙이게 되었다. 만약, 값을 읽어오는것에 있어서 동기 처리가 필요하지 않고 비동기로 처리해도 무관하다면 await 를 사용하지 않고 그냥 호출하면 될 것이다.
값을 읽어오는데 first() 를 사용하였는데, 비동기적으로 원하는 타이밍에 한번만 값을 가져오는 경우에는 first() 사용하여 가져오면 된다.
필자가 지금까지 사용했던 패턴을 생각해보았을 때, 해당 방식을 주로 사용하였기 때문에 first() 를 사용하여 예제를 구현해 보았다.
first() 가 아닌 collect() 를 사용하여 값을 읽어오도록 사용할 수 있는데, 이 경우 다음과 같이 구현하여 사용하면 된다.
위의 사용 방법의 경우, 필자가 설명을 위해서 임시로 만들어둔 것이기 때문에 대충 작성한 것이지만,
collect 내부의 save = it 과 마찬가지로 flow 에서 값을 읽어와서 사용하도록 할 수 있다.
위와 같이 구현을 해두었다면, 단순한 호출을 통하여 데이터를 get/set 할 수 있게 된다.
필자가 학습을 위해 예제를 수정하면서 호출 한 부분이다.
viewModel 에 set/get 함수를 선언해 두었고, 그것을 사용하여 버튼을 클릭하였을 때 값을 저장하거나 읽어오도록 구현한 부분이다.
해당 게시글에 사용한 예제는 GitHub 에 올려두었다.
https://github.com/HeeGyeong/ModuleArchitecture
Preference가 deprecated 가 되었다고 하여서 DataStore로 바꾸고자 학습을 진행하였는데,
생각보다 사용하기가 까다로운면이 있는 것 같다.
설정부터 사용까지 DataStore 가 고려해야할 부분이 더 많기도 하고, 비동기적 처리, 코루틴, Flow 등 사용하기 위해서 습득해야할 지식들이 좀 있는것으로 보인다.
하지만 뭐,
DataStore 를 사용하는것을 권장하는 것에는 이유가 있지 않을까 싶다.
아직 단순히 학습을 위해 예제만 만들어 보았기 때문에 이것을 사용하는 장점에 대해서는 느끼지 못하였지만,
실제로 프로젝트에 적용하고 사용해보다 보면 DataStore의 장점을 알 수 있지 않을까 생각한다.
'Android > AAC' 카테고리의 다른 글
[Android] AAC (Android Architecture Components) 란 ? (Feat. ViewModel) (0) | 2022.05.31 |
---|---|
[Android] AAC Navigation + BottomNavigationView 사용 방법. (0) | 2022.03.11 |
[Android] AAC Navigation 사용 실전 압축 정리 (0) | 2022.02.14 |
[Android] 데이터 바인딩 어댑터 (Data Binding Adapter) 사용 방법 (0) | 2022.02.07 |
[Android] Room 라이브러리 (0) | 2020.06.22 |