최신 영문 문서를 보려면 이곳을 참고하세요.

Realm 리액트 네이티브는 안전하고, 영속적, 빠른 앱 모델 레이어를 효율적으로 작성하게 해줍니다. 모습은 아래와 같습니다.

// 모델과 프로퍼티를 정의합니다.
class Car {}
Car.schema = {
  name: 'Car',
  properties: {
    make:  'string',
    model: 'string',
    miles: 'int',
  }
};
class Person {}
Person.schema = {
  name: 'Person',
  properties: {
    name:    {type: 'string'},
    cars:    {type: 'list', objectType: 'Car'},
    picture: {type: 'data', optional: true}, // 선택적인 프로퍼티
  }
};

// 객체들을 지원하는 기본 Realm 가져오기
let realm = new Realm({schema: [Car, Person]});

// Realm 오브젝트를 만들어 로컬 저장소에 저장하기
realm.write(() => {
  let myCar = realm.create('Car', {
    make: 'Honda',
    model: 'Civic',
    miles: 1000,
  });
  myCar.miles += 20; // 프로퍼티 값을 갱신
});

// 많이 주행한 모든 차들을 질의
let cars = realm.objects('Car').filtered('miles > 1000');

// 한개의 자동차 Results 객체가 반환됩니다
cars.length // => 1

