Realm 모바일 데이터베이스

수십억 사용자들이 사용하고있고 개발자들이 사랑하는 Realm 모바일 데이터베이스는 빠르고 사용하기 쉬우며 오픈소스입니다. 그리고 완전히 무료입니다.

짧은 코드로 저장하고, 빠르게 쿼리하고, 개발 기간을 수주 이상 줄일 수 있습니다.

짧은 코드로 저장하고, 빠르게 쿼리하고, 개발 기간을 수주 이상 줄일 수 있습니다.

Realm 모바일 데이터베이스는 SQLite와 Core Data를 대체할 수 있습니다. zero-copy 디자인 덕분에 Realm 모바일 데이터베이스는 ORM 보다 훨씬 빠르며 SQLite를 직접 사용하는 것 보다 빠른 성능을 보이는 경우도 많습니다. 시작하는데는 몇분이면 됩니다. 쉽게 익힐 수 있습니다.

모바일을 위해 만들어진 데이터베이스 장점

오프라인-우선 기능

오프라인-우선 기능

앱이 오프라인 일 때에도 네트워크에 연결되어있을 때처럼 동작하게 만드세요.

빠른 쿼리

빠른 쿼리

복잡한 쿼리도 순식간에 이루어집니다, 언제나 최신 데이터를 유지하세요.

안전한 쓰레드 관리

안전한 쓰레드 관리

같은 데이터에 멀티쓰레드에서 동시에 접근할 수 있습니다.

크로스 플랫폼 지원

크로스 플랫폼 지원

같은 데이터베이스를 어떤 플랫폼에서건 공유할 수 있습니다.

암호화

암호화

데이터를 쉽게 암호화하고 복호화 하세요.

리액티브 아키텍쳐

리액티브 아키텍쳐

UI를 Realm과 연결하세요. 데이터가 자동으로 업데이트 됩니다.

class Dog {}

Dog.schema = {
  name: 'Dog',
  properties: {
    name: 'string',
    age: 'int',
  }
};

let realm = new Realm({ schema: [Dog] });
realm.write(() => {
  realm.create('Dog', {name: 'Rex', age: 1});
});

let pups = realm.objects('Dog').filtered('age < 2');
Dog *dog = [Dog new];
dog.name = @"Rex";
dog.age = 1;

RLMRealm *realm = [RLMRealm defaultRealm];
[realm transactionWithBlock:^{
  [realm addObject:dog];
}];

RLMResults<Dog *> *allDogs = [Dog allObjects];
RLMResults<Dog *> *pups = [allDogs objectsWhere:@"age < 2"];
class Dog: Object {
  dynamic var name = ""
  dynamic var age = 0
}

let dog = Dog()
dog.name = "Rex"
dog.age = 1

let realm = try! Realm()
try! realm.write {
  realm.add(dog)
}

let pups = realm.objects(Dog.self).filter("age < 2")
public class Dog extends RealmObject {
  public String name;
  public int age;
}

Dog dog = new Dog();
dog.name = "Rex";
dog.age = 1;

Realm realm = Realm.getDefaultInstance();
realm.beginTransaction();
realm.copyToRealm(dog);
realm.commitTransaction();

RealmResults<Dog> pups = realm.where(Dog.class)
                               .lessThan("age", 2)
                               .findAll();
public class Dog : RealmObject 
{
  public string Name { get; set; }
  public int Age { get; set; }
}

var realm = Realm.GetInstance();
realm.Write(() => 
{
  realm.Add(new Dog
  {
    Name = "Rex",
    Age = 1
  });
});

var pups = realm.All<Dog>().Where(d => d.Age < 2);

더 간결한 코드로 만들 수 있습니다

Just 스키마를 정의하기위해 RealmObject 를 subclass하여 정의하고, 스키마를 정의하기위해 RealmObject 를 subclass하여 정의하고, 스키마를 정의하고, 스키마를 정의하기위해 RealmObject 를 subclass하여 정의하고, 스키마를 정의하기위해 RealmObject 를 subclass하여 정의하고, 트랜젝션을 쉽게 관리하고, 그리고 자연스러운 인터페이스 NSPredicate. 간단한 문자열. NSPredicate. LINQ. 를 통해 쿼리 하세요. 데이터베이스를 사용하는 것은 이렇게 쉬워야합니다.

React Native executes JavaScript in a dedicated worker thread so common concurrency primitives are unavailable.
// Query and update the result in another thread
dispatch_async(dispatch_queue_create("background", 0), ^{
  Dog *theDog = [[Dog objectsWhere:@"age == 1"] firstObject];
  RLMRealm *realm = [RLMRealm defaultRealm];
  [realm beginWriteTransaction];
  theDog.age = 3;
  [realm commitWriteTransaction];
});
// Query and update from any thread
DispatchQueue(label: "background").async {
  let realm = try! Realm()
  let theDog = realm.objects(Dog.self).filter("age == 1").first
  try! realm.write {
    theDog!.age = 3
  }
}
public void onActivityCreated(Bundle savedInstanceState) {
  realm = Realm.getDefaultInstance();
  RealmResults<Customer> customers = realm.where(Customer.class).findAllAsync();
  changeListener = new RealmChangeListener() {
    @Override
    public void onChange(RealmResults<Customer> results) {
      listAdapter.notifyDataSetChanged(); // Update the UI
    }
  };
  customers.addChangeListener(changeListener);
}
// Query and update from any thread
Task.Run(() =>
{
  var realm = Realm.GetInstance();
  var theDog = realm.All<Dog>().First(d => d.Age == 1);
  realm.Write(() => theDog.Age = 3);
});

