
SharedPreferences DataStore 비교에서 가장 먼저 잡아야 할 결론은 간단합니다. 새로 만드는 설정 저장 구조라면 DataStore를 우선 검토하는 편이 좋습니다. 다만 기존 앱의 SharedPreferences를 무조건 즉시 갈아엎어야 한다는 뜻은 아닙니다.
DataStore는 SharedPreferences를 대체하기 위해 공식 문서에서 권장되는 저장 방식입니다. 핵심은 단순히 이름이 새롭다는 데 있지 않습니다. 비동기 흐름, 일관된 데이터 처리, Preferences DataStore와 Proto DataStore라는 선택지를 통해 설정 저장 코드를 더 예측 가능하게 만드는 데 있습니다.
먼저 결론
- 새 기능이라면 SharedPreferences보다 DataStore를 먼저 검토합니다.
- 단순 key-value 설정이면 Preferences DataStore가 자연스럽습니다.
- 타입이 중요한 구조화 설정이면 Proto DataStore가 더 적합합니다.
- 기존 SharedPreferences는 마이그레이션 비용과 위험을 보고 단계적으로 옮깁니다.
- DataStore는 작은 설정 저장에 적합하지, 모든 로컬 데이터 저장소를 대체하는 도구는 아닙니다.
설정 저장은 작아 보이지만 앱 전체에서 오래 남는 코드가 되기 쉽습니다. 그래서 처음에는 조금 더 명확한 구조를 선택하는 편이 나중에 유지보수 비용을 줄여 줍니다.
SharedPreferences는 오랫동안 Android에서 간단한 설정값 저장에 쓰였습니다. 로그인 유지 여부, 다크 모드 설정, 마지막 선택 탭, 온보딩 완료 여부 같은 값에는 사용법도 쉽고 진입 장벽도 낮습니다.
문제는 앱이 조금 커진 뒤에 나타납니다. 여러 화면에서 같은 preference를 읽고 쓰기 시작하고, 저장값이 UI 상태와 연결되고, 기본값과 마이그레이션 규칙이 늘어나면 단순 key-value 저장도 점점 설계 문제가 됩니다.
- 같은 key를 여러 곳에서 직접 문자열로 다룬다.
- 저장값 변경을 화면 상태에 자연스럽게 연결하기 어렵다.
- 동기 API에 기대어 메인 스레드에서 읽고 쓰는 코드가 남는다.
- 기존 key를 새 구조로 옮기는 기준이 코드 곳곳에 흩어진다.
- Boolean, String, Int 몇 개로 시작했는데 점점 도메인 설정처럼 커진다.
SharedPreferences가 틀렸다는 뜻은 아닙니다. 작은 앱이나 오래된 코드에서는 여전히 남아 있을 수 있습니다. 다만 새 코드에서 굳이 같은 구조를 반복할 이유는 줄어들었습니다.
둘을 비교할 때는 저장 API 이름보다 사용 흐름을 먼저 봐야 합니다. SharedPreferences는 간단한 key-value 저장에 익숙한 방식이고, DataStore는 저장값을 비동기 데이터 흐름으로 다루는 방식입니다.
새 코드에서는 이 차이가 큽니다. 화면은 설정값을 관찰하고, repository는 저장 방식을 숨기고, 쓰기 작업은 suspend 함수로 제한할 수 있습니다. 그래서 설정값이 UI 상태와 연결될수록 DataStore 쪽 구조가 더 안정적입니다.
DataStore가 해결하려는 문제
DataStore는 설정 저장을 Flow 기반으로 읽고, suspend 함수 안에서 수정하는 방향으로 설계합니다. 그래서 저장값을 UI 상태와 연결하거나, 코루틴 기반 코드와 맞추거나, 저장 로직을 repository 안에 숨기기 쉽습니다. 화면 상태와 저장값의 경계를 잡는 문제는 ViewModel 상태 설계와도 자연스럽게 이어집니다.
공식 문서는 DataStore를 SharedPreferences를 대체하는 개선된 데이터 저장 솔루션으로 설명합니다. 이 말은 DataStore가 Room이나 파일 저장까지 모두 대체한다는 뜻이 아닙니다. 범위는 작고 단순한 앱 설정, 사용자 preference, 가벼운 로컬 상태에 가깝습니다.
핵심은 저장 방식보다 읽고 쓰는 흐름입니다. SharedPreferences는 값 하나를 바로 꺼내는 느낌이 강합니다. DataStore는 설정 상태를 하나의 데이터 흐름으로 보고, 변경될 때마다 안전하게 관찰하는 쪽에 가깝습니다.
Preferences DataStore와 Proto DataStore 차이
DataStore에는 두 가지 선택지가 있습니다.
Preferences DataStore는 key-value 방식입니다. 미리 스키마를 만들지 않고, key를 정의한 뒤 Boolean, String, Int 같은 값을 저장합니다. SharedPreferences와 쓰임새가 가장 비슷해서 기존 설정 저장 코드를 옮길 때 접근하기 쉽습니다.
Proto DataStore는 Protocol Buffers로 스키마를 정의합니다. 저장할 데이터 구조가 명확하고 타입 안정성이 중요할 때 어울립니다. 예를 들어 알림 설정, 정렬 기준, 테마, 필터 옵션이 하나의 사용자 설정 모델로 묶여야 한다면 Proto DataStore가 더 읽기 좋은 구조가 될 수 있습니다.
- key 몇 개를 저장한다면 Preferences DataStore
- 설정 모델이 하나의 구조로 커진다면 Proto DataStore
- 관계형 데이터, 목록, 검색, 복잡한 쿼리가 필요하다면 Room
- 파일 자체를 저장해야 한다면 파일 저장 또는 MediaStore
DataStore 선택에서 중요한 기준은 저장할 수 있느냐가 아니라 나중에 읽고 바꿀 때 구조가 무너지지 않느냐입니다.
마이그레이션은 언제 해야 할까
기존 앱에 SharedPreferences가 있다면 바로 전체 교체부터 생각하지 않는 편이 좋습니다. 먼저 저장값의 성격을 나눠야 합니다.
- 새로 추가하는 설정은 DataStore로 시작할 수 있습니다. 기존 코드와 섞이는 기간이 있더라도 새 기능부터 구조를 바꾸면 위험이 작습니다.
- 자주 바뀌고 UI와 강하게 연결되는 설정은 마이그레이션 우선순위가 높습니다. 테마, 정렬 기준, 필터 상태처럼 화면 상태와 맞물리는 값은 Flow로 다루는 이점이 큽니다.
- 거의 바뀌지 않는 legacy flag는 억지로 먼저 옮기지 않아도 됩니다. 마이그레이션 자체가 버그를 만들 수 있기 때문입니다.
공식 API에는 SharedPreferencesMigration이 준비되어 있습니다. 기존 SharedPreferences의 key를 DataStore로 옮길 수 있습니다. 다만 마이그레이션 후에도 이전 SharedPreferences를 계속 쓰면 어느 쪽 값이 진짜인지 헷갈릴 수 있습니다. 옮긴 key는 새 구조에서만 다루도록 정리하는 것이 안전합니다.
코드 예제
Preferences DataStore는 보통 Context 확장 property로 시작합니다.
private val Context.userSettingsDataStore by preferencesDataStore(
name = "user_settings"
)읽을 때는 DataStore의 data Flow를 domain 값으로 바꿉니다.
object UserSettingsKeys {
val DARK_MODE = booleanPreferencesKey("dark_mode")
}
class UserSettingsRepository(
private val dataStore: DataStore<Preferences>
) {
val darkModeEnabled: Flow<Boolean> =
dataStore.data.map { preferences ->
preferences[UserSettingsKeys.DARK_MODE] ?: false
}
suspend fun setDarkModeEnabled(enabled: Boolean) {
dataStore.edit { preferences ->
preferences[UserSettingsKeys.DARK_MODE] = enabled
}
}
}SharedPreferences에서 옮길 때는 SharedPreferencesMigration을 연결할 수 있습니다.
private val Context.userSettingsDataStore by preferencesDataStore(
name = "user_settings",
produceMigrations = { context ->
listOf(
SharedPreferencesMigration(
context = context,
sharedPreferencesName = "legacy_user_settings"
)
)
}
)이 예제에서 중요한 부분은 코드 길이가 아닙니다. 설정 저장을 repository 안으로 모으고, 화면은 Flow를 관찰하고, 쓰기는 suspend 함수로 제한한다는 구조입니다.
실전 체크리스트
- 이 값은 앱 설정이나 사용자 preference인가?
- 값이 작고 단순한가?
- 여러 화면에서 같은 값을 관찰해야 하는가?
- 새 기능이라 처음부터 저장 구조를 정할 수 있는가?
- 기존 SharedPreferences key를 옮긴 뒤 이전 접근 경로를 제거할 수 있는가?
- 타입 안정성이 중요한 설정 모델인가?
- 목록, 검색, 정렬, 관계형 쿼리가 필요한 데이터는 아닌가?
1~5번이 중요하면 DataStore가 잘 맞습니다. 6번이 중요하면 Proto DataStore를 검토합니다. 7번에 해당하면 DataStore가 아니라 Room이나 다른 저장 방식을 봐야 합니다.
마무리
SharedPreferences DataStore 비교의 핵심은 “무조건 최신 기술을 쓰자”가 아닙니다. 새 설정 저장 구조에서는 DataStore를 기본 후보로 두고, 기존 SharedPreferences는 위험이 작은 영역부터 단계적으로 옮기는 것이 현실적인 기준입니다.
Preferences DataStore는 SharedPreferences와 비슷한 문제를 더 안전한 흐름으로 다루게 해 줍니다. Proto DataStore는 설정이 하나의 모델로 커질 때 더 명확한 구조를 줍니다.
작은 설정값일수록 대충 저장해도 된다고 생각하기 쉽습니다. 하지만 앱이 오래 갈수록 이런 작은 저장 구조가 화면 상태, 사용자 경험, 유지보수성을 조용히 좌우합니다.
공식 문서는 DataStore의 기본 방향과 구현 예제를 자세히 설명합니다. 더 깊게 확인하려면 Android Developers DataStore 문서, Preferences DataStore codelab, Proto DataStore codelab을 함께 보는 것이 좋습니다.