티스토리 뷰

OpenSource/Realm

Realm

malrang-malrang 2022. 7. 19. 23:36

Realm

  • Realm: 대용량 DB
    • 버전 호환성
      • iOS 8 이상
      • Xcode 7.3 이상
      • Xcode 14 이상 사용시 ios 11이상
    • 장점:
      • SQLite와 CoreData보다 작업 속도가 빠르다.
      • Realm Studio를 통해서 DB 상태를 편하게 확인할 수 있다.
      • 직관적인 코드로 작업할 수 있다.
      • Rx를 지원하는 RxRealm이 존재한다.
      • 높은 용량을 요구하고 보통 대용량 데이터를 다룰 때 사용한다고 한다.
    • 단점:
      • 바이너리 용량이 늘어남
      • main thread 이용하고 있는데 다른 thread 접근하면 에러남. 그래서 사용할 때 스레드 지정해줘야 함
      • 다양한 쿼리를 지원하지 않음
      • iOS8부터 지원가능

Realm이란??

Realm은 모바일에 특화된 NoSQL 데이터 베이스로 Swift, Objective-C, java 등 다양한 SDK를 제공하는 라이브러리다.

iOS에서 Realm을 사용할 경우 UserDefaults와 CoreData를 대체하여 Persistent Data를 저장하고 관리 할 수 있다.

대표적인 특징으로 ORM이 아닌 데이터 컨테이너 모델을 사용하며 데이터 객체를 Realm에 객체 형태로 저장한다.
그렇기 때문에 DB에서 가져온 데이터를 복잡한 가공과정 없이 바로 사용할수 있는 장점이 있다.

Realm 을 사용해보자!

1. 설치

Realm을 Swift 프로젝트에 설치할 때 SPM, CocoaPods, Carthage 를 사용해 설치할수 있다.

SPM 설치 방법
프로젝트 파일을 연후 좌측 상단의 file -> Add PAckages 클릭

우측상단의 Search Bar 에 Realm 깃헙 URL을 입력해준다.
https://github.com/realm/realm-cocoa.git

입력하면 Realm의 라이브러리 들이 나오는데 원하는걸 추가해주면된다.

2. 모델정의

Realm에 저장할 데이터 객체를 정의할 때는 일반적인 모델을 정의 하는것과 같이 class를 만들고 필요한 property를 정의하면 된다.

Realm에서 사용할 수 있는 형태로 만들기 위해 Object를 상속해야 하며
Property를 정의 할때 앞에 @Persisted키워드를 붙여준다.

final class RealmTodo: Object {
    @Persisted var todoListItemStatus: String
    @Persisted var identifier: UUID
    @Persisted var title: String
    @Persisted var body: String
    @Persisted var date: Date

    convenience init(
        todoListItemStatus: TodoListItemStatus,
        identifier: UUID,
        title: String,
        body: String,
        date: Date
    ) {
        self.init()
        self.todoListItemStatus = todoListItemStatus.displayName
        self.identifier = identifier
        self.title = title
        self.body = body
        self.date = date
    }
}

CRUD

Realm 데이터 베이스를 관리해줄 타입을 하나만든뒤 내부에 CRUD를 구현해주었다.

먼저 Realm데이터 베이스에 접근하고, 원하는 작업을 하기위해 아래와 같은 프로퍼티를 생성한다.

let realm = try? Realm()

이녀석을 사용해 local default Realm 객체를 열어 사용해주면 된다.

Create

func create(todoData: Todo) {
        try? realm?.write {
            realm?.add(todoData.convertRealmTodo())
        }
    }

파라미터로 받은 값을 위에 생성했던 realm 프로퍼티에 추가하는 작업이다.

Read

func read() -> [Todo] {
        var todoArray: [Todo] = []
        realm?.objects(RealmTodo.self).forEach { todoArray.append($0.convertTodo()) }

        return todoArray
    }

Realm에 저장된 데이터를 모두 가져와 타입을 변환한후 반환하도록 해주었다.

Update

func update(selectedTodo: Todo) {
        let item = realm?.objects(RealmTodo.self)
            .filter({ $0.identifier == selectedTodo.identifier })
            .first

        if item != nil {
            try? realm?.write({
                item?.todoListItemStatus = selectedTodo.todoListItemStatus.displayName
                item?.identifier = selectedTodo.identifier
                item?.title = selectedTodo.title
                item?.body = selectedTodo.description
                item?.date = selectedTodo.date
            })
        }
    }

파라미터로 받은값과 Realm에 저장된 데이터중 identifier가 일치하는 데이터를 찾아 값을 수정해주었다.

Delete

func delete(todoID: UUID) {
        guard let item = realm?.objects(RealmTodo.self).filter({ $0.identifier == todoID }).first else {
            return
        }

        try? realm?.write({
            realm?.delete(item)
        })
    }

Update와 유사하게 identifier를 파라미터로 받아 Realm에 저장된 데이터중 identifier가 일치하는 데이터를 찾아 제거 해주었다.

Write Transactions

위의 CRUD예시 코드에서 add, delete 같은 메서드를 realm?.write 블럭 내부에서 사용한것을 볼수 있다.

Realm은 read-write operation으로 이루어진 transaction으로 관리한다.

생성, 수정, 삭제 동작을 하기 위해서는 write transacti block 내부에서 행해져야 한다.
Realm을 오픈해서 생성, 수정, 삭제 를 하게 되는것이다.
read 는 write블럭 내부가 아니어도 된다!

Transaction은 동시에 하나만 열릴 수 있고, 열려있는 transaction이 complete되기 전까지 Realm은 다른 write을 block 한다.

Transaction이 완료된 경우, Realm은 Commit을 하고 디스크에 데이터를 쓰거나, cancel하고 error를 방출한다.

import RealmSwift

final class RealmDatabase {
    private var realm: Realm?

    init() {
        self.realm = try? Realm()
    }

    func create(todoData: Todo) {
        try? realm?.write {
            realm?.add(todoData.convertRealmTodo())
        }
    }

    func read() -> [Todo] {
        var todoArray: [Todo] = []
        realm?.objects(RealmTodo.self).forEach { todoArray.append($0.convertTodo()) }

        return todoArray
    }

    func update(selectedTodo: Todo) {
        let item = realm?.objects(RealmTodo.self)
            .filter({ $0.identifier == selectedTodo.identifier })
            .first

        if item != nil {
            try? realm?.write({
                item?.todoListItemStatus = selectedTodo.todoListItemStatus.displayName
                item?.identifier = selectedTodo.identifier
                item?.title = selectedTodo.title
                item?.body = selectedTodo.description
                item?.date = selectedTodo.date
            })
        }
    }

    func delete(todoID: UUID) {
        guard let item = realm?.objects(RealmTodo.self).filter({ $0.identifier == todoID }).first else {
            return
        }

        try? realm?.write({
            realm?.delete(item)
        })
    }
}

참고한 문서및 자료

https://www.mongodb.com/docs/realm/sdk/swift/quick-start/
https://velog.io/@dlskawns96/Swift-Realm%EC%9D%98-%ED%8A%B9%EC%A7%95%EA%B3%BC-%EC%82%AC%EC%9A%A9%EB%B2%95

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/07   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31
글 보관함