안드로이드 내부 데이터베이스를 공부하던 중 알게된 SQLite
하지만 SQLite를 사용하면 crud 부분을 직접 쿼리문으로 작성해야하고, 이 과정은 개발자로 하여금 편의성을 떨어트린다.
그래서 나오게 된 Room 라이브러리
사실 예전부터 공부해야겠다고 느꼈으나, 서버통신하는 부분부터 익히고나서 배우자는 생각으로 등한시했던 것 같다.
오늘은 Room 데이터베이스를 얕게나마 공부하며, 정리한 부분을 적어보고자 한다.
(※ 룸을 사용하기 위해선 Room 라이브러리 latest_version을 dependency에 추가하면 되며, 룸과 코루틴을 같이 사용시 의존성을 주입해야한다.)
먼저, Room 데이터베이스을 사용하기 위해선 Entity, DAO, Database 를 정의해주어야한다.
개인적으로 느낀 바로, Entity는 DB로 치면 테이블 역할을 한다고 느꼈다.
-Entity 예시 코드-
@Entity(tableName = "User") data class MyEntity ( @PrimaryKey(autoGenerate = true) var id : Int = 0 @ColumnInfo(name = "user_name") var userName : String @Ignore var userJob : String )
예시 코드처럼 class 상단에 @Entity 어노테이션을 붙여줌으로써, "이 클래스를 테이블로 쓸거야~" 라고 간단하게 알려줄 수 있다.
Entity에 테이블명을 정의해줄 수 있는데, 만약 따로 정의하지 않는다면 클래스명을 테이블명으로 사용하게 된다.
@PrimaryKey 는 DB의 기준키와 같은 역할을 하고,
autoGenerate = true 로 함으로써, Entity의 형식에 맞는 데이터가 추가되면 값이 1씩 자동으로 증가한다.
@ColumnInfo 를 통해 DB에 열 이름을 따로 부여할 수 있다.
사용하고 싶지 않는 필드가 있을 경우, @Ignore 를 통해 해당 필드를 무시할 수 있다.
(물론 더 많은 어노테이션과 기능들이 있으나, 내가 지금 배우고 이해가 가는 것은 이 정도 까지이다.)
Dao에선 앱 데이터베이스의 데이터와 상호작용하는 메서드를 구현하게 된다.
-Dao 예시 코드-
@Dao interface MyDao { // 각각 crud의 역할중, @Insert // create fun insertAll(vararg users: User) @Query("SELECT * FROM user") // read fun getAll(): List<User> @Update // update fun updateUsers(vararg users: User) @Delete // delete fun delete(user: User) // 를 담당한다. }
@Insert 를 통해, 데이터베이스의 테이블에 '매개변수를 삽입'하는 메서드를 만들 수 있다.
(즉, 해당 메소드를 호출을 하여 entity의 형식에 맞는 인스턴스를 매개변수로 받아와서 DB에 데이터로 추가하게 된다!)
@Query 를 통해, Entity의 '조회', '삭제' 등을 할 수 있다.
(예시코드에선 "user 테이블의 내용 전부(*)를 조회하겠다." 라고 해석할 수 있다.)
@Update 를 통해, DB 테이블에 '특정 행을 업데이트'하는 메서드를 정의할 수 있다.
@Delete 를 통해, DB 테이블에 '특정 행을 삭제'하는 메서드를 정의할 수 있다.
지금까지 만들어놓은 테이블, 메서드를 기반으로 실질적으로 사용하게될 내부 데이터베이스를 만드는 과정이라고 보면 된다.
먼저 예시 코드를 보자.
-Database 예시 코드-
@Database(entities = [MyEntity::class], version = 1) abstract class MyDatabase : RoomDatabase() { // Dao 또한 추상 메서드로 호출한다. abstract fun myDao() : MyDao // 싱글톤 패턴으로 Database 생성을 위한 instance를 만든다. companion object { private var instance : MyDatabase? = null @Synchronized fun getInstance(context: Context) : MyDatabase? { if(instance == null) { synchronized(MyDatabase::class) { instance = Room.databaseBuilder( context.applicationContext, MyDatabase::class.java, "my_database" ).build() } } return instance } } }
@Database() 어노테이션을 통해 데이터베이스 생성용으로 만들 추상클래스임을 알려주고, (entities = [내 Entitiy명::class],version = 버젼명)을 정의한다.
@Synchronized 는 instance 객체가 여러 곳에서 호출될 경우 동시에 호출되는 것을 방지하고, 순차적으로 호출되게 된다.
(자세히 말하자면 동시에 호출될 시, 내부 로직이 꼬이는 것을 방지하기 위해 사용하는 것이다!)
instance == null 이라면, Room.databaseBuilder(빌더 패턴)을 통해 Database 를 만들게 된다.
지금까지 Room에 대해 공부한 것을 정리해보았다.
아직 부족한 것이나 혹시나 잘못(?)되었을 지식을 정리하기 위해, 앞으로 만들 프로젝트에는 Room을 적용시켜서 실질적인 사용법을 익혀나가야겠다!