iyOmSd/Title: Swift

[Swift] Realm DB

냄수 2020. 9. 17. 13:01
반응형

iOS는 많은 데이터베이스들이 있어요

 

Realm SQLite FMDB CoreData

이 중에서 어떤 것을 골라서 써야 하나 생각하게 되죠

 

이 게시글은 Realm에 대해 초점을 더 두고 다른 것들은 간략하게 언급해볼게요!!

 

SQLite

기본내장 프레임워크라 따로 설치가 필요가 없어요

그렇기 때문에 DB의 많은 부분을 접근하고 조작할 수 있어요

여러 프로세스와 스레드로부터 안전해요

 

FMDB

SQLite는 Objective-C로 구성되어있는데 이를 wrapping 해서 Swift에 맞게 사용할 수 있어요

 

CoreData

데이터베이스가 아니에요!

SQLite를 저장소로 쓰지만 프레임워크 자체는 데이터베이스가 아니에요

객체 그래프를 관리하기 위한 프레임워크라고 할 수 있겠네요

따라서 객체에 중점을 두고있어요

SQLite보다 더 많은 메모리를 사용하고 더 많은 저장 공간을 사용해요

하지만 SQLite보다 빠르게 동작해요

 

 

Realm

우선 Realm은 NoSQL이에요

 

NoSQL이란..?

Not Only SQL의 약자로 데이터베이스 관리시스템을 지칭하는 단어라고 해요

관계형 DB를 사용하지 않는다의 의미가 아니라 여러 유형의 DB를 사용하는 것이에요

데이터를 저장하는데 SQL 외에 다른 방법도 있다는 거예요

 

 

객체 중심 데이터베이스예요

ORM(Object Relational Mapping)이 아니에요

 

ORM이란..?

객체와 관계와의 설정을 의미해요

객체 지향 프로그래밍은 클래스를 사용하고 관계형 데이터 베이스는 테이블을 사용하는데

객체 모델과 관계형 모델이 같을 수없겠죠??

이 객체 간의 관계를 바탕으로 SQL을 생성해줘서 불일치를 해결해 준다고 하네요

Object <- Mapping -> DB

ORM이름에서 알 수 있듯이 Mapping을 해주는 역할이에요

 

iOS와 Android 간 DB 공유가 가능해요

 

몇 줄의 코드로 모든 작업을 처리할 수 있어요

 

메인 스레드에서 읽기/쓰기를 할 수 있어요

 

객체를 직접 디스크에 유지해요

 

모바일에 최적화된 데이터베이스로

Realm SQLite FMDB CoreData

중에서 제일 성능이 좋아요

 

단점으로는

메인 스레드를 사용해서 다른 스레드 접근 시 에러가나요

바이너리 용량이 커지구요

 

간단하고 성능이 중요하지 않다면 SQLite나 FMDB같이 편한 DB를 사용하는 게 알맞고

그때그때 상황과 앱의 성능을 생각하면서 정하면 될 것 같아요

 

 

 

사용법

간단하게 사용하는 방법을 알아보려고 해요

realm.io/docs/swift/latest/#installation

 

Realm: Create reactive mobile apps in a fraction of the time

Realm Swift is the first database built for mobile. An alternative to SQLite and Core Data that's fast, easy to use, and open source.

realm.io

여기에 설치와 사용법이 작성되어있어서 더 자세히 보고 싶으시면 들어가서 보세요!!

 

라이브러리를 받아야하니

 

pod 'RealmSwift'

를 해주고 install 부터 해야겟죠??

 

Realm파일은 Documents가 기본경로로 설정되서 생성되요

 

우선 API문서는

realm.io/docs/swift/latest/api/

여기에 있구요

 

    func createRealmFile() {
        let realm = try! Realm()
        print(realm.configuration.fileURL)
        let path = realm.configuration.fileURL?.deletingLastPathComponent().path
        print(path)
    }

처음에 db파일을 만들듯 realm 파일을 만들어줘야겠죠??

 

경로를 보면

차이가 느껴지시죠?

앞에 file:// 형식이 사라지고 뒤에 default.realm파일명이 사라졌어요

기본으로는 default.realm이라는 파일이 생기나보네요 ㅎㅎ

 

이름을 우리가 원하는 파일로 만들고 싶잖아요??

문서에 잘 나와 잇네요!!

    func setDefaultRealmForUser(fileName: String) {
        var config = Realm.Configuration()

        // Use the default directory, but replace the filename with the username
        config.fileURL = config.fileURL!.deletingLastPathComponent().appendingPathComponent("\(fileName).realm")

        // Set this as the configuration used for the default Realm
        Realm.Configuration.defaultConfiguration = config
    }

클래스 메서드를 이용해서 설정을 해주면 파일 이름을 변경할 수 있어요

 

값이 잘 들어갔는지 있는지 확인을 하려면

realm.io/kr/products/realm-studio/

 

Realm Studio: open, edit, and manage your Realm data

