[Android] Room, sharedPreference, DataStore

๐Ÿ’ก๋กœ์ปฌ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๊ตฌํ˜„์„ ์œ„ํ•ด ์‚ฌ์šฉ๋˜๋Š” Room, sharedPreference, DataStore์˜ ์ฐจ์ด์— ๋Œ€ํ•˜์—ฌ ์ •๋ฆฌํ•˜์˜€์Šต๋‹ˆ๋‹ค.

 

๊ฐœ์š”

  • Room, SharedPreferences, DataStore๋Š” ๋ชจ๋‘ ์•ˆ๋“œ๋กœ์ด๋“œ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๋กœ์ปฌ ํ™˜๊ฒฝ์— ์ €์žฅํ•˜๊ณ  ๊ด€๋ฆฌํ•˜๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค.
  • ๊ฐ ๋ฐฉ์‹์€ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๋Š” ์šฉ๋„์™€ ๋ฐฉ์‹์— ์ฐจ์ด๊ฐ€ ์žˆ์œผ๋ฉฐ, ๊ฐ ์žฅ๋‹จ์ ๊ณผ ์„ฑ๋Šฅ์˜ ์ฐจ์ด๊ฐ€ ์žˆ์–ด์„œ ์ฐจ์ด๋ฅผ ์•Œ๊ณ  ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

Room

  • Room์€ ์•ˆ๋“œ๋กœ์ด๋“œ์—์„œ ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ ORM ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ž…๋‹ˆ๋‹ค.
    • Object-Relational Mapping : ๊ฐ์ฒด ๊ด€๊ณ„ ๋งคํ•‘ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ
  • ๋‚ด๋ถ€์ ์œผ๋กœ SQLite ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์‚ฌ์šฉํ•˜์ง€๋งŒ, ๋” ์‰ฝ๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ฐ์ฒด ์ง€ํ–ฅ์ ์ธ ๋ฐฉ์‹์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
  • SQLite์˜ ๋ณต์žกํ•œ SQL ์ฟผ๋ฆฌ ์ž‘์„ฑ ๊ณผ์ •์„ ์ถ”์ƒํ™”ํ•˜์—ฌ ๋” ์‰ฝ๊ฒŒ ๋ฐ์ดํ„ฐ๋ฅผ ๊ด€๋ฆฌํ•˜๊ณ , ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ž‘์—…์„ ์œ„ํ•œ ๊ฐ„๋‹จํ•œ API๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

ํŠน์ง•

  • ๊ฐ ํ…Œ์ด๋ธ”์ด ์„œ๋กœ ๊ด€๊ณ„๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๋ณต์žกํ•œ ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๋ฅผ ํ…Œ์ด๋ธ”๋กœ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • Entity-DAO ๊ตฌ์กฐ๋ฅผ ํ™œ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ์ฒด๋กœ ํ‘œํ˜„(Entity)ํ•˜๋Š” ํด๋ž˜์Šค์™€, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ์‚ฐ์„ ๋‹ด๋‹นํ•˜๋Š”(DAO)๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
  • Coroutines, LiveData, Flow๋ฅผ ํ†ตํ•ด ๋ฐ์ดํ„ฐ ๋ณ€๊ฒฝ์„ ๊ฐ์ง€ํ•˜๊ณ  ์‹ค์‹œ๊ฐ„ UI๋ฅผ ์—…๋ฐ์ดํŠธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
@Entity
data class User(
    @PrimaryKey val uid: Int,
    @ColumnInfo(name = "first_name") val firstName: String?,
    @ColumnInfo(name = "last_name") val lastName: String?
)

@Dao
interface UserDao {
    @Query("SELECT * FROM user")
    fun getAll(): List<User>

    @Insert
    fun insertAll(vararg users: User)
}

