로컬 저장소는 네트워크와 무관하게 데이터를 저장하는 공간이다
대표적으로 SQLite와 Room이 있고 이 두가지 방식의 차이점과 사용법을 정리해보려고 한다 🧐
특정 기능에 대해서만 궁금한 사람들은 목차를 클릭해서 빠르게 확인해보시길!
✏️ 로컬 저장소란?
들어가기에 앞서 로컬 저장소가 뭔지 헷갈린다면 이해하고 넘어가보자
로컬 저장소는 네트워크 서버가 아닌 디바이스에 데이터를 저장하는 공간을 의미한다
디바이스에 저장하기 때문에 네트워크 연결 여부와는 관계 없이 사용할 수 있다
✏️ SQLite
SQLite는 안드로이드에 내장된 데이터베이스로 구조화된 데이터를 저장할 때 사용한다
직접 SQL 쿼리를 작성해야하는 번거로움이 있다
현재는 Room을 자주 사용하지만 이전에는 SQLite가 기본 옵션이었다!
- SQL 문법을 사용해 CRUD 작업을 수행
- Cursor를 사용해 데이터를 직접 매핑해야 함
- 데이터베이스의 스레드 관리를 개발자가 직접 해야 함
- 유효성 검사 및 쿼리 검증이 런타임에서 이루어짐
🔹 SQLite 사용법
SQLite를 어떻게 사용하는지 간단한 코드를 통해 살펴보자
우선 SQLite를 사용하려면 SQLiteOpenHelper
를 상속받아 데이터베이스를 관리해야한다
class DBHelper(context: Context) : SQLiteOpenHelper(context, DATABASE_NAME, null, DATABASE_VERSION) {
override fun onCreate(db: SQLiteDatabase) {
db.execSQL("CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, age INTEGER)")
}
override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
db.execSQL("DROP TABLE IF EXISTS users")
onCreate(db)
}
fun insertUser(name: String, age: Int) {
val db = writableDatabase
val values = ContentValues().apply {
put("name", name)
put("age", age)
}
db.insert("users", null, values)
}
fun getUser(id: Int): User? {
val db = readableDatabase
val cursor = db.rawQuery("SELECT * FROM users WHERE id = ?", arrayOf(id.toString()))
return if (cursor.moveToFirst()) {
val user = User(cursor.getInt(0), cursor.getString(1), cursor.getInt(2))
cursor.close()
user
} else {
cursor.close()
null
}
}
}
onCreate
: 테이블 생성 (앱이 최초 실행될 때 한번만 호출)onUpgrade
: DB 업그레이드 (마이그레이션)insertUser
: 데이터 삽입 예시getUser
: 특정 사용자 조회 예시
MainActivity에서의 사용:
val dbHelper = DBHelper(this)
dbHelper.insertUser("홍길동", 25)
val user = dbHelper.getUser(1)
Log.d("DB", "User: ${user?.name}, Age: ${user?.age}")
SQLite는 직접적인 SQL 작성과 수동 데이터 매핑으로 인해 코드가 복잡하고 유지보수가 어렵다
이런 문제를 해결하기 위해 Room이 등장하였다
✏️ Room
Room은 SQLite를 추상화한 Jetpack 라이브러리로 직접 SQL을 작성하지 않고도 데이터베이스를 다룰 수 있게 한다
- 자동 객체 매핑: 쿼리 결과를 지정한 데이터 클래스로 자동 매핑
- SQL 작성 간소화: @Query 어노테이션을 사용해 간단히 쿼리를 정의 가능
- 스레드 관리: 백그라운드 스레드에서 데이터 작업을 자동으로 처리하여 메인 스레드를 차단하지 않음
- 유효성 검사: 컴파일 타임에 SQL 문법과 데이터베이스 스키마를 검증하여 런타임 오류를 방지
- LiveData 및 Flow 지원: 데이터 변경 사항을 실시간으로 감지하여 UI에 반영 가능
- 마이그레이션 지원: 데이터베이스 구조 변경 시, 간단한 API로 마이그레이션을 처리
🔸 Room 사용법 (Entity, Dao, Database)
Room을 사용하려면 Entity, Dao, Database를 정의해야 한다
1️⃣ Entity
데이터베이스 테이블을 정의하는 데이터 클래스
@Entity(tableName = "users")
data class User(
@PrimaryKey val id: Int,
val name: String,
val age: Int
)
2️⃣ Dao (Data Access Object)
쿼리를 추상화한 인터페이스 CRUD 연산 수행
쿼리문을 어노테이션으로 정의하고 Room이 구현한다
@Dao
interface UserDao {
@Insert
fun insertUser(user: User)
@Query("SELECT * FROM users WHERE id = :userId")
fun getUser(userId: Int): User
}
3️⃣ Databse
데이터베이스의 진입점(Access Point)으로 RoomDatabase를 상속받아 정의한다
@Database(entities = [User::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
abstract fun userDao(): UserDao
}
MainActivity에서의 사용:
val db = Room.databaseBuilder(
applicationContext,
AppDatabase::class.java, "example-db"
).build()
val userDao = db.userDao()
userDao.insertUser(User(name = "홍길동", age = 25))
val user = userDao.getUser(1)
Log.d("DB", "User: ${user?.name}, Age: ${user?.age}")
✏️ Room과 SQLite의 차이점
기능 | SQLite | Room |
쿼리 작성 | 직접 SQL 작성 필요 | @Query 어노테이션으로 간결한 정의 가능 |
데이터 매핑 | Cursor를 사용해 수동 매핑 필요 | 자동 객체 매핑 지원 |
스레드 관리 | 별도 스레드 관리 필요 | 자동 백그라운드 스레드 지원 |
유효성 검사 | 실행 중 오류 발생 가능 | 컴파일 타임에 SQL 문법 및 엔터티 검증 |
라이브 데이터 연동 | 기본적으로 불가능 | LiveData, Flow, RxJava와 통합 지원 |
마이그레이션 | 수동 처리 필요 | 간단한 마이그레이션 API 제공 |
위의 표를 토대로 SQLite보다 Room을 추천하는 이유를 정리해보았다:
- 추상화와 편의성: Room은 SQL 문법을 몰라도 쉽게 사용할 수 있다
- 안전성: Room은 컴파일 타임에 SQL 문법과 스키마를 검증해 런타임 오류를 줄인다
- 생산성: Room은 DAO와 객체 매핑을 제공해 생산성을 높이고, SQLite는 수동 처리로 인해 복잡하다
- 실시간 데이터 연동: Room은 LiveData, Flow와 같은 현대적인 데이터 흐름 지원한다
✅ 마무리
SQLite는 직접 SQL을 작성해야 하므로 번거롭지만
Room은 이를 추상화하여 더욱 편리하게 사용할 수 있도록 지원한다
따라서! Room을 사용하는 것을 권장한다!
📌 참고 자료
'Android > Study' 카테고리의 다른 글
[Android/Kotlin] RecyclerView에 ItemDecoration으로 구분선 넣기 (2) | 2025.02.06 |
---|---|
[Android] RecyclerView와 ViewHolder 패턴 (+ListVIew) (4) | 2025.02.05 |
[Jetpack Compose] Android Navigation 기초 (2) | 2025.01.23 |
[Jetpack Compose] Scaffold 사용법 (1) | 2025.01.21 |
[Jetpack Compose] 위치 권한 요청 및 처리하기 (1) | 2025.01.15 |