DataStore๋ ์ฝ๋ฃจํด๊ณผ flow๋ฅผ ์ฌ์ฉํ๋ SharedPreferences์ ๊ฐ์ ํ์ด๋ผ๊ณ ํ ์ ์๋ค. SharedPreferences๋ฅผ ์ฌ์ฉํ ๋๋ ๋ณดํต ์ค์ ๊ฐ๊ณผ ๊ฐ์ ๋จ์ ๋ฐ์ดํฐ ์ ์ธ key-value๋ก ๋ฌถ์ด๋ ๊ฐ๋ค์ ์ ์ฅํ๋๋ฐ, primitive type๋ง ์ ์ฅํ ์ ์๋ค๋ ๋จ์ ๊ณผ, String์ผ๋ก ๋ง๋ JSON์ ์ ์ฅํ๋ค๊ณ ์ณ๋ ๋ถ์์ ๋ฐ์ํ๋ ๋ฐํ์์๋ฌ๋ฅผ ํผํ ์ ์์๋ค.
๋ํ ์์ฑ๋๋ ํ์ผ์ด XMLํ์ผ์ด๊ณ ์ค์ ํ์ผ์์ ์ ํ๊ธฐ ๋๋ฌธ์ UI ์ฐ๋ ๋์์ ๋๋ ค๋ฒ๋ฆฌ๋ฉด ANR์ด ๋ฐ์ํ๊ฑฐ๋ ๋ฐํ์์๋ฌ๊ฐ ๋ฐ์ํ ๊ฐ๋ฅ์ฑ์ด ๋ํํ๋ค. ๋น๋๊ธฐ ๊ธฐ๋ฅ๋ ์ ์ฐํ์ง์๋ค. DB์์ค์ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํด์ผ ํ๋ค๋ฉด ๋น์ฐํ Room์ ์ฌ์ฉํด์ผํ๋ค.
DataStore๋ฅผ ์ฌ์ฉํ๊ฒ ๋ ๊ณ๊ธฐ๋ ์๋ฒ์์ ๋ฐ์์ค๋ access token์ ์ ์ฅํด๋์ผ api ์์ฒญํ ๋ ํค๋์ ํ ํฐ์ ๋ฃ์ด์ ์์ฒญํ๋๋ฐ, SharedPreferences๋ ํ์ผ์ด ๋จ์์์ด ์์ ํ์ง ์์ DataStore๋ฅผ ์ ํํ๋ค.
์ด ๊ธ์์ SharedPreference -> DataStore ๋ง์ด๊ทธ๋ ์ด์ ์ ๋ค๋ฃจ์ง ์๋๋ค.
DataStore
DataStore๋ Preferences DataStore์ Proto DataStore๋ก ๋๋๋ค.
์ ์๋ ๊ธฐ์กด์ SharedPreferences์ ๊ฑฐ์ ๋์ผํ ๊ธฐ๋ฅ, ์ฌ์ฉ๋ฒ์ ๊ฐ๊ณ , ํ์๋ ์ปค์คํ ๋ฐ์ดํฐํ์ ์ Protocol Buffer๋ฅผ ํตํด ์ ์ฅํ๋ค. ์ปค์คํ ๋ฐ์ดํฐ ํ์ ์ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ Type-Safety๋ฅผ ๋ณด์ฅํ๊ธฐ ์ํ ์คํค๋ง๋ฅผ ๋ฏธ๋ฆฌ ์ง์ ํด์ผ๋๋ค๋ ๊ท์ฐฎ์์ด ์๊ธดํ๋ค.
์ค์ ๋ฒ๊ณผ ๊ฐ์ ๊ฑด ๊ณต์๋ฌธ์๋ฅผ ๋ฐ๋ผ๊ฐ๋ฉด ์ ์ ์๋ ๋ถ๋ถ์ด๊ธฐ ๋๋ฌธ์ ๋ฐ๋ก ๋ค๋ฃจ์ง ์๊ฒ ๋ค. ๋ํ ์ด๋ฒ ํ๋ก์ ํธ์์๋ Preferences DataStore๊ฐ ์ฌ์ฉ๋๊ธฐ ๋๋ฌธ์ ์ด๊ฑธ ๋ค๋ฃจ๊ฒ ๋ค.
Preferences DataStore
DataStore ํด๋์ค์ Preferencesํด๋์ค๋ฅผ ์ฌ์ฉํ์ฌ ๊ตฌํํ๋ค. Preferencesํด๋์ค๋ Mapํ์์ผ๋ก DataStore๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํ ํ์ ์ด๋ค.
์ฑ๊ธํค์ผ๋ก ์ธ์คํด์ค ๋ง๋ค๊ธฐ
val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "preferences name")
์ด ๊ณผ์ ์ด ์ ์ผ ์ค์ํ๋ค. ์ต์์ ํ๋กํผํฐ๋ก data store์ธ์คํด์ค๋ฅผ ํธ์ถํด์ ์ฑ๊ธํค์ผ๋ก ๋ง๋๋ ์์ ์ธ๋ฐ, ์ฑ๊ธํค์ผ๋ก ์ธ์คํด์ค๋ฅผ ๋ง๋ค์ง ์๋๋ค๋ฉด ์๋์ ๊ฐ์ ์๋ฌ๋ฉ์์ง๋ฅผ ๋ณผ ์ ์๋ค.
You should either maintain your DataStore as a singleton or confirm that there is no two DataStore’s active on the same file (by confirming that the scope is cancelled)
๋์ผํ ์ด๋ฆ์ ๊ฐ๋ datastore์ธ์คํด์ค๊ฐ ์ค๋ณต์ผ๋ก ์์ฑ๋์ด ๋ฒ๋ฆฐ ๋์ฐธ์ฌ๋ค.
์ฝ๊ณ ์ฐ๊ธฐ(๋ฉํฐ๋ชจ๋์์)
์ธ ๋๋ ์ฝ๋ฃจํด์์, ์ฝ์ ๋๋ flow๋ก ์๋ํ๋ค. ์ฌ๊ธฐ์๋ ์ํ์ฝ๋ ๋ง๊ณ ์ค์ ๋ก ์์ ํ๋ ์ฝ๋๋ฅผ ๊ฐ์ ธ์๋ดค๋ค.
๋ฉํฐ๋ชจ๋์ ์ฌ์ฉ ์ค์ด๊ณ data layer์ ์์ฑ๋ ์ฝ๋๋ค. ์ ์ฒด ์ฝ๋ ๋จผ์ ์ฌ๋ ค๋๊ฒ ๋ค. ๋ฆฌํ๋ ์ ํ ํฐ, ํ ํฐ ์ฌ๋ฐ๊ธ ๋ถ๋ถ๋ ์์ง๋ง ํธ์๋ฅผ ์ํด์ Access Token๋ถ๋ถ๋ง ๊ฐ์ ธ์๋ค.
@Singleton
val Context.tokenDataStore by preferencesDataStore("tokens")
class TokenRepoImpl @Inject constructor(
private val api: TokenApi,
@ApplicationContext private val context: Context
): TokenRepo {
private object PreferenceKeys {
val ACCESS_TOKEN = stringPreferencesKey("access_token")
}
override suspend fun getAccessToken(): String {
val userAccessToken: Flow<String?> = context.tokenDataStore.data.map {
it[ACCESS_TOKEN]
}
return userAccessToken.first().toString()
}
override suspend fun setAccessToken(accessToken: String) {
context.tokenDataStore.edit {prefs ->
prefs[ACCESS_TOKEN] = accessToken
}
}
}
์ต์์ ํ๋กํผํฐ๋ก ์ธ์คํด์ค๋ฅผ ์์ฑํด ์ฑ๊ธํค์ผ๋ก ๋ง๋ค์ด์ค๋ค.
@Singleton
val Context.tokenDataStore by preferencesDataStore("tokens")
์ฌ๊ธฐ์ preferencesDataStore์ ํ๋ผ๋ฏธํฐ๋ก ๋ค์ด๊ฐ๋ String๊ฐ์ ์ผ์ข ์ ๋๋ ํฐ๋ฆฌ๋ค. ์ฌ๊ธฐ์๋ tokens์ธ๋ฐ, ์์ผ๋ก tokenDataStore๋ก ์ ๊ทผํ๋ key-value ์์ ๋ชจ๋ tokens ๋ฐ์ ์์ฑ๋๋ค.
private object PreferenceKeys {
val ACCESS_TOKEN = stringPreferencesKey("access_token")
}
key-value์์ผ๋ก ๋ค์ด๊ฐ ๊ฐ์ Key๋ฅผ ๋ด๋ ๊ณณ์ด๋ค. ๊ทธ๋ฅ “access_token”์ด๋ผ๊ณ ์ง์ ๊ฐ์ ๋ฃ์ด๋ ๋์ง๋ง ๊ฐ๋ ์ฑ์ ๋์ด๊ธฐ ์ํด object๋ก ๋ฌถ์ด์ ๋ง๋ค์ด ์คฌ๋ค.
์ง์๋๋ PreferencesKey ์ ํ์ ์ฌ๊ธฐ์ ํ์ธํ ์ ์๋ค.
override suspend fun setAccessToken(accessToken: String) {
context.tokenDataStore.edit {prefs ->
prefs[ACCESS_TOKEN] = accessToken
}
}
datastore์ ์ฐ๋ ๋ถ๋ถ์ด๋ค. SharedPreferences์ ์ ์ฌํ ๋ชจ์ต์ธ๋ฐ, edit ๋ฉ์๋๋ ๋ฐ์ดํฐ๋ฅผ ํธ๋์ญ์ ๋ฐฉ์์ผ๋ก ์ ๋ฐ์ดํธ ํ๋ค. ๋๋ค๋ก ๋ฌถ์ธ ๋ถ๋ถ์ ๋จ์ผ ํธ๋์ญ์ ์ผ๋ก ์ทจ๊ธ๋๋ค. suspend fun์ผ๋ก ์ ์ธ๋์ด ์๊ธฐ ๋๋ฌธ์ ๋ฐ๋์ ์ฝ๋ฃจํด์์ ํธ์ถํด์ผํ๋ค.
override suspend fun getAccessToken(): String {
val userAccessToken: Flow<String?> = context.tokenDataStore.data.map {
it[ACCESS_TOKEN]
}
return userAccessToken.first().toString()
}
Flow๋ฅผ ํตํด ๊ฐ์ ์ฝ๋ ์ฝ๋๋ค. first()๋ Flow์ ์ฒซ๋ฒ์งธ ๊ฐ์ collectํ๋ ๋ฉ์๋์ธ๋ฐ, ์ ์ฝ๋์์๋ ๊ฐ์ด ํ๋๊ธฐ ๋๋ฌธ์ first๋ก ์ถฉ๋ถํ๋ค.
HTTPํต์ ํค๋์ ํ ํฐ ๊ฐ์ ๋ฃ์ ๋๋ ๋น๋๊ธฐ๋ก ์ฒ๋ฆฌํ ๋ ๊ฐ ๋ณด์ฅ์ด ์๋ ์ ์์ด์ runBlocking์ ์ฌ์ฉํ๋ค.
์ฐธ์กฐ:
https://medium.com/androiddevelopers/introduction-to-jetpack-datastore-3dc8d74139e7
https://developer.android.com/topic/libraries/architecture/datastore?authuser=1&hl=ko
"๋๊ธ, ๊ณต๊ฐ ๋ฒํผ ํ ๋ฒ์ฉ ๋๋ฅด๊ณ ๊ฐ์ฃผ์๋ฉด ํฐ ํ์ด ๋ฉ๋๋ค"