[iOS] Realm이란? + migration에 대해

CastleSilver·2023년 4월 15일
0

iOS 공부

목록 보기
11/13

Realm은 MongoDB에서 만든 객체지향 모바일 앱 database입니다. ORM과 DAO(Data Access Object, 데이터베이스의 data에 접근하기 위한 객체) 필요없이 간단하게 데이터를 저장, 쿼리 및 동기화할 수 있습니다.

특징

ACID-Compliant

데이터베이스 트랜잭션이 제 때 이루어질 수 있게 하는 원자성(Atomicity), 항상성(consistency), 독립성(isolation), 내구성(durability)의 속성을 지니고 있을경우 ACID-Compliant하다고 표현합니다.

원자성

데이터 트랜잭션은 원자와 같이 더 작은 단위로 쪼개질 수 없습니다. 원자성은 전체 트랜잭션에서의 단지 한 요소가 되는 것을 의미하는 것뿐만 아니라, 전체 트랜잭션으로의 통합을 의미합니다. 다시 말해서, 한 트랜잭션이 정상적으로 작동하지 않는다면 다른 부분도 실패한다는 것입니다.

일관성

데이터베이스가 의도한대로 동작하기 위해서는 적절한 데이터 유효성 규칙을 준수해야 합니다. 따라서 일관성은 이러한 규칙을 준수하는 데이터만이 데이터베이스에 쓰여질 수 있다는 것을 의미합니다. 만약 데이터의 규칙을 따르지 않는 데이터가 생성하면 이전으로 '롤백'됩니다.

독립성

독립성은 여러 개의 트랜잭션이 서로에게 영향을 주지 않는 방식으로 동시에 수행되는 것을 의미합니다. 예를 들어 한 온라인 쇼핑몰에 재고가 10개가 있는 아이템이 있고, 2명의 손님이 각각 5개, 6개 아이템을 사고 싶어합니다. 만약 5개를 원하는 손님이 먼저 결제에 성공한다면, 남은 한 사람은 5개의 아이템을 살 수 밖에 없게 됩니다. 이처럼 독립성은 재고를 넘어서 아이템이 판매되는 것을 방지합니다.

내구성

내구성은 서버가 예상치 못한 상태로 다운되거나 시스템 에러가 발생한다해도 이미 완료된 트랜잭션의 데이터를 저장하는 것을 의미합니다.

NoSQL 데이터베이스

NoSQL은 "Not Only SQL"의 약어로, SQL만을 사용하지 않는 데이터베이스 관리 시스템을 지칭하는 단어입니다. 관계형 데이터베이스와는 달리 사전에 스키마를 정의하지 않아도 저장될 수 있는 유연성, 상업용 하드웨어를 사용해 증가한 트래픽을 지원할 수 있는 확장성, 높은 트래픽에도 빠르고 안정적으로 데이터를 전달할 수 있는 고성능, 여러 서버, 데이터 센터, 클라우드 리소스 전반의 데이터를 자동으로 복제할 수 있는 가용성과 분산형 데이터 저장소를 위해 설계된 고도의 기능성이라는 특징을 갖고 있습니다. 그러나 금융, 회계 분야 같이 데이터 변형 및 데이터 중복을 방지하기 위해 정규화된 데이터에 의존하는 작업이나 쿼리 복잡성이 높은 데이터 처리 방식의 경우에는 적합하지 않습니다.

데이터 컨테이너 모델 사용

Realm은 ORM이 아닌 데이터컨테이너 모델을 사용하고 데이터 객체는 Realm에 객체로 저장됩니다. 여기서 컨테이너란, OS상에 논리적인 구획을 만들고, 어플리케이션을 작동시키기 위해 필요한 라이브러리나 어플리케이션 등을 하나로 모아 마치 별도의 서버인 것처럼 사용할 수 있게 만드는 것을 의미합니다. Realm은 객체 컨테이너로서 Realm의 데이터는 쿼리, 필터링, 상호 연결이 가능하고 저장됩니다. 다시 말해서 Realm은 객체 형태로 데이터를 읽어오고 객체 형태로 DB에 저장하기 때문에 별도의 데이터 가공 과정이 필요가 없습니다.

사용법

Cocoapods 설치

pod 'RealmSwift'

객체 생성

객체 컨테이너로 동작하기 때문에 객체를 생성해주고, 변수 앞에는 @objc dynamic를 붙여줍니다.

// Define your models like regular Swift classes
class Dog: Object {
    @objc dynamic var name = ""
    @objc dynamic var age = 0
}
class Person: Object {
    @objc dynamic var name = ""
    @objc dynamic var picture: Data? = nil // optionals supported
    let dogs = List<Dog>()
}

Realm 생성

// Get the default Realm
let realm = try! Realm()

데이터 저장

// Use them like regular Swift objects
let myDog = Dog()
myDog.name = "Rex"
myDog.age = 1
print("name of dog: \(myDog.name)")

// Persist your data easily
try! realm.write {
    realm.add(myDog)
}

데이터 삭제

// Delete an object with a transaction
try! realm.write {
    realm.delete(myDog)
}

데이터 업데이트

실시간으로 업데이트 되기 때문에 별도의 구현이 필요없다.

이 외에도 다양한 사용방법이 존재하며, 자세한 내용은 공식 홈페이지를 참조하면 된다.

migration

Realm의 Table 구조를 바꾸게 되면 runtime error가 발생할 수 있습니다. 이 때 Table 구조를 업데이트 하는 것을 migration이라 합니다.

적용방법

먼저 RealmConfiguration 객체를 빌드합니다. schemaVersion은 버전을 올릴 때마다 수정해주어야 하며, migration에는 Migration 객체를 생성해서 넘겨줍니다.

let config = Realm.Configuration(
    schemaVersion: 2,
    migrationBlock: { migration, oldSchemaVersion in
        if oldSchemaVersion < 2 {
            migration.enumerateObjects(ofType: Person.className()) { oldObject, newObject in
                let firstName = oldObject!["firstName"] as! String
                let lastName = oldObject!["lastName"] as! String
                newObject!["fullName"] = "\(firstName) \(lastName)"
            }
        }
})

Realm.Configuration.defaultConfiguration = config

위 코드에서는 schemaVersion을 2로 설정하고, migrationBlock에 Migration 객체를 생성했습니다. 이때, oldSchemaVersion을 이용하여 이전 데이터베이스와 현재 데이터베이스를 비교합니다. 만약 oldSchemaVersion이 2보다 작다면, Person 클래스의 firstName과 lastName 속성을 이용하여 fullName 속성을 만듭니다.

마지막으로 새로 생성한 config 객체를 Realm Configuration으로 설정해주면 migration이 완료됩니다.

profile
우당탕탕 비전공자 개발자

0개의 댓글