Android에서 Database를 왜 배울까?
대부분의 정보는 서버에 저장하지만 클라이언트에서만 저장해야 하는 값도 존재한다. 또한 이러한 지식을 알고 있으면 서버 개발자와의 협업에도 유리하다! 그래서 안드로이드를 공부하더라도 DB를 배우는 것이 좋다. 안드로이드에서도 (Key-Value 및 관계형 데이터베이스) 형태 기반으로 값을 저장 가능할 수 있다.
대표적인 저장 방법으로는 3가지가 있다.
- File (text...)
- SharedPreferences (Key-Value)
- RoomDB (관계형 DB)
📌 SharedPreferences
안드로이드에서 간단하게 값을 저장하고 불러오는 방법이다.
기본적인 자료구조만 가능하기 때문에 하나의 Key에 다중 값을 저장하기는 어렵다!
Key-Value 형태로 값을 저장
Key는 String Type을 사용
Value는 기본적인 자료 구조만 가능 (Boolean, Long, String, Int, Double, Set (순서 없이 여러 개 담는))
❗하나의 Key에 다중값을 담을 순 없을까?
Set 자료형으로 저장 -> 순서가 구분되지 않는다.
String에 구분자로 저장 -> 구분자가 값에 들어가면 문제가 된다.
String으로 여러 데이터를 표현하는 데이터 포맷인 JSON 사용 ->
- Key-Value 형태로 해석 가능한 문자열 기반 포맷
- ex. {"name":"에릭", "age":23}
- 외부 라이브러리를 사용하여 변환 가능 ex) GSON
- 네트워크 통신에서 값을 주고받는데도 자주 사용된다.
http 통신에는 객체 개념이 없기 때문에 주로 문자열로 주고받아야 하는데
JSON 형태로 받으면 서버에서 바로 이해할 수 있다!
package com.example.dbproject
import android.content.Context
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import com.example.dbproject.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// packageName or 임의로 name 정해주고 모드 설정해줌
val sharedPrefs = getSharedPreferences("sharedprefs", Context.MODE_PRIVATE)
// sharedPrefs 객체를 가져오고 editor 를 가져온다.
val editor = sharedPrefs.edit()
// editor 로 값 수정 (key-value)
editor.putString("yejin", "android")
// 저장 다 했다는 의미로 apply
editor.apply()
// 가져오는 것 (""는 값이 없으면 나오는 것)
val spvalue = sharedPrefs.getString("yejin", "")
Log.d("SP", "${spvalue}")
}
}
android라는 값이 정상적으로 출력되는 것을 볼 수 있다.
📌 RoomDB
데이터베이스를 서버 대신 파일 형태로 저장하는 SQLite 기반
관계형 데이터베이스 구조
SQL문 사용 (자주 사용되는 Insert, Delete는 SQL문 작성 없이 가능)
- Database (데이터베이스)
저장하는 데이터의 집합 단위를 말합니다
- Entity (항목)
데이터베이스 내의 테이블을 의미합니다
- DAO (다오)
데이터베이스에 접근하는 함수(insert,update,delete,...)를 제공합니다
우선, RoomDB를 사용하기 위해 build.gradle 파일을 수정해준다.
AppDatabase, User, UserDao를 만들어주면 RoomDB 초기 세팅은 끝난다!
AppDatabase.kt
package com.example.dbproject
import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
// DB 와 객체를 넣는 과정
// 여러 클래스가 들어올 수 있으니 배열, 바뀔 수도 있으니 버전을 줌
@Database(entities = [User::class], version = 1)
abstract class AppDatabase: RoomDatabase() {
// 자동으로 Dao 값 채워줌
abstract fun userDao(): UserDao
// 싱글톤 패턴 (하나의 앱에서 사용될 때 DB 하나를 전역적으로 재활용)
companion object {
// database 가 담기는 객체
private var appDatabase: AppDatabase? = null
@Synchronized // 여러 스레드에서 하나의 자원에 접근하려고 할 때 그것을 방지
fun getInstance(context: Context): AppDatabase? {
if (appDatabase == null) { // null 일 때 초기화를 해줘야함
synchronized(AppDatabase::class.java){ // 이 클래스가 점유하고 있다는 뜻
appDatabase = Room.databaseBuilder(
context.applicationContext, // 전역적
AppDatabase::class.java,
"app-database", // 이름 다 다르게
).allowMainThreadQueries().build()
}
}
return appDatabase
}
}
}
User.kt
package com.example.dbproject
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
@Entity // RoomDB 에서 사용되는 객체라는 것을 알리기 위해
data class User (
@ColumnInfo(name = "name") val name: String,
@ColumnInfo(name = "age") val age: Int,
// 고유키 autoGenerate 자동으로 증가
@PrimaryKey(autoGenerate = true) @ColumnInfo(name = "userId") val userId: Int = 0
)
UserDao.kt
꼭 인터페이스로 설정!
package com.example.dbproject
import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.Query
@Dao
interface UserDao {
@Insert
fun insert(user: User)
@Delete
fun delete(user: User)
// 가져오는 것
@Query("SELECT * FROM User")
fun selectAll(): List<User>
@Query("SELECT * FROM User WHERE userId = :userId")
fun selectByUserId(userId: Int): User
@Query("SELECT * FROM User WHERE name = :name")
fun selectByUserName(name: String): List<User> // 동일 이름 있을 수 있어서
// 업데이트
@Query("UPDATE User SET name = :name WHERE userId = :userId")
fun updateNameByUserId(userId: Int, name: String)
}
DB CRUD 시작
데이터 생성 (Create)
val roomDb = AppDatabase.getInstance(this) // nullable 한 DB
if(roomDb != null) {
val user = User("예진", 22)
roomDb.userDao().insert(user) // insert 할 때마다 고유 id 자동으로 증가
val userList = roomDb.userDao().selectAll()
Log.d("DB", "User List : ${userList}")
}
데이터 수정 (Update)
val roomDb = AppDatabase.getInstance(this) // nullable 한 DB
if(roomDb != null) {
roomDb.userDao().updateNameByUserId(1, "예슬")
val userList = roomDb.userDao().selectAll()
Log.d("DB", "User List : ${userList}")
}
데이터 삭제 (Delete)
val roomDb = AppDatabase.getInstance(this) // nullable 한 DB
if(roomDb != null) {
val deletedUser = User("", 0, 1)
roomDb.userDao().delete(deletedUser)
val userList = roomDb.userDao().selectAll()
Log.d("DB", "User List : ${userList}")
}
데이터 아이디로 찾기 (Read)
앞에서 다 지워버려서 안드라는 user를 추가해주고 userId 2를 가진 유저를 찾아줬다.
val roomDb = AppDatabase.getInstance(this) // nullable 한 DB
if(roomDb != null) {
val user = roomDb.userDao().selectByUserId(2)
Log.d("DB", "User List : ${user}")
}
'🍞 Front-End > Android' 카테고리의 다른 글
[Android] Retrofit2 사용법 (0) | 2022.11.27 |
---|---|
[Android] Progress 타이머 (0) | 2022.11.08 |
[Android] 앱 권한 요청 API level 오류 (0) | 2022.11.02 |
[Android] 계산기 RoomDB (0) | 2022.10.31 |
[Android] 에뮬레이터에서 Toast 메세지가 안 보일 때 (0) | 2022.10.31 |