쓰레드간를 넘나들며 작접하세요

새로운 쓰레드에서 사용하기 위해서는 Realm에 새로운 레퍼런스를 만들면 그대로 사용할 수 있습니다. 각각의 쓰레드는 언제나 일관된 데이터를 보여주기때문에 상태가 언제나 업데이트 된 상태로 유지됩니다.

let key = new Int8Array(64);  // pupulate with a secure key

let realm = new Realm({ schema: [Dog], encryptionKey: key });

let dogs = realm.objects('Dog').filtered('name CONTAINS "Fido"');
// Generate a random encryption key
NSMutableData *key = [NSMutableData dataWithLength:64];
(void)SecRandomCopyBytes(kSecRandomDefault, key.length, (uint8_t *)key.mutableBytes);

// Open the encrypted Realm file
RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration];
config.encryptionKey = key;
RLMRealm *realm = [RLMRealm realmWithConfiguration:config error:nil];
// Use the Realm as normal
RLMResults<Dog *> *dogs = [Dog objectsInRealm:realm where:@"name contains 'Fido'"];
// Generate a random encryption key
var key = Data(count: 64)
_ = key.withUnsafeMutableBytes { bytes in
  SecRandomCopyBytes(kSecRandomDefault, 64, bytes)
}

// Open the encrypted Realm file
let realm = try! Realm(configuration: Realm.Configuration(encryptionKey: key))
// Use the Realm as normal
let dogs = realm.objects(Dog.self).filter("name contains 'Fido'")
// Generate a random encryption key
byte[] key = new byte[64];
new SecureRandom().nextBytes(key);

// Open the encrypted Realm file
RealmConfiguration realmConfiguration = new RealmConfiguration.Builder()
        .encryptionKey(key)
        .build();

// Use the Realm as normal
Realm realm = Realm.getInstance(config);
RealmResults<Dog> results = realm.where(Dog.class).contains("name", "Fido").findAll();
// Generate a random encryption key
var random = new Random();
var key = new Byte[64];
rnd.NextBytes(key);
var config = new RealmConfiguration("Mine.realm");
config.EncryptionKey = key;

// Open the encrypted Realm file
var realm = Realm.GetInstance(config);
// Use the Realm as normal
var dogs = realm.All<Dog>().Where(d => d.Name.Contains("Fido"));

모든것을 암호화 하세요

데이터를 AES-256로 암호화하세요. 금융권에서 사용할 정도로 안전합니다.

let realm = new Realm({ schema: [Person] });
realm.addListener((sender, name) => {
  if (name === 'change') {
    this.setState({ source: sender.objects('Dog') });
  }
});
self.notificationToken = [[Dog objectsWhere:@"age > 5"]
                            addNotificationBlock:^(RLMResults<Dog *> *results,
                                                   RLMCollectionChange *change,
                                                   NSError *error) {
  if (error) {
    // handle error
    return;
  } else if (!changes) {
    [self.tableView reloadData];
    return;
  }

  // Update table view to animate deletions, insertions and modifications
  [tableView beginUpdates];
  [tableView deleteRowsAtIndexPaths:[changes deletionsInSection:0]
    withRowAnimation:UITableViewRowAnimationAutomatic];
  [tableView insertRowsAtIndexPaths:[changes insertionsInSection:0]
    withRowAnimation:UITableViewRowAnimationAutomatic];
  [tableView reloadRowsAtIndexPaths:[changes modificationsInSection:0]
    withRowAnimation:UITableViewRowAnimationAutomatic];
  [tableView endUpdates];
}];
let realm = try! Realm()
notificationToken = realm.objects(Dog.self).filter("age > 5").addNotificationBlock { changes in
  switch changes {
  case .initial:
    tableView.reloadData()
    break
  case .update(_, let deletions, let insertions, let modifications):
    // Update table view to animate deletions, insertions and modifications
    break
  case .error(let error):
    // handle error
    break
  }
}
Realm realm = Realm.getDefaultInstance();

// Query in the background
RealmResults<Dog> results = realm.where(Dog.class)
  .greaterThan("age", 5)
  .findAllAsync();

// Use ChangeListeners to be notified about updates
results.addChangeListener(new RealmChangeListener<RealmResults<Dog>() {
  @Override
  public void onChange(RealmResults<Dog> results) {
    // Update UI
  }
});

