[Android] Local Database(SQLite, Room)
- -
๐ค SQLite?
์ฑ์ ๋ฐ์ดํฐ๋ฅผ ํจ์จ์ ์ผ๋ก ๊ด๋ฆฌํ๊ธฐ ์ํ ์ ์ฅ์ (๋ก์ปฌ ๋ฐ์ดํฐ๋ฒ ์ด์ค)
์๊ท๋ชจ ๋ฐ์ดํฐ๋ฅผ ๊ด๋ฆฌํ๊ณ ์ฌ์ฉํ๋๋ฐ ์ ํฉํ ๊ด๊ณํ ๋ฐ์ดํฐ ๋ฒ ์ด์ค๋ก, RDBํ์(์ก์ ํํ, ํ๊ณผ ์ด ) ๋ก ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๋ค.
์๋๊ฐ ๋น ๋ฅด๊ณ ๊ฐ๋ณ๋ค๋ ์ฅ์
์ด์ ํ๋ก์ ํธ์์ SQLite๋ฅผ ์ฌ์ฉํ์ฌ ํ๋ก์ ํธ๋ฅผ ์งํํด์์ต๋๋ค.
ํ์ง๋ง ์๋์ ๊ฐ์ ์ด์ ๋ก ์ธํด SQLite ๋ณด๋ค Jetpack ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ํฌํจ๋ Room์ ์ฌ์ฉ์ ๊ถ์ฅํ๊ณ ์์ต๋๋ค.
๊ตฌ๊ธ์์๋ ์ด๋ฌํ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ณ ์ ์๋กญ๊ฒ Room Database Library๋ฅผ ๋ฐฐํฌํ์์ต๋๋ค.
๐ฎ Room?
SQLite ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ์ฝ๊ณ ํธ๋ฆฌํ๊ฒ ์ฌ์ฉํ ์ ์๋๋ก ํ๋ ORM ๋ผ์ด๋ธ๋ฌ๋ฆฌ
ORM์ ๋ ๋ญ์ผ? (Object-Relational Mapping)
- ORM์ด๋, Object Relational Mapping, ๊ฐ์ฒด-๊ด๊ณ ๋งคํ์ ์ค์๋ง์
๋๋ค.
๊ฐ์ฒด ์งํฅ ํ๋ก๊ทธ๋๋ฐ(Object Oriented Programming, OOP)์ ํด๋์ค๋ฅผ ์ฌ์ฉํ๊ณ , ๊ด๊ณํ ๋ฐ์ดํฐ๋ฒ ์ด์ค(Relational DataBase, RDB)๋ ํ ์ด๋ธ์ ์ฌ์ฉํฉ๋๋ค. ์ด๋ฌํ ๊ฐ์ฒด ๋ชจ๋ธ๊ณผ ๊ด๊ณํ ๋ชจ๋ธ ๊ฐ์ ๋ถ์ผ์น๊ฐ ์กด์ฌํ๊ฒ ๋๋๋ฐ, ORM์ ํตํด ๊ฐ์ฒด ๊ฐ์ ๊ด๊ณ๋ฅผ ๋ฐํ์ผ๋ก SQL๋ฌธ์ ์๋์ผ๋ก ์์ฑํ์ฌ ๋ถ์ผ์น๋ฅผ ํด๊ฒฐํ ์ ์์ต๋๋ค. - ORM์ ์ด์ฉํ๋ฉด SQL Query๊ฐ ์๋ ์ง๊ด์ ์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ์กฐ์ํ ์ ์์ต๋๋ค.
์๋ฅผ๋ค์ด, Member ํ ์ด๋ธ์ ๋ฐ์ดํฐ๋ฅผ ์ถ๋ ฅํ๊ธฐ ์ํด์ MySQL์์๋ SELECT * FROM Member; ๋ผ๋ query๋ฅผ ์คํํด์ผ ํ์ง๋ง,
ORM์ ์ฌ์ฉํ๋ฉด Member ํ ์ด๋ธ๊ณผ ๋งคํ๋ ๊ฐ์ฒด๋ฅผ member๋ผ ํ ๋, member.findAll(); ๋ผ๋ ๋ฉ์๋ ํธ์ถ๋ก ๋ฐ์ดํฐ ์กฐํ๊ฐ ๊ฐ๋ฅํฉ๋๋ค.
๐๐ป SQLite๋ณด๋ค Room ์ฌ์ฉ์ด ๊ถ์ฅ๋๋ ์ด์
- ์ถ์ํ์ ORM (Object-Relational Mapping):
- Room์ ์ฌ์ฉํ๋ฉด ๋ฐ์ดํฐ๋ฒ ์ด์ค ์คํค๋ง๋ฅผ ์ ์ํ๋ ํด๋์ค๋ฅผ ์์ฑํ๊ณ , ํด๋น ํด๋์ค๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๋ฐ์ดํฐ๋ฒ ์ด์ค ์์ ์ ์ํํ ์ ์์ต๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด ๋ฐ์ดํฐ๋ฒ ์ด์ค ์์ ์ ์ถ์ํํ์ฌ ๊ฐ๋ฐ์๊ฐ ๋ ์ฝ๊ฒ ์ฝ๋๋ฅผ ์ ์ง ๊ด๋ฆฌํ ์ ์์ต๋๋ค.
- ์ปดํ์ผ ํ์ ๊ฒ์ฌ:
- Room์ ์ปดํ์ผ ํ์์ SQL ์ฟผ๋ฆฌ๋ฅผ ๊ฒ์ฌํ์ฌ ์ค๋ฅ๋ฅผ ๋นจ๋ฆฌ ๋ฐ๊ฒฌํ ์ ์๋๋ก ๋์์ค๋๋ค. ์ด๊ฒ์ ๋ฐํ์ ์ค๋ฅ๋ฅผ ๋ฐฉ์งํ๊ณ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์์ ์ ์์ ํ๊ฒ ์ํํ ์ ์๋๋ก ํฉ๋๋ค.
- LiveData ๋ฐ ViewModel ์ง์:
- Room์ Android์ ์ํคํ ์ฒ ์ปดํฌ๋ํธ ์ค ํ๋์ธ LiveData์ ํจ๊ป ์ฌ์ฉํ๊ธฐ์ ์ด์์ ์ ๋๋ค. LiveData๋ฅผ ์ฌ์ฉํ๋ฉด ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ๋ฐ์ํ๋ ๋ณ๊ฒฝ ์ฌํญ์ ๊ด์ฐฐํ๊ณ , UI๋ฅผ ์๋์ผ๋ก ์ ๋ฐ์ดํธํ ์ ์์ต๋๋ค. ์ด๋ก์จ ํ๋ฉด ๊ฐฑ์ ์ด ๊ฐํธํด์ง๋๋ค.
- ๋ํ Room์ ViewModel๊ณผ ํจ๊ป ์ฌ์ฉํ๊ธฐ ์ฝ์ต๋๋ค. ์ด๊ฒ์ ๋ฐ์ดํฐ์ ์์กด ์ฃผ๊ธฐ๋ฅผ ๊ด๋ฆฌํ๊ณ , ํ๋ฉด ํ์ ๊ณผ ๊ฐ์ ๊ตฌ์ฑ ๋ณ๊ฒฝ ์ ๋ฐ์ดํฐ ์์ค์ ๋ฐฉ์งํฉ๋๋ค.
- ์ ์ง ๊ด๋ฆฌ ๋ฐ ํ์ฅ์ฑ:
- Room์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์คํค๋ง์ ๋ฒ์ ์ ๊ทธ๋ ์ด๋ ๋ฐ ๋ง์ด๊ทธ๋ ์ด์ ์ ์ฝ๊ฒ ์ฒ๋ฆฌํ ์ ์๋ ๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค. ์ฑ์ด ์ ๋ฐ์ดํธ๋๊ฑฐ๋ ๋ณ๊ฒฝ๋ ๋, ๋ฐ์ดํฐ๋ฒ ์ด์ค ์คํค๋ง๋ฅผ ์ฝ๊ฒ ์กฐ์ ํ๊ณ ๊ด๋ฆฌํ ์ ์์ต๋๋ค.
- ํธ๋ฆฌํ ์ฟผ๋ฆฌ ๋น๋:
- Room์ SQLite ์ฟผ๋ฆฌ๋ฅผ ๋ ์ฝ๊ฒ ์์ฑํ ์ ์๋๋ก ํธ๋ฆฌํ ์ฟผ๋ฆฌ ๋น๋๋ฅผ ์ ๊ณตํฉ๋๋ค. ์ด๋ฅผ ํตํด ๋ณต์กํ ์ฟผ๋ฆฌ๋ฅผ ๋ ์ง๊ด์ ์ผ๋ก ์์ฑํ ์ ์์ต๋๋ค.
๐๐ป Room ๊ตฌ์ฑ ์์
์ํฐํฐ(Entity), ๋ฐ์ดํฐ ์ ๊ทผ ๊ฐ์ฒด(DAO), ๋ฃธ ๋ฐ์ดํฐ๋ฒ ์ด์ค(Room Database) ์ด ์ธ ๊ฐ์ ๊ตฌ์ฑ ์์๋ฅผ ํตํด Room ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ๊ตฌ์ฑ๋ฉ๋๋ค.
- ๋ฃธ ๋ฐ์ดํฐ๋ฒ ์ด์ค
๋ฐ์ดํฐ๋ฒ ์ด์ค๋ ์ฑ์ ์ ์ฅ๋์ด ์๋ ๋ก์ปฌ ๋ฐ์ดํฐ์ ๋ํ ์ก์ธ์ค ํฌ์ธํธ๋ฅผ ์ ๊ณตํด์ฃผ๋ ์ญํ
- ๋ฐ์ดํฐ ์ ๊ทผ ๊ฐ์ฒด(Data Access Objects)
DAO๋ ์ฑ์์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋ฐ์ดํฐ๋ฅผ ์ถ๊ฐ, ์ญ์ , ์ ๋ฐ์ดํธ ์์ ์ ํ ์ ์๋ ๋ฉ์๋๋ฅผ ์ ๊ณตํด์ฃผ๋ ์ญํ
๊ทธ ์ธ์๋ ๋ค์ํ ์ฟผ๋ฆฌ ์ฌ์ฉ ๊ฐ๋ฅ
- ์ํฐํฐ
๋ฐ์ดํฐ๋ฒ ์ด์ค ๋ด์ ์กด์ฌํ๋ ํ ์ด๋ธ
๐ค๐ป๐ค๐ป SQLite vs Room ๋น๊ต
- SQLite ์ฌ์ฉ
public class DBHelper extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "MyMemoDB";
private static final int DATABASE_VERSION = 1;
private static final String TABLE_MEMOS = "memos";
private static final String COLUMN_ID = "id";
private static final String COLUMN_CONTENT = "content";
public DBHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
String CREATE_MEMOS_TABLE = "CREATE TABLE " + TABLE_MEMOS + "("
+ COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
+ COLUMN_CONTENT + " TEXT)";
db.execSQL(CREATE_MEMOS_TABLE);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (oldVersion < newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + TABLE_MEMOS);
onCreate(db);
}
}
public void addMemo(String content) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(COLUMN_CONTENT, content);
db.insert(TABLE_MEMOS, null, values);
db.close();
}
public List<String> getAllMemos() {
List<String> memoList = new ArrayList<>();
String selectQuery = "SELECT * FROM " + TABLE_MEMOS;
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);
if (cursor.moveToFirst()) {
do {
String content = cursor.getString(cursor.getColumnIndex(COLUMN_CONTENT));
memoList.add(content);
} while (cursor.moveToNext());
}
cursor.close();
db.close();
return memoList;
}
}
- DBHelper ํด๋์ค๋ฅผ ์ ์ํฉ๋๋ค.
์ด ํด๋์ค๋ SQLiteOpenHelper๋ฅผ ํ์ฅํ๋ฉฐ, ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ์์ฑํ๊ณ ๋ฒ์ ๊ด๋ฆฌ๋ฅผ ํฉ๋๋ค.
- onCreate ๋ฉ์๋์์๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์คํค๋ง๋ฅผ ์ ์ํ๊ณ ํ
์ด๋ธ์ ์์ฑํฉ๋๋ค.
์ด ์์ ์์๋ "memos"๋ผ๋ ํ ์ด๋ธ์ ์์ฑํฉ๋๋ค.
- onUpgrade ๋ฉ์๋์์๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์คํค๋ง์ ์
๊ทธ๋ ์ด๋๋ฅผ ์ฒ๋ฆฌํฉ๋๋ค.
์ด ๊ฒฝ์ฐ, ์ด์ ๋ฒ์ ๊ณผ ํ์ฌ ๋ฒ์ ์ ๋น๊ตํ์ฌ ํ ์ด๋ธ์ ์ญ์ ํ๊ณ ๋ค์ ์์ฑํฉ๋๋ค.
- addMemo ๋ฉ์๋๋ ์๋ก์ด ๋ฉ๋ชจ๋ฅผ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ถ๊ฐํฉ๋๋ค.
์ด ๋ฉ์๋๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ์ด๊ณ ContentValues๋ฅผ ์ฌ์ฉํ์ฌ ๋ฐ์ดํฐ๋ฅผ ์ฝ์ ํฉ๋๋ค.
- getAllMemos ๋ฉ์๋๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ๋ชจ๋ ๋ฉ๋ชจ๋ฅผ ๊ฐ์ ธ์ต๋๋ค.
SQL ์ฟผ๋ฆฌ๋ฅผ ์ํํ์ฌ ๊ฒฐ๊ณผ๋ฅผ ๊ฐ์ ธ์จ ํ, ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋ฐ ์ปค์๋ฅผ ๋ซ๊ณ ๋ฉ๋ชจ ๋ชฉ๋ก์ ๋ฐํํฉ๋๋ค.
- Room ์ฌ์ฉ
@Entity(tableName = "memos")
public class Memo {
@PrimaryKey(autoGenerate = true)
public int id;
@ColumnInfo(name = "content")
public String content;
}
@Dao
public interface MemoDao {
@Insert
void insert(Memo memo);
@Query("SELECT * FROM memos")
List<Memo> getAllMemos();
}
@Database(entities = {Memo.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {
public abstract MemoDao memoDao();
}
- Memo ํด๋์ค๋ ์ํฐํฐ๋ฅผ ์ ์ํฉ๋๋ค.
์ํฐํฐ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค ํ ์ด๋ธ๊ณผ ๋งคํ๋ฉ๋๋ค.
์ด ํด๋์ค์์๋ id (๊ธฐ๋ณธ ํค)์ content ํ๋๋ฅผ ๊ฐ์ง๊ณ ์์ต๋๋ค.
- MemoDao ์ธํฐํ์ด์ค๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์์
์ ์ ์ํฉ๋๋ค.
@Insert ์ด๋ ธํ ์ด์ ์ ์ฌ์ฉํ์ฌ ๋ฉ๋ชจ ์ฝ์ ๋ฉ์๋๋ฅผ ์ ์ธํ๊ณ ,@Query ์ด๋ ธํ ์ด์ ์ ์ฌ์ฉํ์ฌ ๋ชจ๋ ๋ฉ๋ชจ๋ฅผ ๊ฐ์ ธ์ค๋ ๋ฉ์๋๋ฅผ ์ ์ํฉ๋๋ค.
- AppDatabase ํด๋์ค๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ์ ์ํฉ๋๋ค.
@Database ์ด๋ ธํ ์ด์ ์ ์ฌ์ฉํ์ฌ ์ํฐํฐ ๋ฐ ๋ฒ์ ์ ์ง์ ํฉ๋๋ค.
์ด ํด๋์ค๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ธ์คํด์ค๋ฅผ ๋ฐํํ๋ memoDao() ๋ฉ์๋๋ฅผ ์ ๊ณตํฉ๋๋ค.
'android studio' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[android] setValue() , postValue() (1) | 2023.08.09 |
---|---|
[android] Handler & Looper (0) | 2023.07.24 |
[android] android service? (0) | 2023.07.21 |
[android] ViewBinding vs DataBinding ? (0) | 2023.07.12 |
[android] ViewModel๋? (0) | 2023.07.09 |
์์คํ ๊ณต๊ฐ ๊ฐ์ฌํฉ๋๋ค