// 다른 차를 추가합니다
realm.write(() => {
  let myCar = realm.create('Car', {
    make: 'Ford',
    model: 'Focus',
    miles: 2000,
  });

// 질의 결과는 실시간으로 갱신됩니다
cars.length // => 2

시작하기

아래의 설치 설명을 따라 Realm 리액트 네이티브를 npm으로 설치하거나 깃헙의 소스를 보세요.

요구사항

  • 리액트 네이티브 어플리케이션을 실행할 수 있게 환경 설정을 합니다. 리액트 네이티브 설명을 따라가세요.
  • Realm을 사용하는 앱은 iOS와 안드로이드에서 사용할 수 있습니다.
  • 리액트 네이티브 0.20.0 이상을 지원합니다.
  • 리액트 네이티브 매니저(rnpm)이 글로벌하게 설치 되고 최신 버전인지 확인하세요.

    npm install -g rnpm

설치

  • 새로운 리액트 네이티브 프로젝트를 만드세요

    react-native init <project-name>
  • 디렉토리를 새 프로젝트로 변경하고 (cd <project-name>) realm 의존성을 추가합니다.

    npm install --save realm
  • 다음으로 realm 네이티브 모듈을 프로젝트에 연결하기 위해 rnpm을 사용합니다.

    rnpm link realm

이제 준비가되었습니다. Realm을 동작하기 위해 index.ios.jsindex.android.js에 있는 여러 분의 class <project-name>의 정의에 아래를 추가합니다.

const Realm = require('realm');

class <project-name> extends Component {
 render() {
   let realm = new Realm({
     schema: [{name: 'Dog', properties: {name: 'string'}}]
   });

   realm.write(() => {
     realm.create('Dog', {name: 'Rex'});
   });
   return (
     <View style={styles.container}>
       <Text style={styles.welcome}>
         Count of Dogs in Realm: {realm.objects('Dog').length}
       </Text>
     </View>
   );
 }
}

앱을 기계나 시뮬레이터에서 수행할 수 있습니다!

API 문서

전체 API 문서에서 모든 클래스, 메서드 등을 확인할 수 있습니다.

예제

깃헙의 프로젝트에서 클론을 받는 것으로 시작합니다.

git clone https://github.com/realm/realm-js.git

리액트 네이티브 예제 프로젝트는 examples/ReactExample 디렉토리에 있습니다. 처음 예제를 수행하기 앞서 지금 디렉토리에서 npm install을 실행해야 합니다.

도움을 구하려면

만약 (Crashlytics나 HockeyApp 같은) 크래쉬 리포터를 사용한다면 로그 수집 활성화를 잊지 마세요. Realm은 예외가 발생하거나 회복할 수 없는 상황이 있을 때 (사용자 데이터가 아닌) 메타데이터 정보를 로그로 남깁니다. 이 메시지들은 무언가 잘못되었을 때 디버깅하는 것을 돕습니다.

모델

Realm 데이타 모델은 스키마 정보를 정의해 초기화 과정에 Realm에 전달합니다. 객체의 스키마는 객체의 namenametype을 가진 속성으로의 집합이다. 객체와 리스트 속성을 위해 objectType을 지정할 수 있고 optional 이나 default도 이곳에 지정합니다.

var Realm = require('realm');

const CarSchema = {
  name: 'Car',
  properties: {
    make:  'string',
    model: 'string',
    miles: {type: 'int', default: 0},
  }
};
const PersonSchema = {
  name: 'Person',
  properties: {
    name:     'string',
    birthday: 'date',
    cars:     {type: 'list', objectType: 'Car'},
    picture:  {type: 'data', optional: true}, // 선택적인 프로퍼티
  }
};

// Car와 Person 모델로 Realm 초기화하기
let realm = new Realm({schema: [CarSchema, PersonSchema]});

기존의 클래스를 상속하고 모델 클래스를 정의하는 경우 스키마를 생성자에 정의하여 생성자를 Realm의 초기화할 때 전달합니다.

class Person {
  get ageSeconds() {
    return Math.floor((Date.now() - this.birthday.getTime()));
  }
  get age() {
    return ageSeconds() / 31557600000;
  }
}

Person.schema = PersonSchema;

// `Person` 생성자를 전달한 것에 주의하라
let realm = new Realm({schema: [CarSchema, Person]});

모델 클래스의 정의가되어 있으면 객체를 Realm에 저장하거나 검색할 수 있습니다.

realm.write(() => {
  let car = realm.create('Car', {
    make: 'Honda',
    model: 'Civic',
    miles: 750,
  });

  // 모델에 정의 된 모든 속성을 읽고 쓸 수 있습니다
  console.log('Car type is ' + car.make + ' ' + car.model);
  car.miles = 1500;
});

기본 프로퍼티 타입

Realm는 다음과 같은 데이터 유형을 기본 데이터 형으로 지원하고 있습니다: bool , int , float , double , string , data, date.

  • bool 속성은 JavaScript의 Boolean타입으로 연결됩니다.
  • int , floatdouble 속성은 JavaScript의 Number 형에 연결됩니다. 내부적으로 ‘int’ 와 ‘double’ 형은 64 비트로 저장됩니다. 반면 float 형은 32 비트로 저장됩니다.
  • string 속성은 String 형으로 연결됩니다.
  • data 속성은 ArrayBuffer 형으로 연결됩니다.
  • date 속성은 Date 형으로 연결됩니다.

기본 속성을 간단히 지정하는 경우 단 하나의 속성을 지정하게 됩니다. 그렇지 않은 경우에는 하나의 입구를 가지는 사전형을 정의해야 합니다.

const CarSchema = {
  name: 'Car',
  properties: {
    // 아래의 type 속성의 정의는 모두 같은 의미입니다
    make:   {type: 'string'},
    model: 'string',
  }
}

객체 속성

객체 스키마에 name 속성을 지정하여 객체 형을 지정합니다.

const PersonSchema = {
  name: 'Person',
  properties: {
    // 아래의 type 속성의 정의는 모두 같은 의미입니다
    car: {type: 'Car'},
    van: 'Car',
  }
};

객체 속성을 사용하는 경우 Realm을 열 때 지정한 스키마에 모든 참조 형이 정의되어 있어야 합니다.

// PersonSchema에서 'Car'형의 속성을 사용되고 있기 때문에 CarSchema도 전달해야 합니다.
let realm = new Realm({schema: [CarSchema, PersonSchema]});

객체 속성에 접근하려면 일반적인 속성 문법을 사용하여 중첩 된 속성에 접근합니다.

realm.write(() => {
  var nameString = person.car.name;
  person.car.miles = 1100;

  // 올바른 JSON을 속성으로 설정하여 새 Car를 생성합니다
  person.van = {make: 'Ford', model: 'Transit'};

  // 같은 자동차 인스턴스에 두 속성을 설정합니다
  person.car = person.van;
});

리스트 속성

리스트 속성을 위해 속성 형 listobjectType을 지정합니다.

const PersonSchema = {
  name: 'Person',
  properties: {
    cars: {type: 'list', objectType: 'Car'},
  }
}

리스트 속성에 접근하면 List 객체가 반환됩니다. List 객체는 일반적인 JavaScript 배열 객체와 거의 흡사한 메서드를 가집니다. 크게 다른 점은 List 객체에 대한 변경 사항이 자동으로 하부의 Realm에 보관된다는 점입니다. 또 List 객체는 리스트에 의해 획득된 하부의 객체를 가지고 있습니다. List 인스턴스를 소유한 객체의 속성으로부터만 접근할 수 있고 수동으로 생성할 수 없습니다.

let carList = person.cars;

// 리스트에 새 차들을 추가하기
realm.write(() => {
  carList.push({make: 'Honda', model: 'Accord', miles: 100});
  carList.push({make: 'Toyota', model: 'Prius', miles: 200});
});

let secondCar = carList[1].model;  // 배열 인덱스를 통해 접근합니다

선택적 속성

각 속성은 optional 지사자를 이용하여 선택적인지 비 선택적인지 정의할 수 있습니다.

const PersonSchema = {
  name: 'Person',
  properties: {
    name:     {type: 'string'},               // 필수 속성
    birthday: {type: 'date', optional: true}, // 선택적 속성

    // 객체 속성은 언제나 선택적입니다
    car:      {type: 'Car'},
  }
};

let realm = new Realm({schema: [PersonSchema, CarSchema]});

realm.write(() => {
  // 선택적 속성은 생성시에는 `null` 또는 `undefined`로 설정할 수 있습니다
  let charlie = realm.create('Person', {
    name: 'Charlie',
    birthday: new Date(1995, 11, 25),
    car: null,
  });

  // 선택적 속성은 null` 또는 `undefined`, 새로운 null이 아닌 값으로
  // 설정될 수 있습니다
  charlie.birthday = undefined;
  charlie.car = {make: 'Honda', model: 'Accord', miles: 10000};
});

기본 프로퍼티 값

속성 정의에 default 속성을 사용하여 기본 속성 값은 정의할 수 있습니다. 기본 값을 사용하기 위해서는 객체 색성시 속성을 설정하지 않습니다.

const CarSchema = {
  name: 'Car',
  properties: {
    make:  {type: 'string'},
    model: {type: 'string'},
    drive: {type: 'string', default: 'fwd'},
    miles: {type: 'int',    default: 0}
  }
};

realm.write(() => {
  // `miles` 속성은 지정하지 않았기 때문에 기본값 `0`이 설정됩니다.
  // `drive` 속성은 지정되었기에 기본 값을 새로운 값으로 대체됩니다.
  realm.create('Car', {make: 'Honda', model: 'Accord', drive: 'awd'});
});

인덱스화된 속성

속성을 인덱스로 지정하기 위해 indexed 지시자를 속성 정의에 추가할 수 있다. 이는 int, string, bool 속성 형을 지원한다.

var BookSchema = {
  name: 'Book',
  properties: {
    name: { type: 'string', indexed: true },
    price: 'float'
  }
};

프로퍼티를 인덱스화하면 속성의 동등 비교는 향상되지만 삽입은 비용이 들어 느려진다.

기본 키

객체 모델의 stringint 속성을 위한 객체 모델에 primaryKey를 지정할 수 있다. 기본 키를 정의하면 객체의 검색, 업데이트를 효과적으로 할 수 있고 각 값들이 중복되지 않은 것을 강요할 수 있습니다. 기본 키가 설정된 객체는 Realm에 저장 한 후 기본 키를 변경할 수 없습니다.

const PersonSchema = {
  name: 'Person',
  primaryKey: 'id',
  properties: {
    id:   'int',    // 기본 키
    name: 'string'
  }
};

기본 키는 자동으로 인덱스화됩니다.

쓰기

모든 객체에 대한 변경(추가, 변경, 삭제)은 쓰기 트랜잭션 안에서 이루어져야 합니다.

쓰기 트랜잭션는 무시할 수 없는 오버헤드를 가져옵니다. 쓰기 트랜잭션이 최소가 되도록 설계하십시오.

객체의 생성

지금까지 설명한 바와 같이, 객체의 생성은 create 메소드를 사용합니다.

let realm = new Realm({schema: [CarSchema]);

realm.write(() => {
  realm.create('Car', {make: 'Honda', model: 'Accord', drive: 'awd'});
});

중첩된 객체

객체 속성을 가진 객체는 각 객체 속성을 JSON을 사용하여 재귀적으로 하위 속성을 포함하여 한 번에 생성 할 수 있습니다.

let realm = new Realm({schema: [PersonSchema, CarSchema]);

realm.write(() => {
  realm.create('Person', {
    name: 'Joe',
    // 중첩 된 객체를 한 번에 재귀 적으로 생성할 수 있습니다
    car: {make: 'Honda', model: 'Accord', drive: 'awd'},
  });
});

객체 갱신

전형적인 갱신

쓰기 트랜잭션에서 속성들을 설정해서 어떤 객체를 갱신할 수 있습니다.

realm.write(() => {
  car.miles = 1100;
});

기본 키를 사용하여 객체를 생성하고 갱신

모델이 기본 키를 가진 경우 기본 키 값에 따라 Realm이 지능적으로 객체를 갱신하거나 추가할 수 있습니다. 이 기능을 이용하려면 create 메소드의 세번째 인자를 true로 전달합니다.

realm.write(() => {
  // 책 객체를 생성하고 저장합니다
  realm.create('Book', {primaryId: 1, title: 'Recipes', price: 35});

  // 기본키에 맞는 book을 새 가격으로 갱신합니다
  realm.create('Book', {primaryId: 1, price: 55}, true);
});

위의 예제에서 먼저 저장된 객체는 기본 키로 primaryId 속성이 기본 키는 1 인 객체가 있고 세 번째 인자를 true 로 지정하였습니다. 그렇기 때문에 새로운 객체가 생성되는 것이 아니라 기존 객체의 가격 속성이 업데이트됩니다. name 속성은 전달하는 객체에 포함되어 있지 않기 때문에 갱신되지 않고 원래 값이 유지됩니다.

객체 삭제

객체를 삭제하려면 쓰기 트랜잭션에서 delete 메소드를 사용합니다.

realm.write(() => {
  // 책을 생성합니다
  let book = realm.create('Book', {primaryId: 1, title: 'Recipes', price: 35});

  // 책을 삭제합니다
  realm.delete(book);

  // `Results`, `List`나 자바스크립트 `Array`를 전달하여
  // 여러권의 책을 삭제할 수 있습니다
  let allBooks = realm.objects('Book');
  realm.delete(allBooks); // Deletes all books
});

질의

질의는 어느 하나의 객체 형의 객체들을 Realm에서 가져옵니다. 검색 조건을 지정하여 결과를 필터링하거나 정렬 할 수 있습니다. (질의와 속성 접근을 포함한) 모든 질의는 Realm에서 지연됩니다. 데이터는 객체와 속성에 접근 한 경우에만 읽어집니다. 이를 통해 대량의 데이터도 효율적으로 처리 할 수​​ 있습니다.

질의를 실행하면 Results 객체가 반환됩니다. Results는 단순한 뷰나 데이터이고, 변경할 수 없습니다.

Realmd에서 객체를 가져오는 가장 기본적인 방법은 Realmobjects 메소드를 사용하는 것입니다. 이는 인자로 주어진 형태의 객체를 모두 가져옵니다.

let dogs = realm.objects('Dog'); // Realm에서 개를 전부 가져옵니다

필터링

filtered 메소드에 질의할 문자열을 전달하여 Results를 필터링 할 수 있습니다.

아래의 예는 이전의 전체 강아지를 가져 오는 예제를 수정하여 색상이 tan이고 이름이 ‘B’로 시작하는 객체를 가져옵니다.

let dogs = realm.objects('Dog');
let tanDogs = dogs.filtered('color = "tan" AND name BEGINSWITH "B"');

그 시점에서 NSPredicate 문의 부분집합만 질의 언어입니다. ==, !=, >, >=, <, <=의 기본적인 비교 연산자는 수치 속성만 지원합니다. ==, BEGINSWITH, ENDSWITH, CONTAINS 연산자를 문자열 속성에서 사용할 수 있습니다. 문자열 비교는 연산자에 [c]를 덧붙여서 대소문자 구분없이 할 수 있습니다. ==[c], BEGINSWITH[c]등이죠. 연결이나 자식 객체에 대한 속성에 의한 필터링은 질의에서 키패스를 지정함으로서 가능합니다. 예: car.color == 'blue'.

정렬

Results는 정렬 기준을 설정할 수 있고 하나 이상의 속성에 기반해서 정렬할 수 있습니다. 아래는 위의 주행거리를 숫자를 표시하는 예제에서 반환받은 자동차들을 정렬하는 예입니다.

let hondas = realm.objects('Car').filtered('make = "Honda"');

// 주행거리 순으로 혼다 자동차를 정렬합니다
let sortedHondas = hondas.sorted('miles');

Results의 순서만 쿼리를 정렬 할 때 일관성을 유지하도록 보장합니다. 성능상의 이유로, 삽입 순서는 보장할 수 없습니다.

자동 갱신되는 결과

Results 인스턴스는 라이이브며 하부의 데이터로 자동 갱신되는 뷰입니다. 이 의미는 결과를 다시 가져올 필요가 없다는 것입니다. 객체 수정은 질의에 영향을 주고 결과에 즉시 반영됩니다.

let hondas = realm.objects('Car').filtered('make = "Honda"');
// hondas.length == 0

realm.write(() => {
  realm.create('Car', {make: 'Honda', model: 'RSX'});
});
// hondas.length == 1

이는 objects, filtered, sorted 메서드에 반환된 걸 포함해서 모든 Results 인스턴스에 적용됩니다.

Results의 속성은 Realm을 빠르고 효과적이게 하며 동시에 여러분의 코드를 단순하고 보다 반응적으로 만듭니다. 예를 들어 쿼리 결과를 표시하는 뷰에서 Results 를 보유하고 직접 데이터의 표시에 사용하면 재검색 할 필요없이 항상 최신 데이터를 표시 할 수 있습니다.

변경 이벤트를 구독하면 Realm 데이터의 갱신을 알 수 있어 Results를 다시가져올 필요가 없고 앱의 UI가 갱신되어야 할 때를 알 수 있습니다.

결과 제한

대부분의 다른 데이터베이스 기술은 (SQLite의 ‘LIMIT’ 키워드같은) 질의의 결과에 대한 ‘페이지옮기기’를 제공합니다. 이 방법은 디스크의 과도한 읽어들이거나 한 번에 대량의 데이터를 메모리에로드 하는 것을 피하기 위해 사용됩니다.

Realm 질의는 지연 실행되므로 이러한 페이지 옮기기는 전혀 필요 없습니다. 왜냐하면 Realm은 질의로부터 객체를 실제로 명시적인 접근을 할 때만​ 불러오기 때문입니다.

UI관련 혹 다른 구현에서 질의된 객체의 특정 소집합이 필요하다면 단순히 Results를 가져오고 필요한 객체들만 읽으면 됩니다.

let cars = realm.objects('Car');

// 처음 5개의 차만 가지고 옵니다
let firstCars = cars.slice(0, 5);

Realms

다중 Realm

어떨 경우에는 여러 Realm 파일을 다른 위치에 저장하는 것이 유용합니다.

예를 들어 기존의 메인 Realm 파일 대신에 애플리케이션의 Realm 파일로 어떤 데이터를 저장하고 싶을 수 있습니다. Realm 객체의 초기화시에 path 를 지정하여 Realm 파일의 저장 위치를 지정할 수 있습니다. 모든 경로는 애플리케이션의 쓰기가능한 문서 디렉토리로 부터 상대적입니다.

// 다른 경로의 realm을 열기
let realmAtAnotherPath = new Realm({
  path: 'anotherRealm.realm',
  schema: [CarSchema]
});

기본 Realm 경로

이 문서에서 지금까지의 코드 예제에서는 path 인자를 지정하지 않았습니다. path 인자를 지정하지 않으면 기본 경로가 사용됩니다. 기본 저장 경로에 접근하거나 변경하려면 전역 속성에 정의 된 Realm.defaultPath을 사용합니다.

스키마 버전

Realm의 초기화시에 지정할 수있는 마지막 선택은 schemaVersion 속성입니다. 지정하지 않으면 기본 값으로 0 이 사용됩니다. 기존 데이터에서 스키마를 변경 한 경우에는 반드시 schemaVersion 을 초기화 할 때 지정해야합니다. 만약 스키마가 변경되어 있음에도 불구하고 schemaVersion 를 지정하지 않은 경우는 예외가 발생합니다.

const PersonSchema = {
  name: 'Person',
  properties: {
    name: 'string'
  }
};

// schemaVersion의 기본 값은 0
let realm = new Realm({schema: [PersonSchema]});

const UpdatedPersonSchema = {
  // 스키마 이름이 같기 때문에 Realm의
  // 이전 `Person` 객체는 갱신됩니다
  name: 'Person',
  properties: {
    name: 'string',
    dog:  'Dog'     // 새 프로퍼티
  }
};

// 스키마가 업데이트되어 있음에도 불구하고
// `schemaVersion`을 지정하지 않기 때문에 예외가 발생합니다.
let realm = new Realm({schema: [UpdatedPersonSchema]});

// 새로운 스키마로 Realm을 가져오는데 성공합니다
// this will succeed and update the Realm to the new schema
let realm = new Realm({schema: [UpdatedPersonSchema], schemaVersion: 1});

Realm의 현재 스키마 버전을 가져오길 바란다면 Realm.schemaVersion 메서드를 사용할 수 있습니다.

let currentVersion = Realm.schemaVersion(Realm.defaultPath);

마이그레이션

데이터베이스를 사용할 때 데이터 모델은 종종 바뀝니다. 예를 들어 아래의 Person 모델을 가정해봅시다.

var PersonSchema = {
  name: 'Person',
  properties: {
    firstName: 'string',
    lastName: 'string',
    age: 'int'
  }
}

이 데이터 모델이 성과 이름을 분리해서 받는 대신 name 속성을 요구하도록 갱신하길 원합니다. 이를 위해 아래와 같이 스키마를 바꾸어야 합니다.

var PersonSchema = {
  name: 'Person',
  properties: {
    name: 'string',
    age: 'int'
  }
}

이 시점에서 기존 모델 버전으로 저장한 데이터가 있다면 새 코드와 기존에 Realm이 디스크에 저장한 낡은 데이터 간에 불일치가 됩니다. 불일치가 발생하고 마이그레이션을 하지 않은채 기존의 Realm을 새 스키마로 열게되면 예외가 발생합니다.

마이그레이션 수행하기

스키마 버전을 갱신하고 부가적인 migration 함수를 정의하여 마이그레이션과 관련된 스키마 버전을 정의한다. 작성한 마이그레이션 함수는 기존의 스키마에서 현재의 스키마로 데이터 모델을 바꾸기 위한 어떤 로직을 제공합니다. Realm이 열릴 때 마이그레이션이 필요한 경우에는 주어진 스키마 버전으로 Realm을 갱신하도록 마이그레이션 함수를 적용합니다.

주어진 마이그레이션 함수가 없다면 새로운 schemaVersion으로 갱신할 때 새로운 속성은 자동으로 추가되고 낡은 속성들은 데이터베이스로 부터 제거됩니다. 만약 버전을 업그레이드할 때 낡은 속성을 갱신하고 싶거나 새로운 속성들을 초기화하길 원한다면 마이그레이션 함수에서 이를 하여야 합니다. 예를 들어 이전에 정의한 Person 모델을 마이그레이션 하고 싶다고 가정합시다. 오래된 firstNamelastName 속성을 이용하여 새로운 스키마의 속성 name을 초기화합시다.

var realm = new Realm({
  schema: [PersonSchema],
  schemaVersion: 1,
  migration: function(oldRealm, newRealm) {
    // schemaVersion을 1로 갱신해야 할때만 이 변경을 적용합니다
    if (oldRealm.schemaVersion < 1) {
      var oldObjects = oldRealm.objects('Person');
      var newObjects = newRealm.objects('Person');

      // 모든 객체를 순환하여 새 스키마의 name 속성을 설정합니다
      for (var i = 0; i < oldObjects.length; i++) {
        newObjects[i].name = oldObjects[i].firstName + ' ' + oldObjects[i].lastName;
      }
    }
  }
});

var fullName = realm.objects('Person')[0].name;

한번 마이그레이션이 성공적으로 호출되면 Realm과 모든 객체들은 앱에서 일반적일 때와 같이 접근이 됩니다.

선형 마이그레이션

위에 설명한 마이그레이션 패턴으로 여러 버전의 마이그레이션을 할 때 여러분은 잠재적으로 이슈를 만날 가능성이 있습니다. 사용자가 앱 업 데이트를 뛰어넘었고 속성이 버전을 뛰어넘은 동안 여러번 변경되었을 수 있습니다. 이 경우 낡은 스키마에서 최신의 스키마로 갱신하기 위해 낡은 마이그레이션 코드를 수정하여야 할 수 있습니다.

이 이슈를 예방하기 위해 여러 마이그레이션을 선형적으로 하고 이전 버전으로 부터 데이터베이스가 갱신된 것을 확실히 하고 연관된 마이그레이션 코드를 수행할 수 있습니다. 이 패턴으로 하기 위해서는 낡은 마이그레이션 코드는 절대 변경되어서는 안되고 낡은 스키마와 코드 블록을 앞으로를 위해 가지고 있어야 합니다. 예제는 다음과 같습니다.

var schemas = [
  { schema: schema1, schemaVersion: 1, migration: migrationFunction1 },
  { schema: schema2, schemaVersion: 2, migration: migrationFunction2 },
  ...
]

// 배열에 있는 첫번째 스키마기 때문에
// 현재 스키마 버전에 적용되는 첫번째 스키마
var nextSchemaIndex = Realm.schemaVersion(Realm.defaultPath);
while (nextSchemaIndex < schemas.length) {
  var migratedRealm = new Realm(schemas[nextSchemaIndex++]);
  migratedRealm.close();
}

// 마지막 스키마로 Realm을 엽니다
var realm = new Realm(schemas[schemas.length-1]);

변경 이벤트

변경 이벤트는 쓰기 트랜잭션이 완료되면 발송됩니다. 변경 이벤트는 이렇게 등록합니다.

// Realm 변경 이벤트를 관찰합니다
realm.addListener('change', () => {
  // Update UI
  ...
});

// 모든 리스너를 해제합니다
realm.removeAllListeners();

리액트 네이티브 ListView

ListResults 인스턴스를 ListView 의 데이터 소스로 이용하는 경우 realm/react-native 모듈에서 제공되는 ListViewListView.DataSource 을 이용하는 것을 강하게 권장합니다.

import { ListView } from 'realm/react-native';

API는 거의 React.ListView와 같습니다. 자세한 정보는 ListView documentation를 참고하세요.

암호화

미국으로부터의 수출 제한이나 금수 조치가 있는 국가에 거주하는 경우 Realm 사용에 대한 제한이 있을 수 있으므로, 저희 라이센스의 수출 규정 준수 조항을 참고하십시오.

Realm을 만들때 64 바이트 암호 키를 제공하면 Realm은 데이터베이스 파일을 디스크에 AES-256+SHA2로 저장하는 것을 지원합니다.

var key = new Int8Array(64);  // 암호키를 생성하기
var realm = new Realm({schema: [CarObject], encryptionKey: key});

// Realm을 일반적인 방법으로 쓰기
var dogs = realm.objects('Car');

디스크의 저장되는 모든 데이터가 필요시 투명하게 AES-256 암호화, 복호화 과정을 겪고 SHA-2 HMAC으로 검증되게 됩니다. Realm 인스턴스를 얻을 때 마다 동일한 암호키가 필요합니다.

암호화된 Realm을 사용할 때 (일반적으로 10% 내로 느려지는) 성능 지연이 있습니다.

문제 해결

충돌 보고

우리는 개발자로 충돌 보고 도구를 사용하실 것을 권장하고 있습니다. (디스크 IO 등과 같은) 많은 Realm 작업 중에 실시간 오류가 발생할 수 있습니다. 그렇기에 충돌 보고서를 수집하는 것은 무엇으로 인해 문제가 발생했는지를 확인할 수 있고 오류 처리 개선 및 버그 수정에 도움이 됩니다.

많은 상용 충돌 보고 도구들은 로그를 수집하는 옵션을 제공합니다. 우리는 이 기능을 사용하는 것을 강하게 권유합니다. 예외가 발생하거나 회복 불가능상 상황에 빠졌을 때 Realm이 (사용자 데이터를 제외한) 메타데이터 정보를 기록할 수 있습니다. 이 메시지들은 이런 문제가 발생했을 때 디버깅에 유용합니다.

Realm 이슈 보고하기

Realm에 대한 어떤 이슈를 발견하면 우리가 충분히 이해할 수 있게 많은 정보를 포함하거나 재현할 수 있는 정보들을 포함해서 GitHub에 이슈를 발행하거나 kr@realm.io로 메일을 주세요.

아래 정보는 우리에게 매우 유용합니다.

  1. 목적
  2. 기대 결과
  3. 실제 결과
  4. 재현 단계
  5. 이슈에 집중한 코드 샘플 (컴파일 가능한 전체 작동 프로젝트가 이상적입니다).
  6. Realm의 버전
  7. 충돌 로그와 스택 트레이스 위에 자세히 나온 충돌 보고을 참고하세요