// Or RxJava
Observable<RealmResults<Dog>> obs = results.asObservable();
// To bind a ListView to results of a query
public partial class DogsPage : ContentPage
{
  internal Realm realm;
  internal IEnumerable<Dog> Entries { get; }

  public DogsPage()
  {
    InitializeComponent();
    realm = Realm.GetInstance();

    // Results from queries will automatically notify the Binding
    // and update the ListView accordingly
    Entries = realm.All<Dog>().Where(d => d.Age > 5)
    DogsList.ItemsSource = Entries;
  }

<ListView x:Name="DogsList">
  <ListView.ItemTemplate>
    <DataTemplate>
      <TextCell Text="{Binding Name}" 
        Detail="{Binding Age, StringFormat='is {0:#}'}" /> 
    </DataTemplate>
  </ListView.ItemTemplate>
</ListView>

리액티브 앱을 개발하세요

Realm 객체는 언제나 살아있습니다. 즉 언제나 최신의 데이터를 유지하고있습니다. 데이터가 수정되면 알림을 받아 UI를 업데이트 할 수 있습니다. 앱이 오래된 데이터를 보여주는 일은 이제 없어집니다

// Authenticating the User
Realm.Sync.User.registerWithProvider('http://realm.example.co:9080', 'google', googleAccessToken, (error, user) => {
  if (!error) {
    // Opening a remote Realm
    var realm = new Realm({
      sync: {
        user: user,
        url: 'realm://realm.example.co:9080/~/userRealm',
      }
    });
    // Any changes made to this Realm will be synced across all devices!
  }
})
// Authenticating the User
[RLMSyncUser logInWithCredentials:[RLMSyncCredentials credentialsWithGoogleToken:@"google token"]
                    authServerURL:[NSURL URLWithString:@"http://realm.example.com:9080"]
                     onCompletion:^(RLMSyncUser *user, NSError *error) {
  if (user) {
    // Opening a remote Realm
    NSURL *realmURL = [NSURL URLWithString:@"realm://realm.example.com:9080/~/userRealm"];
    RLMRealmConfiguration *config = [[RLMRealmConfiguration alloc] init];
    config.syncConfiguration = [[RLMSyncConfiguration alloc] initWithUser:user realmURL:realmURL];
    RLMRealm *realm = [RLMRealm realmWithConfiguration:config error:nil];
    // Any changes made to this Realm will be synced across all devices!
  } else if (error) {
    // handle error
  }
}];
// Authenticating the User
SyncUser.logIn(with: .google(token: "google token"),
               server: URL(string: "http://realm.example.com:9080")!) { user, error in
  if let user = user {
    // Opening a remote Realm
    let realmURL = URL(string: "realm://realm.example.com:9080/~/userRealm")!
    let config = Realm.Configuration(syncConfiguration: SyncConfiguration(user: user, realmURL: realmURL))
    let realm = try! Realm(configuration: config)
    // Any changes made to this Realm will be synced across all devices!
  } else if let error = error {
    // handle error
  }
}
// Authenticating the User
User user = User.login(Credentials.google("google token"),
                       "http://realm.example.com:9080/auth");
// Opening a remote Realm
String realmURL = "realm://realm.example.com:9080/~/userRealm";
SyncConfiguration config = new SyncConfiguration.Builder(user,
                                                         realmURL).build();
Realm realm = Realm.getInstance(config);
// Any changes made to this Realm will be synced across all devices!
var user = await User.LoginAsync(Credentials.Google("google token"),
                                 new Uri("http://realm.example.com:9080"));

var realmUrl = new Uri("realm://realm.example.com:9080/~/userRealm");
var config = new SyncConfiguration(user, realmUrl);

var realm = Realm.GetInstance(config);
// Any changes made to this Realm will be synced across all devices!

데이터를 언제나 동기화하세요

Realm 모바일 플랫폼을 사용하여 Realm 모바일 데이터베이스를 Realm 오브젝트 서버와 완전하게 같이 동작하게 할 수 있습니다. Realm 오브젝트 서버의 URL을 설정하기만 하면 나머지는 로컬 데이터베이스를 사용하는 것과 똑같이 사용하면 됩니다. 데이터는 저장될때마나 자동으로 동기화될 것이고, 추가로 해줄 작업은 없습니다.

현재 Realm Java, Realm Objective‑C & Realm Swift에서 사용가능 합니다. Realm React Native 와 Realm Xamarin에서도 곧 지원할 예정입니다.

오픈소스입니다

The Realm Mobile Database is developed in the open. Thousands of developers work with us on GitHub, plus hundreds more write add-ons that work with the Realm Mobile Database. The 25,000 stars on our repos speak for themselves.

최신의 모바일 개발 뉴스를 받아보세요

세계 여러곳에서 일어나는 최고의 발표 세션자료와 개발 글들을 이메일로 받아보세요. 우리가 이미 블로그에 올린 자료들도 확인해보세요.



포춘 500 기업, 혁신적인 스타트업, app store 넘버원 앱 개발사의 성공 스토리

5분안에 시작할 수 있습니다. 무료입니다