DataStore를 이번에 처음 제대로 써봤습니다..!
SharedPreferences → EncryptedSharedPreferences → DataStore로 왜 넘어가야 하는지 궁금해서 정리해봤어요!
SharedPreferences가 왜 더 이상 추천되지 않을까 ?
1. 동기 방식이므로 ANR 위험성이 존재
: commit() / apply() 모두 파일 I/O 기반
- commit() → 동기(blocking), 완료될 때까지 UI Thread 멈춤
- apply() → 비동기처럼 보이지만 디스크 I/O는 백그라운드에서 처리
사실 자주 발생하진 않을 것 같은데, 저장량이 많거나 여러 쓰기 요청이 한 번에 몰리면 영향이 있을 수 있습니다
2. 앱 내부 저장소에 XML 파일 형태로 저장되므로 값이 그대로 노출
: 이를 해결하기 위해 공식으로 지원되는 EncryptedSharedPreferences 가 있었는데 Deprecated됨
-> 이러한 이유들로 현재 구글에서 공식적으로 권장하는 방법은 DataStore를 사용하는 것입니다
DataStore란 ?
SharedPreferences의 XML 기반·동기 저장 방식을 개선한 Jetpack 기반 비동기 Key-Value 저장소입니다 (Binary 포맷으로 저장)
사용법은 아래와 같습니다
1️⃣ library 연동
//toml 파일에 선언
datastore = { group = "androidx.datastore", name = "datastore-preferences",
version.ref = "datastore"} // 1.1.1 사용
//build.gradle(app) 선언
implementation(libs.datastore)
2️⃣ Context기반으로 접근가능한 datastore 생성
val Context.dataStore by preferencesDataStore(
name = "test_datastore" // datastore 명칭
)
3️⃣ 비동기 형태로 save, get 함수 생성
DataStore는 기본적으로 비동기 + 코루틴 기반이라, 값을 저장할 때도 suspend, 가져올 때는 Flow로 동작
suspend fun <T> save(
context: Context,
key: Preferences.Key<T>,
value: T
) {
context.dataStore.edit { prefs ->
prefs[key] = value
}
}
fun <T> get(
context: Context,
key: Preferences.Key<T>
): Flow<T?> {
return context.dataStore.data.map { prefs ->
prefs[key]
}
}
4️⃣ 저장, 불러오기
//위에서 생성한 함수 사용
/
save(context, stringPreferencesKey("token"), "토큰값")
get(context, stringPreferencesKey("token"))
사용법은 생각보다 꽤 간단했어요!
정리해보자면, SharedPreference와 DataStore의 차이는 아래와 같습니다
| SharedPreference | DataStore | |
| 구조 | XML 파일 | Binary file |
| I/O 방식 | 동기 | 완전 비동기(Coroutine + Flow) |
| 스레드 안전성 | 완벽히 안전하지 않음 | 철저히 스레드-safe |
| 대용량 처리 | 비효율적 | Stream 기반으로 안전하게 처리 |
| 타입 안정성 |
key-string 기반 , 비교적 느슨 | 키 자체에 타입 존재 |
여기서 각각 타입 안정성만 좀 확인해보자면,
[SharePreference] : 다른 타입 가져오려고 하면 런타임에서 오류 발생
val prefs = context.getSharedPreferences("test", Context.MODE_PRIVATE)
prefs.edit()
.putString("age", "20") // age에 스트링 저장
.apply()
//값을 가져올 때
val age: Int = prefs.getInt("age", 0) //런타임에서 ClassCastException
[DataStore] : 타입 미일치 시 컴파일에서 오류 발생
왜냐하면, DataStore는 키가 타입을 정의하기 때문에, 저장할 때도, 읽을 때도 컴파일 단계에서 오류를 잡아줍니다!
object PrefKeys {
val AGE = intPreferencesKey("age")
val NICKNAME = stringPreferencesKey("nickname")
}
prefs[PrefKeys.AGE] = "20" //int에 string 넣으려고 해서 컴파일타임에서 오류
하지만, DataStore도 암호화가 자동으로 지원되진 않기 때문에 민감 정보 저장 시 권장사항은 Crypto API 와 DataStore를 같이 쓰는 것입니다
모든 정보를 암호화할 필욘 없지만 토큰과 같은 민감정보들, 그리고 개인정보들은 암호화를 사용해야겠죠..!
암호화 방법에 대해서는 2탄 포스팅으로 돌아오겠습니다!
'📱 Android' 카테고리의 다른 글
| [Android] ForegroundService - SecurityException (0) | 2025.10.24 |
|---|---|
| [Android] AudioManager와 isSpeakerPhoneOn Deprecated (0) | 2025.10.18 |
| [Android] 소켓 연결하기 - WebSocket , Socket.IO (0) | 2025.09.27 |
| [Android] 하나의 화면에 다양한 UI 블록을 구성하는 3가지 방식 (2) | 2025.07.28 |
| [Android] NetworkInfo Deprecated (0) | 2025.06.06 |