Download our cross-platform developer tool for the Realm Database and Realm Platform. Available for Mac, Windows, and Linux.

realm.io

을 이용해서 확인할 수 있어요

 

Open Realm file을 누르고

파일 경로로 나온 위치를 따라가면 저기에 제가만든 .realm파일이 2개가 보이네요!!

클릭해보면

....

지원안한데요...

하하ㅏ....

나중에되면 해봐야겟네요...

 

 

 

이제 객체를 만들어볼게요

class Animal: Object {
    @objc dynamic var name: String = ""
    @objc dynamic var age: Int = 0
}

Object를 상속시켜주세요 이타입이 Realm에 쓸 객체에요

Realm 모델 속성은 dynamic var 선언이 필요하구요

하지만

List, RealmOptional 같은속성들은 동적으로 정의 할 수 없으므로 이런 타입들은

let으로 사용하여 선언해야한데요!!

 

간단한 코드를 보면서 이해해볼게요

class ViewController: UIViewController {

    var realm: Realm!
    override func viewDidLoad() {
        super.viewDidLoad()
        createRealmFile()
        
        let dog = add(name: "dog", age: 1)
        let cat = add(name: "cat", age: 5)
        print(dog)
        print(cat)
        
        
        dog.age = 10 // err
        try! realm.write {
            dog.age = 10
        }
        
        let myDog = realm.objects(Animal.self).filter("name == 'dog'").first
        let testDog = realm.objects(Animal.self).filter("name == 'dog'").first
        
        // MARK: TEST1
        print("dog")
        print(dog)
        print("myDog")
        print(myDog)
        
        try! realm.write {
            myDog?.age = 3
        }
        // MARK: TEST2
        print("myDog")
        print(myDog)
        print("testDog")
        print(testDog)
    }
        
    func add(name: String, age: Int) -> Animal {
        let animal = Animal()
        animal.name = name
        animal.age = age
        
        try! realm.write {
            realm.add(animal)
        }
        
        return animal
    }
}

 

추가

try! realm.write {
    realm.add(animal)
}

기본적으로 Realm().add(_:update:)를 이용해서

객체를 업데이트/추가 기능을 할수 있어요

하지만 추가작업이나 수정작업을 할때는 realm.write{ ... } 블럭안에서 진행해야해요

밖에서 작업한다면 에러가 날거에요

 

수정

try! realm.write {
    myDog?.age = 3
}

 

TEST1는 저장한 Animal객체와 Realm에서 가져온 객체가

수정이 일어났을때 값을 비교하는거에요

저장한 Animal객체를 반환받고 그 객체를 수정했어요

TEST1은 보통 객체를 수정한 결과를 나타내죠

Realm객체가 아니라 보통 쓰는 객체를 수정했기 때문에 영향이 없어요

Realm에 있는 객체의 값에는 영향을 주지 않아요

 

TEST2

Realm에 있는 Animal객체를 두 번꺼내와서

그중 하나의 객체만 수정한거에요

TEST2는 Realm의 객체를 가져와서 수정했고 그 객체를 수정하면

다른 객체의 값도 변해있는걸 알 수 있어요

객체가 자동으로 업데이트돼서

Realm객체의 속성을 고치면 그 객체를 참조하는 객체에도 반영돼요

 

삭제

try! realm.write {
    realm.delete(myDog!)
}

삭제를 하면 유효하지않은 객체라고 뜨네요 

혹은 deleteAll()을 통해서 전체삭제도 가능해요

 

 

접근

let dog = realm.objects(Animal.self).filter("name == 'dog'").first

realm.objects에 타입을 넣어줘서 해당 타입에해당하는 객체를 모두불러올수있고

filter를통해서 원하는 값을 필터링 할 수 있어요

sort도 .sorted(byKeyPath:), sorted(byProperty:)을 이용해서

정렬할 수 있어요 하지만 정렬 기준으로 여러속성을 지원하지 않기 때문에

sorted(by:)를 사용해서 여러속성을 이용해서 정렬할 수 있어요

 

혹은 문서에 써있는 예제처럼

let predicate = NSPredicate(format: "color = %@ AND name BEGINSWITH %@", "tan", "B")
tanDogs = realm.objects(Dog.self).filter(predicate)

쿼리문을 이용해서 가져올 수 도있어요

 

 

Notification

Realm이 변경됬을때 알림도 줄수 있어요

꼭 해제도 해줘야해요

let notiToken = realm.observe { notification, realm in
    switch notification {
    case .didChange
    case .refreshRequired
    }
}

notiToken.invalidate()

보통 추가, 수정, 삭제될때 didChange 이벤트가 발생해서 그에맞는 처리를 해주면 돼요

 

 

그 외..

 

클래스 메서드 primarykey()를 재정의 해서

기본키를 지정할 수 있어요

 

클래스 메서드  ignoredProperties()를 재정의해서 

Realm에 저장되지 않는 속성을 지정할 수 있어요

 

 

사용법이 엄청 간단해서 편한 것 같아요

반응형