@Database(entities = [User::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
    abstract fun userDao(): UserDao
}

SharedPreferences

  • SharedPreferences๋Š” Android์—์„œ ๊ธฐ๋ณธ์ ์œผ๋กœ ์ œ๊ณตํ•˜๋Š” key - value ํ˜•์‹์œผ๋กœ ๊ฐ„๋‹จํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•  ์ˆ˜ ์žˆ๋Š” ์ €์žฅ์†Œ์ž…๋‹ˆ๋‹ค.
  • ์ฃผ๋กœ ์•ฑ ์„ค์ •๊ฐ’์ด๋‚˜ ๊ฐ„๋‹จํ•œ ์‚ฌ์šฉ์ž ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•˜์—ฌ, ๋‚ด๋ถ€ ์ €์žฅ์†Œ์— XML ํŒŒ์ผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜์—ฌ ์˜๊ตฌ์ ์œผ๋กœ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค.

ํŠน์ง•

  • ๊ธฐ๋ณธ ํƒ€์ž…์˜ ๋ฐ์ดํ„ฐ๋ฅผ ํ‚ค - ๊ฐ’ ์Œ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด์„œ ๊ฐ„๋‹จํ•œ ๋ฐ์ดํ„ฐ ์ €์žฅ์— ๋น ๋ฅด๊ณ  ์œ ์šฉํ•˜๊ฒŒ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๋ฐ์ดํ„ฐ ์ €์žฅ์„ ๋น„๋™๊ธฐ ์ ์œผ๋กœ ์ฒ˜๋ฆฌ(apply()), ๋™๊ธฐ์ ์œผ๋กœ ์ฒ˜๋ฆฌ(commit())ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
val sharedPreferences = getSharedPreferences("prefs", Context.MODE_PRIVATE)
val editor = sharedPreferences.edit()

// ๋ฐ์ดํ„ฐ ์ €์žฅ
editor.putString("user_name", "John Doe")
editor.putInt("user_age", 30)
editor.apply()

// ๋ฐ์ดํ„ฐ ์ฝ๊ธฐ
val userName = sharedPreferences.getString("user_name", null)
val userAge = sharedPreferences.getInt("user_age", -1)

DataStore

  • DataStore๋Š” Android์—์„œ SharedPreferences์˜ ๋Œ€์ฒด๋กœ ์ œ๊ณต๋˜๋Š” ํ˜„๋Œ€์ ์ธ ๋ฐ์ดํ„ฐ ์ €์žฅ ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค.
  • SharedPreferences์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๊ณ  ํ‚ค - ๊ฐ’ ์Œ์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜์ง€๋งŒ, ๋น„๋™๊ธฐ ๋ฐฉ์‹์„ ๋” ์•ˆ์ „ํ•˜๊ณ  ํšจ์œจ์ ์œผ๋กœ ๋™์ž‘ํ•˜๊ฒŒ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํŠน์ง•

  • Coroutines, Flow ๊ธฐ๋ฐ˜์œผ๋กœ ๋น„๋™๊ธฐ ์ž‘์—…์„ ๊ธฐ๋ณธ์ ์œผ๋กœ ์ง€์›ํ•˜๋ฉฐ, ์šฐ์ˆ˜ํ•œ ์„ฑ๋Šฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
  • IO ์Šค๋ ˆ๋“œ์—์„œ ์ž‘๋™ํ•˜์—ฌ ๋ฐ์ดํ„ฐ ์ถฉ๋Œ์ด๋‚˜ ์†์‹ค์„ ๋ฐฉ์ง€ํ•˜์—ฌ ๋ฐ์ดํ„ฐ ๋ฌด๊ฒฐ์„ฑ์„ ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค.
  • Proto DataStore๋ฅผ ํ™œ์šฉํ•˜๋ฉด ๋” ๊ตฌ์กฐํ™”๋œ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Preferences DataStore

  • SharedPreferences์™€ ์œ ์‚ฌํ•œ ํ‚ค - ๊ฐ’ ํ˜•์‹์œผ๋กœ ์ €์žฅํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.

Proto DataStore

  • Protocol Buffers๋ฅผ ์‚ฌ์šฉํ•ด ๋” ๊ตฌ์กฐํ™” ๋œ ๋ฐ์ดํ„ฐ ์ €์žฅ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.
  • ์ด๋ฅผ ํ™œ์šฉํ•˜๋ฉด ํด๋ž˜์Šค๋‚˜ ๊ฐ์ฒด๋ฅผ ์ €์žฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Room vs SharedPreferences vs DataStore

ํŠน์ง• Room SharedPreferences DataStore
๋ฐ์ดํ„ฐ ๊ตฌ์กฐ ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค (ํ…Œ์ด๋ธ” ๊ตฌ์กฐ) ํ‚ค-๊ฐ’ ์Œ ํ‚ค-๊ฐ’ ์Œ (Preferences), ํ”„๋กœํ† ์ฝœ ๋ฒ„ํผ (Proto)
์ €์žฅ์†Œ ์œ„์น˜ SQLite ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํŒŒ์ผ XML ํŒŒ์ผ ํ”„๋กœํ† ์ฝœ ๋ฒ„ํผ ํŒŒ์ผ ๋˜๋Š” Preferences ํŒŒ์ผ
๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ (Coroutines, LiveData, Flow) ๊ธฐ๋ณธ์ ์œผ๋กœ ๋™๊ธฐ (apply()๋Š” ๋น„๋™๊ธฐ) ๊ธฐ๋ณธ์ ์œผ๋กœ ๋น„๋™๊ธฐ (Coroutines, Flow)
์‚ฌ์šฉ ์šฉ๋„ ๋ณต์žกํ•œ ๋ฐ์ดํ„ฐ ๋ฐ ๊ตฌ์กฐํ™”๋œ ๋ฐ์ดํ„ฐ ์ €์žฅ ๊ฐ„๋‹จํ•œ ์„ค์ •๊ฐ’ ๋˜๋Š” ์†Œ๋Ÿ‰์˜ ๋ฐ์ดํ„ฐ ์ €์žฅ ๊ฐ„๋‹จํ•œ ์„ค์ •๊ฐ’ ๋˜๋Š” ๋” ๋ณต์žกํ•œ ๋ฐ์ดํ„ฐ ์ €์žฅ
๊ตฌ์กฐํ™”๋œ ๋ฐ์ดํ„ฐ ์ง€์› ์ง€์› ์ง€์›ํ•˜์ง€ ์•Š์Œ Preferences๋Š” ํ‚ค-๊ฐ’, Proto๋Š” ๊ตฌ์กฐํ™”๋œ ๋ฐ์ดํ„ฐ ์ง€์›
์„ฑ๋Šฅ ํฐ ๋ฐ์ดํ„ฐ, ๋ณต์žกํ•œ ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฅผ ํšจ์œจ์ ์œผ๋กœ ์ฒ˜๋ฆฌ ๊ฐ„๋‹จํ•œ ๋ฐ์ดํ„ฐ์— ์ ํ•ฉํ•˜์ง€๋งŒ ๋Œ€๊ทœ๋ชจ ๋ฐ์ดํ„ฐ์—” ๋ถ€์ ํ•ฉ ์„ฑ๋Šฅ ์šฐ์ˆ˜ (๋น„๋™๊ธฐ, IO ์Šค๋ ˆ๋“œ์—์„œ ์‹คํ–‰)

์ •๋ฆฌ

  • Room์€ ๋ณต์žกํ•œ ๊ตฌ์กฐ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๊ณ  ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์•ฑ์— ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค.
  • SharedPreferences๋Š” ๊ฐ„๋‹จํ•œ ์„ค์ •๊ฐ’์ด๋‚˜ ์‚ฌ์šฉ์ž ๋ฐ์ดํ„ฐ์™€ ๊ฐ™์€ ์†Œ๊ทœ๋ชจ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•  ๋•Œ ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค.
  • DataStore๋Š” SharedPreferences์˜ ์ƒ์œ„ ๋ฒ„์ „์œผ๋กœ, ๋น„๋™๊ธฐ ๋ฐ์ดํ„ฐ ์ €์žฅ์ด ๊ธฐ๋ณธ์ ์œผ๋กœ ํ•„์š”ํ•˜๊ฑฐ๋‚˜ ๋” ๊ตฌ์กฐํ™”๋œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ด€๋ฆฌํ•  ๋•Œ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.
  • ์•ฑ์˜ ์š”๊ตฌ ์‚ฌํ•ญ์— ๋”ฐ๋ผ ์ƒํ™ฉ์— ๋งž๊ฒŒ ์‚ฌ์šฉํ•˜๋ฉด ํšจ์œจ์ ์ธ ๋กœ์ปฌ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.