Realm Blog

이제 어디에서나 JavaScript로 Realm을 사용할 수 있습니다. Node.js 전체 지원 소식입니다!

by /

Realm JavaScript 문서를 통해 개발을 시작해 보세요. 스키마를 정의하고 모델 객체 자체를 사용할 수 있으며, 쿼리가 자동으로 업데이트되는 Realm 데이터베이스를 사용하면 데이터를 쉽게 저장할 수 있습니다. 우리는 JavaScript를 플랫폼의 핵심 요소로 삼아 JS 스킬을 가진 모든 개발자들이 Realm을 사용하기 쉽게 했습니다. React Native에서 Realm 모바일 데이터베이스를 지원하는 것부터 출발해서, Linux와 macOS에서 Node.js 버전의 Realm을 사용할 수 있도록 해서 Realm 모바일 플랫폼의 영역을 보다 넓혔습니다. 그리고 드디어 Windows에서의 Node.js 기능을 지원합니다! 이제 JavaScript를 사용할 수 있는 곳이면 어디서나 Realm을 사용할 수 있습니다.

이제 Realm은 React Native뿐만이 아니라 Windows, Linux, macOS 상의 Node.js도 지원합니다. 모바일에서 Realm을 사용하는 것처럼 Realm 모바일 데이터베이스의 장점을 모두 누릴 수 있습니다. 앱을 구축하는 데 필요한 모든 데이터를 쉽고 효율적으로 저장할 수 있습니다. 또한 데이터를 쉽게 동기화하고 JavaScript를 사용해서 멋진 기능의 실시간 협업 앱을 구축할 수 있도록 Win32에서의 Realm 모바일 플랫폼 지원을 위해 열심히 노력하고 있으므로, 곧 좋은 소식을 전해드릴 수 있을 겁니다.

Realm의 장점은 단지 사용하기 쉽다는 점뿐만이 아닙니다. 더 나은 앱 경험을 제공할 수 있도록 JavaScript의 장점과 시너지를 낼 수 있습니다. Realm은 데이터가 변경되면 자동으로 새로 고침되는 반응형 원리를 가지고 있으므로 이벤트 기반 아키텍처에 매우 적합합니다. 또한 크로스 플랫폼이므로 고객이 사용하는 기기와 관계없이 앱을 제공할 수 있도록 JavaScript의 광대한 도달 범위를 활용할 수 있습니다. 마지막으로 Node.js에 대한 보편적 지원으로 서버 단에서도 사용할 수 있습니다. 예를 들어 Realm과 Node.js를 사용해서 웹서버에서의 프로세스간 통신을 할 수도 있습니다.

Realm은 모든 플랫폼의 어느 기기에서나 가장 최신이자 최고의 훌륭한 앱을 더 쉽게 개발할 수 있도록 돕고 있습니다. 오늘 Realm이 진정한 보편적 데이터 플랫폼이 되기 위한 여정에서 또 하나의 큰 도약을 이뤄냈으며, 개발자 여러분이 Realm과 함께 무엇을 만들어낼지 정말 기대됩니다. 지금 당장 Realm JS 문서를 통해 Realm 모바일 데이터베이스로 개발을 시작해 보세요!

더 읽어보기

Realm Java 3.0을 소개합니다: 컬렉션 알림과 스냅샷 및 관계간 정렬이 가능합니다!

by /

2017년 2월 28일 Realm Java 3.0이 발표됐습니다. 이번 릴리즈부터 관계를 기준으로 정렬할 수 있게 됐으며, Realm의 실시간 컬렉션인 RealmResultsRealmList에 정밀한 컬렉션 알림 기능을 추가해서 앱의 원소가 추가, 삭제, 변경되는 것을 알 수 있습니다.

정밀한 컬렉션 알림

지금까지는 Realm에서 제공하는 단일 RealmChangeListener 인터페이스를 사용해서 Realm, RealmObject, RealmResults에 클래스에 등록했습니다. 하지만 어떤 것이 변경됐는지에 대한 정보를 줄 수 없고 단지 변화가 있었던 것만을 알릴 수 있다는 인터페이스상의 한계가 있었습니다. 많은 경우 이것만으로도 충분하지만, 더 많은 정보가 필요한 경우도 있습니다. 일반적으로 RecyclerView의 변화를 애니메이션으로 표시하려는 경우입니다. Realm의 객체는 실시간으로 업데이트되므로 여태까지는 주로 realm.copyFromRealm()과 Android Support Library의 DiffUtil 클래스를 조합해서 이를 해결할 수 있지만 이상적인 방법은 아니었습니다.

이번 릴리즈에서 저희는 정밀한 컬렉션 알림을 추가했습니다. 이는 RealmResults에 등록할 수 있는 새로운 인터페이스로 정확히 어떤 객체가 추가, 삭제, 변경됐는지에 대한 정보를 줍니다. 따라서 실제로 변경된 원소만을 새로 고쳐서 보다 빠르고 반응이 빠른 UI를 구성할 수 있습니다.

또한 Android Adapters 라이브러리도 업데이트해서 RealmRecyclerViewAdapter가 매끄러운 애니메이션을 위해 자동으로 정밀한 알림을 사용하도록 했습니다. 컬렉션 알림 없이 RecyclerView를 사용하는 것과 비교해서 실제 상황을 영상으로 보여드리겠습니다.

private final OrderedRealmCollectionChangeListener<RealmResults<Person>> changeListener = new OrderedRealmCollectionChangeListener() {
    @Override
    public void onChange(RealmResults<Person> collection, OrderedCollectionChangeSet changeSet) {
        // `null`  means the async query returns the first time.
        if (changeSet == null) {
            notifyDataSetChanged();
            return;
        }
        // For deletions, the adapter has to be notified in reverse order.
        OrderedCollectionChangeSet.Range[] deletions = changeSet.getDeletionRanges();
        for (int i = deletions.length - 1; i >= 0; i--) {
            OrderedCollectionChangeSet.Range range = deletions[i];
            notifyItemRangeRemoved(range.startIndex, range.length);
        }

        OrderedCollectionChangeSet.Range[] insertions = changeSet.getInsertionRanges();
        for (OrderedCollectionChangeSet.Range range : insertions) {
            notifyItemRangeInserted(range.startIndex, range.length);
        }

        OrderedCollectionChangeSet.Range[] modifications = changeSet.getChangeRanges();
        for (OrderedCollectionChangeSet.Range range : modifications) {
            notifyItemRangeChanged(range.startIndex, range.length);
        }
    }
};

정밀한 컬렉션 알림은 다른 Realm 리스너와 동일하게 작동하므로, findAllAsync()를 사용하는 것처럼 쿼리가 비동기적으로 실행되면 정밀한 체인지셋이 백그라운드 스레드에서 계산돼서 결과를 UI 스레드로 보내며, 이 때 DiffUtil을 사용해서 변경사항을 계산하는 메모리 오버헤드가 발생하지 않습니다.

컬렉션 스냅샷

Realm의 핵심 설계 원칙은 “라이브” 객체와 컬렉션입니다. 즉, 쿼리에서 RealmResults를 생성하면 기본 데이터가 변경될 때마다 최신 상태로 유지됩니다. 단지 RealmChangeListener`를 등록해서 쿼리의 결과가 업데이트될 때 알림을 받을 수 있으므로 매우 효과적인 반응형 구조를 만들 수 있습니다.

하지만 어떤 경우 이 “라이브” 특성으로 라이브 컬렉션을 순회할 때 예기치 않은 문제가 발생할 수도 있습니다. 예제와 함께 설명하겠습니다.

RealmResults<Guest> uninvitedGuests = realm.where(Guests.class)
  .equalTo("inviteSent", false)
  .findAll();

for (i = 0; i < uninvitedGuests.size(); i++) {
  realm.beginTransaction()
  uninvitedGuests.get(i).sendInvite();
  realm.commitTransaction();
}

여기서 초대받지 못한 모든 손님에 대한 초대를 보내기 위해 쿼리를 했습니다. 만약 uninvitedGuests가 일반적인 ArrayList라면 예상한 대로 동작해서 모든 손님이 초대를 받을 수 있을 겁니다.

하지만 RealmResults는 라이브로 업데이트되고, for 루프 안에서 트랜잭션을 실행하기 때문에 Realm은 자동으로 순회할 때마다 RealmResults를 업데이트합니다. 이 경우 uninvitedGuests 리스트에서 손님이 삭제돼서 전체 배열에서 변동이 일어나지만, for 루프가 현재 인덱스를 추적하기 때문에 인덱스가 잘못된 위치에 있게 됩니다. 결과적으로 절반의 손님만 초청을 받게 되므로 잘못된 결과로 이어집니다.

이를 해결하기 위해서는 두 가지 해결 방법이 있습니다.

// 1. 전체 루프를 트랜젝션 안에 감싸기
realm.beginTransaction()
for (i = 0; i < uninvitedGuests.size(); i++) {
  uninvitedGuests.get(i).sendInvite();
}
realm.commitTransaction();

// 2. 리스트를 역방행으로 순회하기
for (int i = uninvitedGuests.size() - 1; i >= 0; i--) {
  realm.beginTransaction()
  uninvitedGuests.get(i).sendInvite();
  realm.commitTransaction();
}

두 가지 해결 방안 모두 명확하지 않으므로, Realm Java 0.89에서는 RealmResults의 모든 업데이트를 Handler.postAtFrontOfQueue를 사용해서 다음 루퍼 이벤트로 연기하도록 했습니다.

이렇게 해서 간단한 for 루프가 예상대로 작동할 수 있게 됐지만, RealmResults의 동기화가 약간 지연된다는 반대 급부가 있었습니다. 예를 들어 guest 객체에 boolean 값을 설정하는 대신 객체 자체를 삭제하는 경우 쿼리 결과에는 여전히 존재해서 잘못된 객체가 될 수 있습니다.

realm.beginTransaction();
guests.get(0).deleteFromRealm(); // Delete the object from Realm
realm.commitTransaction();
guests.get(0).isValid() == false; // You could now get a reference to a deleted object.

이런 경우가 실제 경우에 거의 발생하지는 않으므로 Realm의 핵심 설계 결정을 위반하지 않고 표준 반복 동작을 구현했다고 할 수 있습니다.

3.0 릴리즈에서 우리는 RealmResults가 다시 온전히 라이브가 되도록 해서 이런 결정을 재검토했습니다. 하지만 라이브 컬렉션이 여전히 간단한 for 루프에서 사용하기 쉽도록 createSnapshot() 메서드를 통해 현재 안정적인 목록을 제공합니다. 간단한 for 루프 안에서 데이터가 변경되는 경우 이 스냅샷을 사용하면 됩니다. 단, 대부분의 경우 루프 안에서 트랜잭션을 발생시키는 것이 여전히 추천하지 않는 패턴임을 기억하세요.

RealmResults<Person> uninvitedGuests = realm.where(Person.class).equalTo("inviteSent", false).findAll();
OrderedRealmCollectionSnapshot<Person> uninvitedGuestsSnapshot = uninvitedGuests.createSnapshot();
for (int i = 0; uninvitedGuestsSnapshot.size(); i++) {
    realm.beginTransaction();
    uninvitedGuestsSnapshot.get(i).setInvited(true);
    realm.commitTransaction();
}

Iterator가 신 뒤에서 이 스냅샷을 사용하므로 항상 사용하던 방식에서 기대하는 대로 동작합니다.

realm.beginTransaction();
RealmResults<Person> uninvitedGuests = realm.where(Person.class).equalTo("inviteSent", false).findAll();
for (Person guest : guests) {
    realm.beginTransaction();
    uninvitedGuests.setInvited(true);
    realm.commitTransaction();
}

여러 가지 이유로 이 기능을 추가했는데, 그중 하나는 정밀한 컬렉션 알림을 지원하는데 내부 리팩토링이 필요했기 때문입니다. 또한 RealmResultsRealmList를 온전히 라이브로 만들어서 모든 Realm 클래스가 동일한 의미를 가지게 되면 더 쉽게 이들에 대해 추론하거나 사용법을 문서로 만들 수 있기 위해서입니다. 따라서 과거에는 다소 혼란스러울 수 있었던 Realm 클래스의 라이브 특성을 완벽하게 지원하고 문서로 만들어서 더욱 강력한 API를 사용자에게 제공할 수 있게 되었습니다.

이런 변경 사항이 기존의 코드 베이스에 문제가 될 수 있지만, 간단한 for 루프 내에서 쓰기 트랜잭션을 수행하는 경우에만 영향을 미치며 다른 경우에는 코드가 정상적으로 계속 작동합니다. 이런 변화 방향이 장기적으로 보다 나은 결과로 이어질 수 있을 것으로 기대합니다.

관계 기준 정렬

지금까지는 RealmResults를 직접적인 속성으로만 정렬할 수 있었습니다. 하지만 이번 Realm Java 3.0 릴리즈부터는 다 대 일 관계를 맺고 있는 객체의 속성으로 정렬하도록 쿼리할 수 있습니다.

예를 들어 주인이 키우고 있는 개의 나이로 Person 객체를 정렬하려면 다음과 같이 하면 됩니다.

RealmResults<Person> persons = realm.where(Person.class).findAllSorted(dog.age, Sort.ASCENDING);

또한 지난 릴리즈의 몇몇 버그를 수정했습니다. 전체 변경 사항에 대해서는 changelog를 확인하세요.


3.0 릴리즈 소식을 함께 해주셔서 감사합니다. 이제 Realm을 사용해서 멋진 앱을 만들어 보세요! 언제나 Stack Overflow, GitHub, Facebook page에서 저희를 만날 수 있습니다!

더 읽어보기

Realm + Microsoft: Xamarin, Azure, Windows 데스크탑까지 모두 지원합니다!

by /

Realm의 비전은 훌륭한 앱을 쉽게 개발할 수 있도록 하는 것입니다. 그리고 가능한 한 많은 개발자들이 핵심 기능에 집중할 수 있으면 돕고 싶습니다. 이런 사명으로 오늘 우리는 Microsoft 개발자들이 Realm을 사용해서 확장성이 높고 상용화가 가능한 실시간 애플리케이션을 쉽게 만들 수 있는 제품을 선보입니다. Xamarin에 새로운 Realm 모바일 데이터베이스 기능을 추가했고, Realm 모바일 플랫폼에서 Xamarin을 지원하며, 마침내 Realm 모바일 데이터를 Windows 데스크탑 플랫폼에서 사용할 수 있게 됩니다!

Microsoft의 Xamarin 팀과 함께 만든 Xamarin과 Azure를 사용한 샘플 앱 튜토리얼에서 이 새로운 도구의 강력한 기능을 볼 수 있습니다. Realm과 Microsoft가 어떻게 조화를 이루는지 확인하세요.

Xamarin과 Realm: Realm 모바일 플랫폼 Xamarin 지원 및 새 Realm 모바일 데이터베이스 기능 소개

Realm Xamarin은 온전히 무료이며 오픈 소스인 클라이언트 측 객체 데이터베이스입니다. 최근 몇 개월간 Realm Xamarin에 객체 수준의 속성 알림, 백링크 지원을 위해 테스트를 거듭해온 결과, 오늘 드디어 Realm Xamarin 1.0 정식 버전을 출시했습니다. 521개의 이슈를 발행해주며 문제 파악과 해결에 많은 도움을 주신 개발자 커뮤니티에도 큰 감사를 드립니다.

또한 오늘부터 Realm 모바일 플랫폼에서 Xamarin을 지원합니다. 이제 C# 개발자들은 단지 Realm을 사용하는 앱을 Realm 오브젝트 서버에 연결하는 것만으로 크로스 플랫폼 리액티브 앱을 만들 수 있습니다. Realm 모바일 플랫폼은 단 한 줄의 시리얼라이제이션이나 네트워킹 코드 없이도 충돌 해결, 사용자 인증, 커스텀 권한 등 실시간 기능을 다채롭게 구축하는데 필요한 모든 것을 제공합니다. 또한 클라이언트에서 Realm 모바일 데이터베이스에 데이터를 저장하기 때문에 앱 사용자들은 최상급의 오프라인 경험 역시 누릴 수 있습니다.

이런 기능을 모두 넣으면 어떤 모습이 될까요? 아래 영상에서 확인하세요.

실시간 협업 기능을 지원하는 Draw 앱을 얼마나 쉽게 만들 수 있는지 Microsoft의 Xamarin 팀과 함께 만든 튜토리얼을 확인하세요. 튜토리얼을 따라가면 Azure에 배포된 Realm 오브젝트 서버와 동기화화된 실시간 크로스 플랫폼 앱을 Xamarin에서 빌드하고 사용할 수 있습니다. 또한 2017년 3월 9일에 개최되는 영어 웨비나에 등록하고 실시간으로 따라해볼 수도 있습니다.

Realm 모바일 플랫폼에 익숙한 분이라면 Realm 오브젝트 서버 문서를 통해 클릭 한 번과 코드 몇 줄만으로도 앱을 만들고 동기화할 수 있습니다.

Realm 데이터베이스 Windows 데스크탑 지원

마지막으로 Realm 모바일 데이터베이스가 Windows 데스크탑에서 사용할 수 있게 됩니다. 이제 Win32 API을 지원하는 많은 컴퓨터에서 Realm을 실행할 수 있습니다. 이번 배포를 통해 Windows 데스크탑 애플리케이션에서도 Realm을 사용할 수 있고, Realm 데이터 생성 및 확인을 위한 커스텀 도구 역시 제작할 수 있습니다. 이에 따라 모바일 개발자에게 지원되던 객체 데이터베이스와 Realm API의 혜택을 보다 많은 개발자가 누릴 수 있습니다. 간단하게 스키마를 정의하고 익숙하게 사용해오던 객체를 그대로 사용하기만 하면 됩니다. 쓰기 트랜잭션에 이들 객체를 추가하는 것만으로 ACID를 준수하는 저희 데이터베이스에 데이터가 저장됩니다. 문서에서 설치 방법을 확인하고 오늘 바로 시작해 보세요.

Realm과 Microsoft로 개발 시작하기

많은 개발자들이 사용하는 Microsoft에 새로운 도구를 지원할 수 있어 정말 기쁘고, 여러분이 Realm, Xamarin, Microsoft와 함께 어떤 결과를 만들어낼지 정말 기대됩니다. Realm Xamarin 문서를 참고해서 적용해 보세요. 이 새로운 Microsoft 도구와 기능의 실제 데모를 확인하고 싶은 분은 2017년 3월 9일에 개최되는 영어 웨비나에서 뵙겠습니다!

더 읽어보기

Realm ObjC & Swift 2.4: 객체 알림 기능 추가!

by /

Realm Objective‑CRealm Swift 2.4 버전을 출시합니다. 이번 릴리즈에서 추가된 객체 레벨의 알림으로 저희 라이브 오브젝트에 더 많은 생명을 불어 넣었습니다. 이제 여러분의 앱이 개별 객체가 업데이트될 때마다 쉽게 응답할 수 있습니다.

객체 레벨 알림

지금까지는 객체의 변경을 알고 싶으면 컬렉션에 포함된 객체가 삭제, 삽입, 수정되는 시점을 알려주는 컬렉션의 알림을 이용해야 했습니다. 하지만 어떤 속성이 변경됐는지까지는 알 수 없었죠. 또한 단일 객체를 비동기적으로 관찰하기 위해 컬렉션을 만드는 것은 부자연스럽고 비용도 많이 들며, 쿼리로 쉽게 고유하게 표현할 수 없는 객체인 경우 정의가 어렵기까지 합니다.

우리는 단일 객체의 속성 레벨 변화를 감지하기 위해 KVO를 지원하고 있지만, KVO는 꽤나 지저분하기로 유명하며 한 KVO 알림당 하나의 속성만 지원합니다. 또한 KVO는 크로스 플랫폼이나 크로스 언어가 아닙니다. KVO 알림은 심지어 비동기식 이므로 UI 스레드를 멈추게 하는 경우마저 있죠 🙀.

이번 릴리즈에 제공되는 객체 레벨의 알림은 가장 유용한 방식으로 단일 객체의 변화를 알아차릴 수 있도록 합니다. 객체 알림은 매우 간단한 API로 제공되며, 컬렉션 알림과 마찬가지로 관찰하려는 객체에 알림 블럭을 추가하기만 하면 됩니다. 알림을 생성하면 NotificationToken이 반환하며, 개체에 대한 알림을 사용한만큼 유지해서 사용합니다.

알림이 시작되면 콜백은 정확히 어떤 속성이 변경됐는지 혹은 관찰하던 객체가 삭제됐는지 등의 자세한 정보를 ObjectChange 구조체로 알려줍니다.

class Message: Object {
  dynamic var isRead = false
  dynamic var content = ""
}

class MessageController: UIViewController {
  private let notificationToken: NotificationToken

  init(message: Message) {
    notificationToken = message.addNotificationBlock { change in
      switch change {
      case .change(let properties):
        if let readChange = properties.first(where: { $0.name == "isRead" }) {
          self.showReadBadge = readChange.newValue as! Bool
        }
        if let contentChange = properties.first(where: { $0.name == "content" }) {
          self.contentView.textValue = contentChange.newValue as! String
        }
      case .deleted:
        self.handleDeletion()
      case .error(let error):
        self.handleError(error)
      }
    }
  }

  deinit {
    notificationToken.stop()
  }
}

객체에 대한 알림이 더 필요하지 않은 경우 간단히 token.stop()를 호출하거나 토큰 객체를 해제하세요.

전체 사용 과정을 요약하면, addNotificationBlock으로 관리 객체에 대한 알림을 만들고, 반환된 NotificationToken 인스턴스를 유지한 상태로, 콜백 내부에서 앱에 필요한 모든 업데이트를 처리합니다.

몇 가지 주의 사항이 있습니다. 리스트 속성이 변경된 경우, newValueoldValue 데이터를 볼 수는 없지만 알림은 계속 실행됩니다. 또한 동기적으로 UI 쓰기를 만들어야 하거나 지정된 쓰기에 대한 알림을 무시할 필요가 있다면 realm.commitWrite(withoutNotifying: [token])에 객체의 알림 토큰을 전달해서 interface 구동형 쓰기 기능을 사용할 수 있습니다.

버그 수정

이번 릴리즈에서 동기화 Realm에 대해 만료된 인증 토큰을 업데이트하는 시점의 몇 가지 오류 처리 문제를 수정했습니다.

토큰 만료 이슈를 피하기 위해 모든 Realm 모바일 플랫폼 사용자에게 이번 버전으로의 업데이트를 강력히 추천합니다.

또한 몇 달 동안 발생해오던 “bad transaction log” 예외를 야기하는 버그를 수정했습니다.

Swift 2 지원 중단

레거시 Swift 버전을 지원하는 데에는 많은 노력이 듭니다 😅. Swift 2.x 대의 활성 Realm 빌더가 5% 미만이며 Swift 2.x을 유지하는데 많은 비용이 들기 때문에 이번 버전부터 Swift 2.x 지원이 중단됩니다.

Realm Swift 2.3.0 버전이 Swift 2.x를 지원하는 마지막 버전입니다. 불편을 끼쳐 드려 죄송합니다.

Xcode 8.3 베타 1

최근 Apple은 Xcode 8.3 베타 버전을 발표했습니다. 이번 릴리즈에는 Realm Objective-C의 컴파일 문제를 수정한 변경 사항이 포함됩니다.

다만 아직 Swift 3.1 컴파일 문제는 해결을 위해 노력 중입니다. Xcode 8.3에서 사용하는 Realm Swift 문제에 대한 개선 사항이 궁금하다면 #4586에서 subscribe 버튼을 클릭해 주세요.


읽어 주셔서 감사합니다. Realm과 함께 멋진 앱을 만들어 보세요! Stack Overflow, GitHub, Facebook 그룹에서 언제든지 저희에게 연락할 수 있습니다!

더 읽어보기

Realm 리액트 네이티브 1.0을 소개합니다! 오브젝트 DB와 Realm 모바일 플랫폼을 사용해 보세요.

by /

오늘 리액트 네이티브에 관한 두 가지 사항을 발표합니다. 먼저 거의 1년 동안 오픈 소스 협업을 마친 끝에 강력한 오브젝트 데이터베이스와 훌륭한 반응형 앱의 토대 개발이라는 핵심 마일스톤을 달성하면서 Realm 리액트 네이티브가 1.0에 이르렀습니다. 또한 이제 Realm 모바일 플랫폼이 리액트 네이티브를 지원합니다. 리액트 네이티브 개발자는 몇 줄의 코드만으로 저희 실시간 플랫폼을 사용해서 새로운 개발 경험을 할 수 있습니다.

작년 초 Realm 리액트 네이티브의 베타 버전을 출시하면서 저희는 여러 열성적인 리액트 네이티브 개발자 커뮤니티 및 TaskRabbit 등의 회사에서 많은 정보를 얻었습니다. Realm은 크로스 플랫폼 데이터베이스이므로 더 많은 코드를 재사용하는 앱과, 보다 관리하기 쉽고 견고한 데이터 레이어를 만들 수 있습니다. 또한 Realm의 라이브 오브젝트와 컬렉션 알림을 통해 Realm에서 지원하는 데이터가 업데이트되면 실시간으로 반응할 수 있는 리액티브 앱을 만들 수 있게 합니다. 얼마나 쉽게 시작할 수 있는지 저희 Realm 리액트 네이티브 문서를 확인해 보세요.

또한 Realm은 단순한 클라이언트측 데이터베이스를 넘어섭니다. Realm 리액트 네이티브 1.0의 출시로 리액트 네이티브 개발자는 Realm 모바일 플랫폼 위에 강력하고 새로운 앱을 개발할 수 있습니다. 앱을 Realm 오브젝트 서버에 연결하고 앱에서 동기화된 Realm을 만들면, Realm이 지원하는 객체가 자신의 속성이 변경될 때마다 자동으로 동기화되며, 오프라인 사용을 위해서 로컬에도 저장됩니다. 또한 Realm 모바일 플랫폼은 충돌 해소와 사용자 인증, 사용자 지정 권한을 위한 도구도 제공하므로 강력하고 협업 가능한 환경을 구축하는데 필요한 모든 것을 갖추고 있습니다.

이에 더해 프로페셔널과 엔터프라이즈 에디션은 이벤트 핸들링 기능도 지원하므로 서버측 JavaScript 코드를 반응형으로 만들 수 있습니다. 이제 언제 어디서나 사용자 데이터가 변경될 때 앱이 응답하도록 전체 코드 베이스에 반응형 원리를 적용할 수 있습니다.

리액트 네이티브 앱은 Realm 모바일 플랫폼에 쉽게 통합할 수 있습니다. 사용자를 인증하고 Realm 오브젝트 서버에 연결한 후 앱의 UI를 아래 코드처럼 반응형으로 업데이트합니다.


import React, { Component } from 'react';
import { Text } from 'react-native';
import Realm from 'realm';
import { ListView } from 'realm/react-native';

export default class DogsView extends Component {
    constructor(props) {
        super(props);
        // 빈 데이터 소스로 구성요소를 초기화합니다
        const ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
        this.state = { dataSource: ds };
    }

    componentWillMount() {
        // `this.props`은 DogsView 인스턴스에 넘길 사용자이름과 비밀번호를 담습니다
        Realm.Sync.User.login('https://my-realm-server.com', this.props.username, this.props.password, (error, user) => {
            let realm = new Realm({
                schema: [ { name: 'Dog', properties: { name: 'string' } } ],
                sync: { user, url: 'realms://my-realm-server.com/~/dogs'}
            });
            // 사용자가 로그인하고 동기화된 realm이 있으면 realm 내의 모든 Dog 객체를 사용해서
            // DataSource를 재설정하고, Dogs 컬렉션의 변경 사항을 구독해서 변경시 UI를 새로 고칩니다.
			const dogs = realm.objects('Dog');
            this.setState({ realm, dataSource: this.state.dataSource.cloneWithRows(dogs) });
			dogs.addListener(() => this.forceUpdate());
        });
    }

    render() {
        return (<ListView dataSource={this.state.dataSource} renderRow={(item) => <Text>{item.name}</Text>} />);
    }
}

Realm 모바일 플랫폼을 시작하고 싶다면 문서에서 상세한 설명을 볼 수 있습니다. Realm 리액트 네이티브와 함께 온라인과 오프라인에 관계없이 모든 기기에서 사용자가 좋아할 기능을 가진 앱을 개발해 보세요!

더 읽어보기

Realm의 경험을 함께 나누는 Realm 월드 투어 서울&부산에 초대합니다!

by /

이제 Realm 개발자들이 여러분을 만나러 갑니다. Realm 모바일 플랫폼 1.0 출시를 기념하며, 3개의 대륙을 누비며 세계 각국의 20개 이상의 도시에서 실시간으로 Realm 플랫폼을 전달하기 위해 저희 최고의 제품 엔지니어들이 이벤트를 진행합니다. Realm 최초의 Realm 월드 투어를 놓치지 마시고, 여러분의 경험을 공유해 주세요!

각 도시의 개발자 커뮤니티와 연락하고, 현지 호스트의 도움을 받아 모임 참석자들을 위한 잊지 못할 시간을 계획했습니다. 이벤트는 모두 Realm의 제품 엔지니어에 의해 진행되며, 오픈소스 Realm 데이터베이스와 Realm 모바일 플랫폼 무료 개발자 에디션에 대한 소개와 함께 심화 기능에 대한 논의가 진행될 예정입니다. 샘플 코드와 실제 사용할 수 있는 데모, 기술 Q&A 세션도 포함됩니다. 일대일로 대면해서 말할 기회와 모범 사례를 공유하고, 개발자 서로에게 배울 수 있는 충분한 시간을 함께 할 예정입니다.

Realm 월드 투어 이벤트는 무료이지만, 참석자 수가 제한돼 있으니 서두르세요. 서울부산의 모임은 온오프믹스에서 신청할 수 있으며, Realm 월드 투어가 어느 도시에서 개최되는지는 공식 페이지에서 볼 수 있습니다.

  • 시간: 3월 8일 (수) 19시 00분 ~ 21시 30분
  • 장소: 서울 강남구 역삼동 D2 STARTUP FACTORY 강남 메리츠타워 16층
  • 시간: 3월 3일 (금) 19시 00분 ~ 21시 30분
  • 장소: 부산 해운대구 우동 부산광역시 해운대구 센텀2로 25 센텀드림월드 15층 트리노드
더 읽어보기

막강한 기능의 Realm 모바일 플랫폼 1.0 버전을 공개합니다!

by /

오늘 Realm 모바일 플랫폼 1.0을 런칭하며, 소규모에서 대규모까지 다양한 용도에서의 제품 사용을 지원할 수 있다는 소식을 여러분께 전해드릴 수 있어 정말 기쁩니다. 우리는 지난 몇 달 동안 심혈을 기울여 버그를 수정하고 제품 완성도를 높이며 코드를 강화하였고, 뒤이어 소개드릴 여러 가지 새 기능을 추가했습니다. 1.0 버전 완성은 Realm의 모든 임직원에게 정말 크나큰 목표였으며, 베타 기간 내내 많은 의견으로 도움을 주신 고객들과 커뮤니티 회원들께 진심으로 감사드립니다!

Realm 모바일 플랫폼을 사용하면 실시간 협업, 라이브 메시징, 강력한 오프라인 우선 경험 등과 같은 정교한 기능을 갖춘 응용 프로그램을 보다 쉽게 만들 수 있습니다. 본 플랫폼은 iOS와 안드로이드에서 각광받는 Realm의 클라이언트단 데이터베이스와 Realm 오브젝트 서버를 연동해서 실시간 데이터 동기화를 자동으로 제공합니다. Realm이 동기화를 처리하므로 개발자는 네트워킹 코드를 작성하거나 유지할 필요가 없으며, 시리얼라이제이션도 할 필요가 없으며, 디바이스의 데이터가 항상 서버의 데이터와 동기화될 것을 신뢰할 수 있습니다. Realm을 사용하면 데이터의 변화에 즉각적으로 반응할 서버사이드의 로직을 아주 쉽게 작성할 수 있으며 기존 시스템이나 API와 간단하게 통합할 수 있습니다.

이번 배포로 저희 플랫폼의 세 버전 모두 사용할 수 있으며, 바로 시험해볼 수 있도록 몇 가지 재밌는 데모 코드를 함께 공개합니다. 아래 내용에서 자세한 내용을 읽으시거나, 바로 데모를 받아보고 싶다면 Mac이나 Linux를 위한 무료 개발자 에디션과 Draw 데모 앱을 다운로드해서 경험해 보세요. 하단의 영상에서 Realm이 Draw 앱을 동작시키는 방법을 볼 수 있습니다.

엔터프라이즈에 추가된 기능 세 가지

이번 배포에서는 엔터프라이즈 에디션에 새로운 기능이 세 가지 추가됩니다.

데이터 통합 API

새 데이터 통합 API를 통해 Realm 모바일 플랫폼을 모든 데이터 소스와 쉽게 통합할 수 있으므로 Realm을 사용해서 실시간 앱과 앱 기능을 기존 데이터와 서비스에 쉽게 연동할 수 있습니다. 많은 베타 사용자들이 이 새로운 Realm 기능을 통해 레거시 시스템을 “모바일화”했으며, 안드로이드와 iOS 팀이 현대적인 리액티브 앱을 만들고 데이터와 로직을 기존 저장 시스템과 연결하기 위해 Realm을 실시간 브릿지로 사용했습니다.

새로운 모바일 쇼핑 경험을 제공하기 위해 기존 결제 거래 데이터베이스에 매끄럽게 연결될 수 있는 새 앱을 필요로 하는 소매 업체를 예로 들어 보겠습니다. Realm의 데이터 통합 API를 활용하면 오브젝트 서버와 지불 트랜잭션 데이터베이스가 같은 데이터로 동기화되도록 하는 Realm 오브젝트 서버를 기존 데이터베이스와 안정적으로 연결할 수 있습니다. 모든 위치에서 데이터의 정확성을 보장하기 위해 Realm API는 끊어진 연결을 이해하고 중단된 트랜잭션을 재시작하도록 설계되었습니다. 이런 보장을 통해 Realm 오브젝트 서버는 클라이언트단 데이터베이스와 결제 트랜잭션 데이터베이스 사이의 미들웨어로 작동할 수 있으며, 소매 업체는 새로운 프로젝트를 위해 Realm에서 기존 데이터베이스 자원을 활용할 수 있습니다.

데이터 통합 API를 사용하면 사용자 정의 커넥터를 쉽게 만들 수 있으며, 오늘 발표되는 PostgreSQL을 위한 첫 번째 사전 빌드 커넥터도 사용할 수 있습니다. 고객 요청에 따라 다른 커넥터 역시 작업 중으로, Oracle, MongoDB, Hadoop, SAP HANA, Redis를 위한 사전 빌드 커넥터를 출시할 예정입니다.

수평 확장성

Realm 플랫폼은 매우 견고하게 만들어졌으며, 단일 Realm 오브젝트 서버는 실행하는 앱과 하드웨어에 따라 만 명 이상의 동시 사용자를 처리할 수 있습니다. 여기에 더해 고객에게 대규모 확장 기능을 제공하기 위해 엔터프라이즈 에디션에 수평 확장성을 추가했습니다. 함께 제공되는 로드 밸런서는 자동으로 배포 연결을 처리합니다. 이런 기능 덕분에 다수의 Realm 오브젝트 서버 인스턴스를 병렬로 배포할 수 있으며, 여러분의 앱은 백만 명 이상의 동시 사용자를 실시간으로 지원할 수 있습니다.

지속적인 백업

지속적인 백업 기능으로 여러분의 Realm 오브젝트 서버 데이터를 보조 서버에 자동으로 백업할 수 있습니다. 정전, 하드웨어 장애, 자연 자해 등의 재해가 발생한 경우 보조 서버로 앱의 오퍼레이션을 지속할 수 있습니다. 재해에서 서버를 안전하게 복구할 수 있도록 다른 지역에 백업 서버를 구성하는 것도 가능합니다.

엔터프라이즈 에디션의 새로운 기능

Realm과 Draw 데모 앱 시작하기

가장 먼저 할 일은 여러분의 컴퓨터나 원하는 클라우스 서비스에 Realm 플랫폼을 설치하는 것입니다. 이벤트 처리 등 다른 프로페셔널 에디션 기능에 관심이 없다면, 강력한 기능을 지녔지만 무료이고 평생 실제 상용 앱에 제약없이 사용 가능한 개발자 에디션으로 시작하는 것이 좋습니다. 라이센스 조항을 확인하세요.) 개발 문서에서 상세한 설치 방법을 볼 수 있습니다.

Realm을 설치했다면 이제 예제 코드를 돌릴 수 있습니다. Draw는 화이트보드 협업 앱으로, 여러 사용자간에 실시간 데이터 동기화를 처리하는 Realm을 보여줍니다. 오픈소스로 GitHub의 Realm 데모들처럼 사용할 수 있습니다. 영상에서는 인터넷이 잠시 끊겼을 때의 시나리오를 포함해서 두 개의 iPad간에 실시간 데이터 동기화를 하는 모습을 볼 수 있습니다.

더 알아보기

Realm 모바일 플랫폼에 대한 자세한 내용이 궁금하거나 질문 사항이 있다면 웨비나에 등록하고 제품 팀이 2017년 1월 31일에 강연하는 실시간 기술 세션에 참가하세요. (영어로 진행됩니다.)

더 읽어보기

Realm Objective-C와 Swift 2.2 버전의 신기능, 스레드 간 객체 전달과 관계 정렬 기능 추가

by /

Realm의 초창기 목표는 일관성있고 간단한 스레딩 모델을 만드는 것이었습니다. 오늘 저희는 스레드에서 스레드로 안전하게 객체를 전달할 수 있는 구조를 도입하여 스레딩 모델을 개선한 Realm Objective‑CRealm Swift 2.2 버전을 배포합니다. 관계 프로퍼티로 정렬할 수 있는 기능과 동기화 개선, 버그 픽스도 포함됩니다.

스레드 이슈

Realm을 사용하면 멀티 스레드에서 객체를 쉽고 안전하게 사용할 수 있습니다. 다년간의 꾸준한 연구와 신중한 설계 결정으로 어려운 스레딩 문제를 해결하고 기존 버전의 멀티 스레딩 지원 기능이 가능하게 됐습니다.

기존의 영문 기사, Threading Deep Dive에서는 사용자가 락이나 자원 조정을 고민하지 않도록 Realm이 동시성을 안전하게 처리하는 다양한 원리에 대해 전체 Realm에서 제공하는 동시성있는 뷰와 객체 그래프를 통해 설명했습니다. 주목할 것은 이 디자인 구조로 다른 ORM이나 데이터 프레임워크에서 나타나는 ‘오류’(fault)💥라는 개념을 해결했다는 점입니다.

동시 환경에서 Realm을 제대로 사용하는 방법을 깊게 이해하려면 저희 공식 문서의 Threading 항목을 꼭 참고해 주세요. 이 리소스를 사용하면 멀티 스레딩과 Realm을 정말로 효율적으로 사용할 수 있습니다. 하지만 이번 배포 전까지는 사용하는 객체가 스레드를 넘지 못했었죠.

스레드 국한

Realm이 그렇게 안전한 스레드 사용이 가능하다면, 왜 스레드 간에 객체를 넘기려고 할 때 예외가 발생하나요?!

Realm의 일관성과 안전성을 보장하기 위해서는 간단한 제약이 부과됩니다. 모든 Realm과 객체, 탐색 결과, 리스트는 작성한 스레드로 제한된다는 것이었죠.

스레드 국한은 정확한 코드를 쉽게 작성하기 위한 디자인의 핵심 부분이며, Realm의 내부에 따른 임시 제한이나 인공적인 제약이 아닙니다.

사실, Realm 객체를 스레드 간에 자유롭게 전달할 수 있도록 구현하는 것은 아주 쉽지만, 사용하기 매우 위험하고 예측이 어렵다는 단점이 있습니다.

Realm은 앱에서 디스크에 부분적으로만 유효한 데이터를 쓰지 않고도 쓰기 도중에 크래시가 발생하는 것을 허용하는 트랜젝션 데이터베이스입니다. write transaction 범위를 생각하면 이해가 쉽습니다.

ACID 중의 isolation, 즉 고립성을 보장하려면 한 트랜젝션에서의 변화가 최신 버전으로 진행될 때까지 다른 트랜젝션에 영향을 미치지 않아야 합니다. 그렇지 않으면 Realm에서 없애둔 ‘오류’(fault)가 발생할 수 있습니다.

이런 고립성을 위해 Realm들을 만든 스레드 안에서의 Realm들은 동일한 버전입니다. 내부적으로는 스레드 당 단 하나의 Realm이 있게 됩니다. Realm이나 Realm의 객체, 쿼리 등을 스레드 간에 자유롭게 교환하는 것은 데이터베이스의 다른 버전을 섞는 것이 되고, 이는 심각한 결과로 이어질 수 있습니다. 예를 들어 객체를 삭제한 스레드에 객체를 전달하면 크래시가 일어날 수도 있고, 스레드 경계를 넘어갈 때 값이 변경될 수도 있으며, 객체 그래프가 각 트랜젝션 버전마다 다른 관계를 가지게 될 수도 있습니다.

스레드 간 데이터를 전달하는 기존 방법

지금까지는 스레드 간에 데이터를 전달하기 위해서 Realm이 지원하지 않는 데이터를 전달해야 했습니다.

주로 관리되지 않는 Realm 객체의 인스턴스를 넘기거나 기본 키 등 Realm이 지원하는 속성을 통해 데이터를 읽는 방법을 사용했죠.

let realm = try! Realm()
let person = Person(name: "Jane", primaryKey: 123)
let pk = person.primaryKey
try! realm.write {
  realm.add(person)
}
DispatchQueue(label: "com.example.myApp.bg").async {
  let realm = try! Realm()
  guard let person = realm.object(ofType: Person.self,
                                  forPrimaryKey: pk) else {
    return // person was deleted
  }
  try! realm.write {
    person.name = "Jane Doe"
  }
}

그러나 객체에 기본 키가 없는 경우 이 방법을 사용할 수 없고, 부실한 데이터를 작업하는 결과가 될 수 있습니다. List, Results, LinkingObjects 등 Realm 객체가 아닌 것을 전달하는 것도 이 접근법으로는 쉽지 않습니다.

스레드 사용이 안전한 참조 사용

이 번 배포부터는 Realm에서 한 스레드로만 국한되던 모든 타입들에 안전한 스레드 사용이 안전한 참조를 만들어서, 간단한 3단계 과정만으로 스레드 간에 객체들을 넘길 수 있습니다.

  1. ThreadSafeReference를 스레드 국한 객체로 초기화
  2. 원하는 스레드나 큐로 ThreadSafeReference 전달
  3. Realm.resolve(_:) 호출로 해당 참조를 원하는 목적지 Realm에서 푼 후, 반환 객체를 기존처럼 사용

아래 예문을 보시죠.

let realm = try! Realm()
let person = Person(name: "Jane") // no primary key required
try! realm.write {
  realm.add(person)
}
let personRef = ThreadSafeReference(to: person)
DispatchQueue(label: "com.example.myApp.bg").async {
  let realm = try! Realm()
  guard let person = realm.resolve(personRef) else {
    return // person was deleted
  }
  try! realm.write {
    person.name = "Jane Doe"
  }
}

실 사용예 🌏

RealmTasks가 오픈 소스이므로 기존 스레드 전달 코드에서 안전한 스레드 사용이 가능한 참조로 바뀐 코드를 다음 GitHub iOS PR #374에서 볼 수 있습니다.

관련 코드는 아래와 같으며, List 프로퍼티를 자동으로 중복 제거하고 백그라운드 스레드에서 쓰기 트랜젝션을 수행합니다.

realm.addNotificationBlock { _, realm in
  let items = realm.objects(TaskListList.self).first!.items
  guard items.count > 1 && !realm.isInWriteTransaction else { return }
  let itemsReference = ThreadSafeReference(to: items)
  DispatchQueue(label: "io.realm.RealmTasks.bg").async {
    let realm = try! Realm()
    guard let items = realm.resolve(itemsReference), items.count > 1 else {
      return
    }
    realm.beginWrite()
    let listReferenceIDs = NSCountedSet(array: items.map { $0.id })
    for id in listReferenceIDs where listReferenceIDs.count(for: id) > 1 {
      let id = id as! String
      let indexesToRemove = items.enumerated().flatMap { index, element in
        return element.id == id ? index : nil
      }
      indexesToRemove.dropFirst().reversed().forEach(items.remove(objectAtIndex:))
    }
    try! realm.commitWrite()
  }
}

관계 프로퍼티 정렬

지금까지는 자신이 가진 프로퍼티로만 Realm 컬렉션을 정렬할 수 있었습니다.

Realm 2.2 버전부터는 객체와 1 대 1 혹은 다 대 1 관계(to-one relationships)를 가지는 다른 객체의 속성으로 컬렉션을 정렬할 수 있습니다.

예를 들어, Person을 자신이 가진 dog 프로퍼티의 age 값으로 정렬하려면 dogOwners.sorted(byKeyPath: "dog.age")와 같이 호출하면 됩니다.

class Person: Object {
  dynamic var name = ""
  dynamic var dog: Dog?
}
class Dog: Object {
  dynamic var name = ""
  dynamic var age = 0
}

realm.beginWrite()

let lucy = realm.create(Dog.self, value: ["Lucy", 7])
let freyja = realm.create(Dog.self, value: ["Freyja", 6])
let ziggy = realm.create(Dog.self, value: ["Ziggy", 9])

let mark = realm.create(Person.self, value: ["Mark", freyja])
let diane = realm.create(Person.self, value: ["Diane", lucy])
let hannah = realm.create(Person.self, value: ["Hannah"])
let don = realm.create(Person.self, value: ["Don", ziggy])
let diane_sr = realm.create(Person.self, value: ["Diane Sr", ziggy])

let dogOwners = realm.objects(Person.self)
print(dogOwners.sorted(byKeyPath: "dog.age").map({ $0.name }))
// Prints: ["Mark", "Diane", "Don", "Diane Sr", "Hannah"]

이전 Realm 버전에서 이렇게 정렬하려면 dog.age 속성을 Person 객체에 저장하거나, Results의 장점을 포기하고 Realm 바깥에서 정렬할 수밖에 없었죠.

API 관점에서의 변화 사항을 하나 알려드립니다. 앞으로는 ‘properties’ 대신 보다 일반적인 ‘key paths’ 용어를 사용할 예정입니다.

  • 다음 Objective-C API는 이후 버전에서 더 이상 사용되지 않습니다.
Deprecated API New API
-[RLMArray sortedResultsUsingProperty:] -[RLMArray sortedResultsUsingKeyPath:]
-[RLMCollection sortedResultsUsingProperty:] -[RLMCollection sortedResultsUsingKeyPath:]
-[RLMResults sortedResultsUsingProperty:] -[RLMResults sortedResultsUsingKeyPath:]
+[RLMSortDescriptor sortDescriptorWithProperty:​ascending] +[RLMSortDescriptor sortDescriptorWithKeyPath:​ascending:]
RLMSortDescriptor​.property RLMSortDescriptor​.keyPath
  • 다음 Swift API는 이후 버전에서 더 이상 사용되지 않습니다.
Deprecated API New API
LinkingObjects​.sorted(byProperty:​ascending:) LinkingObjects​.sorted(byKeyPath:​ascending:)
List.sorted(byProperty:​ascending:) List.sorted(byKeyPath:​ascending:)
RealmCollection.sorted(byProperty:​ascending:) RealmCollection.sorted(byKeyPath:​ascending:)
Results.sorted(byProperty:​ascending:) Results.sorted(byKeyPath:​ascending:)
SortDescriptor(property:​ascending:) SortDescriptor(keyPath:​ascending:)
SortDescriptor​.property SortDescriptor​.keyPath

단, Realm 버전이 3.x에 도달할 때까지는 SemVer에 따라 이들 사용되지 않는 메서드는 계속 지원될 예정입니다.

다른 변경 사항

동기화 변경 사항 (Beta)

  • 기본 동기화 엔진이 BETA-6.5 버전으로 업그레이드됐습니다.
  • 동기화 관련 에러 리포팅 동작이 변경됐습니다. 특정 사용자나 세션에 관련이 없는 오류는 기본 동기화 엔진이 ‘치명적’(fatal)으로 분류한 경우에만 보고됩니다.

버그 픽스

  • 마지막으로 Realm 0.x로 액세스한 파일에서 1.x로 옮기거나, 1.x에서 2.x로 옮기는 경우와 같이 파일 형식 마이그레이션이 필요한 경우 deleteRealmIfMigrationNeeded를 설정하면 Realm까지 삭제됩니다.
  • 중첩 SUBQUERY 표현식을 포함한 쿼리가 수정됐습니다.
  • 이전 스레드의 RLMRealm 인스턴스가 여전히 존재하는 동안 스레드 ID가 재사용될 때 발생하던 잘못된 스레드 예외를 수정했습니다.

레거시 Swift 버전 지원

가능한 Xcode 7.3.1과 Swift 2.x를 계속 지원할 예정이지만, 조속히 모든 사용자가 Swift 3으로 마이그레이션하기를 권장합니다.


읽어 주셔서 감사합니다. 이제 Realm과 함께 멋진 앱을 만들어 보세요! Stack Overflow, GitHub, Twitter에서 저희를 만날 수 있습니다.

더 읽어보기

Realm 모바일 플랫폼을 소개합니다.

by /

 

소개 (0:00)

Realm에 관심을 가진 분이라면 Realm 모바일 플랫폼이 등장할 것이라는 생각을 하셨을지도 모릅니다. Realm 모바일 플랫폼은 이 년 이상 진행돼온 프로젝트로, 상용화하기 위해 많은 연구를 거쳐 왔습니다.

Realm의 한결같은 목표는 보다 나은 앱을 개발하도록 돕는데 있습니다. 즉, 구현하기 까다로운 멋진 라이브 기능과 상호작용 기능을 가진 앱을 보다 쉽고 빠르게 구현할 수 있도록 하는 것입니다.

introducing-RMP-introduction

Realm 모바일 데이터베이스 (0:58)

Realm의 역사는 꽤 길고, 현재까지 좋은 성과를 거두고 있습니다. 샌프란시스코와 코펜하겐에 오피스가 있고, 현재 60명 정도의 직원을 보유하고 있습니다. 하지만 시작 시점에는 지금과 달랐습니다. 사실 Realm은 저와 제 공동 창립자가 덴마크에 앉아서 모바일 데이터베이스를 만들어보고 싶다는 생각을 한 것에서부터 시작됐습니다.

그래서 Y Combinator에 지원했습니다. 누군가는 Y Combinator에 지원하려면 주요 인물들과 인맥이 닿아 있어야 하고 특정 조건에 맞아야한다는 식의 말을 하지만, 사실 저희는 저 멀리 덴마크에 있던 단지 두 사람이었을 뿐이었죠. 인맥도 없었고, 우리의 기술과 Nokia에서 모바일 관련 일을 했다는 이력을 빼고는 아무런 자격도 없었습니다. 정말 아무 것도 아닌 순진한 사람들이었죠.

어쨌거나 우리는 지원 동영상을 보냈고, 놀랍게도 잘 받아들여졌습니다. 오늘날까지 이르는데는 많은 이야기가 있지만, 열심히 노력했고 모든 것을 준비해서 운영했습니다. 우리가 하고자한 일의 핵심이 되는 모바일 데이터베이스의 개발을 시작했고 결국 완성해냈습니다.

개발을 시작하면서 이 작업이 얼마나 걸릴지 생각해봤는데, 이 분야에서 많은 경험이 있었으므로 팔 수 있을만한 제품을 만드는데 한 반 년 정도 걸릴 거라고 예상했습니다. 그러나 몇 년이 흐른 후에야 드디어 좋은 제품을 만들어낼 수 있었습니다. 회사 설립 후 거의 3년이 지난 2014년에 처음 제품을 런칭했죠. 내장형 데이터베이스를 좋은 퀄리티로 만드는 것은 오랜 시간이 걸리더군요. 사실 이 기간을 예측 못했기 때문에 용감하게 시작할 수 있었던 것 같습니다. 결과물은 보시다시피 아주 멋집니다.

이제 우리는 이 기술을 흡족하게 개발해서 온전히 오픈소스로 공개했습니다. 처음 개발을 시작할 때 약속했던 바대로의 오픈소스인 이 제품을 가지고 여러분이 원하는 것은 무엇이든 할 수 있습니다. 세상에 기여를 하는 것은 언제나 즐거운 일입니다.

제게 가장 만족하는 것은 사람들의 애정어린 반응입니다. Realm이 얼마나 멋진지 경험한 사람들이 수많은 트윗과 피드백으로 우리 제품에 대해 말하고 있습니다. 거의 모든 곳에서 사용되고 있으며, 행복하게도 많은 앱을 개선하는데 도움이 됐습니다.

introducing-RMP-apps

Realm 모바일 플랫폼 (5:04)

Realm 모바일 데이터베이스를 배포한 후 다음 단계로 들어설 필요가 생겼습니다. 멋진 데이터베이스를 만들고 모두에게 무료로 나눠주는 것은 좋은 일이지만 이것만으로 지속 가능한 회사를 만들기는 어렵죠. 그래서 Realm 모바일 플랫폼을 만들었습니다.

많은 사람들이 잘 알지 못하지만, 사실 원래 Realm은 제 회사에서 텍스트 에디터를 만들었던 경험에서 영감을 얻었습니다. 아직 git이 개발되지 않은 때였지만 git이 빌트인된 협업 가능한 텍스트 에디터였고, 여기 실시간 협업 기능을 넣고 싶었습니다. 하지만 어떤 데이터베이스도 제가 원하는 실시간 협업 기능을 지원할만큼 빠르지 않았고, 결국 스스로 만들기로 마음먹었습니다. 사람들이 실시간으로 데이터를 공유할 수 있는 이상적인 데이터베이스를 만들자는 아이디어로 개발을 시작했죠. 실제로 개발이 상당히 오래 걸렸는데, 이런 데이터베이스를 최초로 만들어내야했기 때문입니다.

동기화에 대한 요청을 상당히 많이 받았고 언제 이 기능이 가능한지 궁금해하는 사람들이 많았습니다. 최근의 사용자는 업데이트가 가능하고 모든 것이 반응형으로 잘 동작하는 실시간 기능에 대한 요구가 높습니다. 하지만 앱에서 실시간 동기화 기능을 구현하는 것은 쉬운 일이 아닙니다. UI를 직접 데이터에 연결할 수 있어야 하고 업데이트도 돼야 하죠. 우리 플랫폼을 사용한다면 거의 코드를 적지 않고도 이런 기능을 아주 쉽게 사용할 수 있습니다.

모든 객체를 만들고 UI에 연결하면 작동하는 반응형 설정을 원하시나요? 제 원래 비전에 따르면 여기에 협업 기능도 더해집니다. 모든 사람들이 스마트기기를 갖고 있으니, 같이 협업할 수 있도록 돕고 싶습니다. 모든 앱은 협업이 가능해야 합니다. 사람들이 단순히 고양이 사진만을 공유할 수 있도록 하는 것만이 아니라, 사람들이 뭔가 만들고 할 수 있도록 돕고 싶습니다. 온라인과 오프라인에 관계없이 유연하고 매끄러운 경험을 할 수 있길 바랍니다. 이것이 저희의 비전이자, 사용자들이 바라는 것입니다.

Realm 모바일 플랫폼은 데이터베이스와 대응관계에 있습니다. 왜냐면 실제 데이터베이스가 기기에 있으면 실제로 오프라인으로만 사용할 수 있기 때문입니다. 아니면 데이터베이스 로딩에 실패하고 사용자 경험이 저하되겠죠. 데이터베이스가 단지 웹페이지라면 이 문제가 해결됩니다. 디스크에 있는 파일 경로로 데이터베이스를 여는 대신 URL로 열면 되죠. shared Realm을 하나, 혹은 열개, 몇 백개라도 열 수 있습니다. 같은 URL을 연 사람이라면 같은 시간에 같은 데이터를 실시간으로 얻게 되죠. 간단한 컨셉이지만 실제로 작업해보면 놀라운 효과를 냅니다.

핵심 아이디어는 Realm 데이터베이스가 실제 오브젝트 데이터베이스이므로 본래 오프라인 퍼스트라는데서 나옵니다. 즉, 일관성없는 데이터를 앞 뒤로 복사하는 OM 레이어를 가진 SQL 데이터베이스가 아닙니다. Realm 모바일 데이터베이스는 관계형의 실제 데이터베이스이므로 모든 것에 대한 링크를 가질 수 있습니다. 또 반응형 작업을 할 수 있는 체인 노티피케이션도 있습니다. 이제 네트워크 처리를 완전히 추상화 할 수 있습니다. 네트워킹을 고려하지 않고도 URL의 Realm을 열 수 있으며, 같은 Realm을 연 사람들에게 자연스럽게 동기화됩니다.

introducing-RMP-object-server

데이터베이스와 네트워크 양 측에서 여러분이 정말 필요로 하는 다른 멋진 기능으로는 암호화가 있습니다. 실시간 동기화를 수행하고 이벤트 핸들링 기능이 있으므로 서버에서 코드를 실행한 후 변경 사항을 바로 확인할 수 있습니다.

물론 진정한 핵심은 자동 충돌 해소에 있습니다. 즉, 변경 사항을 조정할 수 있다는 점입니다. 수동으로 충돌 해소를 하지 않고 자동으로 해야 하는 이유는 뭘까요? 수동으로 처리할 경우 작업이 멈출 수밖에 없으므로 절대로 실시간이 될 수 없기 때문입니다. 실시간 속도로 작업을 하고 싶다면 자동이어야 합니다.

실제로 사용 중에도 스키마를 변경할 수 있고, 디바이스에 데이터를 넣을 수 있으며, 이벤트 프레임을 사용해서 현존하는 인프라스트럭처에 도입할 수도 있습니다. 이 디바이스들이 모두 서버에 연결돼 있다고 가정해 볼까요?

서버는 자동 충돌 해소가 동작하도록 하는 동기화 엔진을 갖고 있습니다. 또한 서버에서 코드를 돌릴 수 있는 이벤트 프레임워크도 있죠. 당연히 대시보드가 있어서 모든 상황을 확인할 수 있습니다. 인증, 엑세스 컨트롤과 Realm도 있습니다. 각각의 디바이스는 고유한 Realm을 갖고 있으며, 모든 기기간에 공유되는 Realm도 있습니다. 원하는 수만큼 Realm을 가질 수 있죠. 스케일 업이 가능하므로 백만 개 넘게도 만들 수 있어서 단지 이들 사이에 데이터를 퍼뜨리기만 하면 됩니다. 또한 다른 서버에 연결할 수도 있으므로 백엔드 데이터베이스나 API가 있다면 이들에 연결하는 커넥터를 만들어서 사용하는 인프라스트럭쳐에 통합할 수도 있습니다.

introducing-RMP-how-it-works

라이브 오브젝트 (11:09)

이 모든 것을 가능하게 하는 핵심 아이디어는 모든 것이 객체라는 것입니다. 또한 이들 객체는 라이브 오브젝트이죠. Realm을 이미 사용하는 분이라면 멀티 스레드를 생각하면 이해가 쉬울 겁니다. 다수의 스레드에서 Realm을 변경하더라도 안전하게 사용할 수 있고, 다른 스레드에서도 그 변화 상황이 반영됩니다. 여기서 한 걸음 더 나아가서 네트워크에서도 마찬가지로 동작하게 했습니다. 다수의 디바이스에서 객체를 업데이트하더라도 항상 같은 객체일 수 있죠. 이런 변화하는 객체를 라이브 오브젝트라고 합니다. 객체가 바로 데이터 모델이므로 이를 통해 사람이 쉽게 생각할 수 있는 모델이 됩니다. 따라서 앱을 개발하거나 유지하는게 훨씬 쉬워지죠. 즉 평소에 사용하는 것과 정확히 동일한 문법으로 객체를 정의할 수 있습니다.

이런 객체는 다른 일반 객체들처럼 만들어지지만 갑자기 많은 힘을 갖게 됩니다. 트랜잭션을 하거나 쿼리를 할 수 있고 저장도 할 수 있는 이 모든 기능들이 무료로 제공됩니다. 원할히 작동하는 기능들을 가지며, 데이터베이스이자 옵저버블입니다. 앱을 개발하면서 원하는 것은 무엇이든 만들 수 있습니다!

introducing-RMP-features

Realm 모바일 플랫폼이 드디어 사용 가능합니다. 여기서 다운로드할 수 있습니다. 개발자들에게는 완전히 무료고, 고객의 하드웨어에서 운영할 수 있으며, 원하는 것은 무엇이든 개발할 수 있습니다.

상업용 제품도 있습니다. 기업의 요구에 맞춰 고객 백엔드에 보다 통합적이고 서버 사이드를 더 많이 핸들링할 수 있는 기능이 추가되며 인증을 커스터마이즈할 수 있습니다. 하지만 무료 버전도 여전히 강력합니다. 아무 제약 없이 전체 앱을 개발할 수 있으며, 어떤 개발에도, 원하는 만큼 많이, 오랫동안 사용할 수 있습니다.

더 읽어보기

모바일 앱을 위한 리액티브 플랫폼: Realm 프로페셔널 버전

by /

Realm의 목표는 개발자들이 더 나은 앱을 쉽고 빠르게 개발할 수 있도록 하는 것 입니다. 라이브 객체를 사용하는 네이티브 앱을 개발자들이 쉽게 개발하고, 실시간 데이터 동기화를 쉽게 구현할 수 있으며, 데이터 변화에 따라 서버 사이드 로직을 쉽게 동작시키고, 복잡한 기능들이 서로 연동이 가능하게 모바일 인터넷을 위한 더 강력한 데이터 계층을 만드는 것이 우리의 목표입니다. 이를 이루기 위해 Realm 모바일 플랫폼의 구성요소와 특성들도 Realm 모바일 데이터베이스처럼 꾸준히 열심히 개발해왔습니다.

개발자분들을 위한 두 뉴스가 있습니다. 이를 통해 더 많은 개발자들이 Realm을 쉽고 빠르게 앱에 적용할 수 있게될 것입니다. 먼저, 오늘 Realm 모바일 플랫폼의 프로페셔녈 버전을 새롭게 선보입니다. 이 제품은 Realm 플랫폼의 장점과 새로운 가격을 가지고 큰 규모의 개발자들인 여러 분들을 찾아갑니다. 또한, IBM과 협력의 결과를 보여주게 되었습니다. 스캐너앱은 프로페셔녈 버전을 위한 멋지고 새로운 데모 앱입니다. Realm과 IBM 왓슨을 통합하여 복잡한 이미지 처리를 포함하는 반응형 앱을 만들기 위한 오픈소스 템플릿을 개발자들에게 제공해줍니다.

Realm 모바일 플랫폼 프로페셔녈 버전

프로페셔녈 버전은 중간 크기의 앱과 사업들을 위한 Realm 모바일 플랫폼의 새 버전입니다. 이는 자동 실시간 데이터 동기화 등의 무료 개발자 판의 특성 이외에도 이벤트 핸들링과 서버 사이드 데이터 접근 등의 다양한 핵심 특성을 추가하였습니다. 이 개발자 판은 실시간 앱에 이런 특성을 사용하고 싶지만 아직 규모는 크지 않고 엔터프라이즈 버전의 큰 규모용 회사의 특성등은 필요 없는 고객에게 적합합니다. 60일 무료 버전인 프로페셔녈 버전을 오늘 받아보세요.

개발자 판의 출시는 우리가 지속적으로 따라야 할 패턴을 수립합니다. Realm의 특성과 기능들을 점차 아래로 흐르게하고 새로운 가격과 패키지를 만들어 더 많은 개발자가 접근할 수 있게 합니다. 이제 Realm 모바일 플랫폼은 세가지 버전으로 제공됩니다. 개발자 버전은 완전히 무료고 누구나 쓸 수 있습니다. 프로페셔널 버전은 더 강력한 기능을 가지고 있고 중간 크기의 사업을 목표로 하며 수천의 동시 사용자를 지원하고 월당 $1500에서 시작합니다. 전체 기능을 가진 엔터프라이즈 버전은 더 많은 사용자와 더 복잡한 앱을 지원하고 사용 케이스에 따라 가격을 달리 합니다. 우리는 고객들의 다양한 요구를 이해하려 노력하고 있습니다. 여러 버전이나 가격에 대한 궁금증은 여기로 문의해주세요.

스캐너: IBM과의 협업

초기 버전의 전문가 버전으로 IBM에게 연락했을 때 그들은 매우 흥미로워 했고 매우 빠르게 대응했습니다. 그 결과는 스캐너 앱이 탄생 했습니다. Realm 데모 앱으로 무엇이든지 찍고, 복잡한 서버 측 이미지 처리 결과를 바로 확인할 수 있습니다. 이 이미지 처리는 이미지 분류, 안면 인식, 문자열 인식을 포함합니다. 이 앱은 프로페셔널 버전의 핵심 기능인 실시간 데이터 동기화와 이벤트 처리와 IBM의 왓슨 시각 인식 API를 활용합니다. 다양한 실시간 앱에서 이런 기능을 이런 적은 코드를 구현할 수 있습니다. VR 애플리케이션을 위한 지역 판별, 보안을 위한 얼굴 인식, 산업이나 과학 응용을 위한 이미지 분류, 소매 영역에서 라벨 읽기 등을 상상해보세요. 하지만 상상에 너무 많은 시간을 쓰지 말고 직접 해보세요. 데모 애플리케이션과 (스위프트와 안드로이드로 된) 모든 코드는 오픈 소스 프로젝트로 자유롭게 사용할 수 있습니다. 튜토리얼로 시작할 수도 있습니다. IBM 팀은 또 동작하는 앱의 비디오를 포함한 협엽에 관한 블로그를 개재하였습니다.

이 스캐너 앱은 Realm 모바일 플랫폼이 제공하는 매우 일반화된 패턴을 사용합니다. 이를 API 모바일화 (API mobilization)라고 부르며 “API 브릿징”이라고도 합니다. 개발자들은 높은 반응성과 훌륭한 UX 를 지원하는 모바일 앱을 원하며 앱은 기존의 API들에 안정적으로 동기화되어 동작하길 원할 때 사용합니다. 기존 API는 IBM 왓슨과 같은 현대적인 서비스도 될 수 있으며 조직 내의 오래된 시스템도 해당합니다. 모바일 개발자가 마주치는 문제는 모든 네트워크 요청이 비동기적이고 실패할 수 있다는 점입니다. 많은 조직이 특정한 순서로 여러 API를 호출할 필요가 있는 복잡한 비지니스 로직을 가지고 있습니다. 네트워크를 안정적으로 다루기 위해 이 요청들을 적절히 조합하기 위한 추가적인 코드가 필요합니다. 여러 실패 상황을 다루어야 합니다. 이런 문제를 해결하기 위해, 개별 네트워크 요청은 데이터를 JSON과 같은 새로운 포맷으로 바꾸어야 합니다. 게다가 고통스러운 직렬화/비직렬화를 위한 코드도 추가되어야 하죠. 데이터나 스키마가 변경되면 버그는 쉽게 발생합니다.

API 모바일화 패턴은 Realm 플랫폼을 미들웨어로 활용합니다. 모바일 애플리케이션은 (iOS나 안드로이드 용) Realm 데이터베이스을 클라이언트 측에서 사용하며 Realm 플랫폼에 의해 서버 사이드 데이터가 자동으로 동기화됩니다. 서버 측 Realm 플랫폼은 데이터가 변동이 있을 때 마다 (예를 들어 이미지가 추가되었을 때) 왓슨 API를 호출하고 이미지 처리된 결과를 가져와 서버 측의 Realm에 다시 저장하며 이는 즉시 클라이언트 측으로 동기화됩니다. 네트워크와 데이터 변환 등의 코드를 모두 앱에서 제거하세요. Realm 플랫폼이 데이터 전송의 모든 복잡성을 담당하는 동안 모바일 개발자는 평소 사용하는 Realm 데이터베이스를 앱에서 사용하는 네이티브 언어(Java, Swift, Objective-C)로 객체를 직접 사용 할 수 있습니다.

지금 시작하세요

개발자들이 Realm을 이용해서 개발하는 것은 항상 정말 기쁜 일입니다. 그래서 프로페셔널 버전의 무료 체험판을 다운 받아 설치할 수 있게 초대드립니다. 스캐너 앱이나 여러 분의 앱을 설정하여 체험해 보시고 여러 분의 생각을 우리에게 알려주세요.

더 읽어보기

Node를 위한 첫 객체 데이터베이스: Realm Node.js 를 소개합니다

by /

Realm은 모바일 개발자들이 더 나은 앱을 보다 빠르게 개발하도록 돕기 위해, Swift, Objective-C, Java, Xamarin, React Native 등 다양한 언어와 개발환경을 지원하는 Realm Mobile Database을 구축했습니다. 오늘, 저희는 기존 제품과는 완전히 다른 제품인 Realm Node.js를 공개합니다. Realm Node.js는 Node를 위한 최초의 실제 오브젝트 데이터베이스이며, NPM을 통해 무료인 전체 공개 오픈 소스 리파지토리에서 받을 수 있습니다. 콘솔에서 npm install --save realm를 적용하면 됩니다.

수년간 많은 모바일 개발자들이 서버에서 동작하는 Realm 버전 개발을 요청해 왔기 때문에, 이 항목은 우선 순위가 높지는 않지만 백로그에 오랫동안 머물러 있었습니다. 그러나 9월에 저희의 새 제품, Realm Mobile Platform를 출시하면서 우선 순위가 바뀌었고, 잠재 고객들이 플랫폼에 대한 Node 인터페이스에 대해 질문하기 시작했으므로, 빠르게 플랫폼 제품 전략의 Node 부분을 수립한 결과 Realm Node.js가 만들어졌습니다.

Realm Node.js은 무엇이며 무슨 일을 하나요?

Realm은 객체 데이터베이스입니다. 즉, 평소처럼 객체에 대한 작업을 하면 Realm에서 이런 객체들을 디스크에 효율적으로 쉽게 저장합니다. 객체를 JSON으로 직렬화할 필요도 없고, 테이블에 저장하기 위해 ORM을 통해 보낼 필요도 없습니다. 객체 지향 개발 원칙이 지향하는 원칙을 고수하면서 만들고자 한 것을 만들면 됩니다. 모든 모바일 클라이언트단 플랫폼에서 작동하며, 이제 서버단인 Node.js에서도 작동합니다.

모바일 개발자가 Realm Node.js를 사용하면 미리 만들어진 Realm을 클라이언트에 보낼 수 있기 때문에 여러 모로 편리합니다. 앱 용량 제한과 같이 귀찮은 제약 조건을 우회할 수 있으므로 모바일 개발자들이 몇 년간 지속적으로 이런 기능 구현을 요청해왔습니다.

그러나 백엔드 개발자에게 몇몇 초기 버전을 보여주면서, Realm Node.js가 처음 상상했던 것보다 훨씬 더 Node 활용에 유용하다는 것을 알게 됐습니다. 예를 들어 여러 Node 인스턴스 간에 실시간 데이터를 편리하게 공유할 수 있습니다. 이를 설명하기 위해 Realm을 사용해서 한 기기 상의 두 개의 Node 프로세스가 객체의 직렬화와 역직렬화에 대한 부담 없이 하나의 객체를 함께 작업할 수 있도록 하는 간단한 데모를 작성했습니다.

Realm의 고유 기능인 반응형 아키텍쳐도 설명드리겠습니다. Realm은 스레드나 프로세스간 데이터베이스 동시 실행 접근 기능 제공을 위해 Multiversion Concurrency Control를 사용합니다. 즉, 쓰기 실행자에 의해 읽기 실행자가 차단되지 않으며 양측 모두 데이터베이스에 대한 일관적인 뷰를 유지하므로 Realm의 ACID가 유지됩니다. 이같은 조정을 위해 Realm은 쓰기 트랜잭션이 완료될 때 알림 시스템을 사용하여 접근자를 업데이트합니다. 이 점을 활용해서 개발자는 Realm의 알림 API으로 변경 사항에 대응할 수 있습니다. 아래 예제는 Node.js 개발자가 프로세스간 통신을 위해 Realm을 사용해서 두 독립적인 서비스를 조정하는 방법을 보여줍니다.

예제에서 Node.js 인기 라이브러리인 Express가 HTTP endpoint 생성을 위해, 웹 프레임워크 및 로깅 라이브러리인 Winston이 요청에 대한 정보 로그 생성을 위해 쓰였습니다.

var express = require('express'),
    util = require('util'),
    winston = require('winston');
    RealmWinston = require('./winston-realm').Realm;

var app = express();

// Use custom Winston transport: RealmWinston
// Writes log data to winston.realm
winston.add(RealmWinston, {});

app.get('/', function (req, res) {
  res.send('Hello World!');
  winston.info('Handled Hello World');
});

app.use(function (req, res, next) {
  res.status(404).send('Sorry can not find that!');
  winston.error('404 Error at: ' + req.url);
})

app.listen(3000, function () {
  console.log('Example app listening on port 3000!');
});

Realm의 장점을 활용하기 위해, Realm 파일에 Winston 로그 데이터를 저장하는 custom transport를 생성합니다. 기본 경로에 “Hello World” 응답을 확인하는 정보 메시지를 기록합니다. 다른 경로의 경우 404 error로 응답하고 오류 메시지의 해당 경로를 기록합니다. Realm에 로그 데이터를 저장한 이후에는 다른 Node 프로세스를 실행하고 변경에 대응하는 Realm 리스너를 등록할 수 있습니다.

'use strict';

var Realm = require('realm');

let winstonRealm = new Realm({
  path: 'winston.realm'
});

// Register listener to print out log messages at error level
winstonRealm.objects('Log').filtered('level = "error"').addListener((logs, changes) => {
  changes.insertions.forEach((index) => {
    let log = logs[index];
    console.log(log.message);
  })
});

리스너는 Realm이 제공하는 컬렉션 통지를 사용합니다. 컬렉션 통지는 특정 변경 사항이 발생하면 변화가 발생한, 즉 삽입, 삭제, 수정된 객체의 인덱스로 전달합니다. 아래 예제는 오류 수준의 모든 로그 쿼리에 리스너를 추가한 다음 로그 메시지를 콘솔에 표시합니다.

이 예제는 단순하지만, 이 설정은 마이크로 서비스 아키텍쳐 전반의 데이터를 조정하는 보다 복잡한 시나리오에도 사용할 수 있습니다. 전체 데모를 확인하세요. Realm의 모든 JavaScript 플랫폼은 기반 코드 구현을 공유하므로, 여러분의 Node.js 프로젝트에 Realm을 적용할 준비가 되었다면 React Native 문서와 API docs에서 유용한 정보를 찾을 수 있을 겁니다.

또 어디에 Realm Node.js를 활용할 수 있을까요? 로컬 메모리보다 큰 데이터셋을 작업할 때 사용할 수 있습니다. 질의와 관찰이 가능한 데이터 구조로도 활용할 수 있습니다. 여러 Node 인스턴스 사이에 리액티브 구조를 구축하는데도 활용해 보세요. Docker 이미지 간의 통신을 위해서도 사용할 수 있겠죠. 여러분이 적용해본 다양한 분야를 공유해 주세요!

더 읽어보기

Realm Java 2.0 - 모바일 플랫폼 지원

by /

오늘 우리는 Realm 모바일 플랫폼 지원이 추가되고 여러 작은 변경과 버그 수정이 된 2.0 버전의 Realm Java를 출시합니다.

Realm 모바일 플랫폼 확장

Realm 모바일 플랫폼 런칭 글을 읽지 않았다면 지금 읽고 안드로이드의 기술적인 부분을 살펴봅시다.

먼저 모바일 플랫폼 확장을 다음과 같이 앱의 build.gradle 파일을 수정하여 활성화합니다.

realm {
  syncEnabled = true
}  

동기화된 Realm의 설정에 대해 짧게 살펴봅시다.

// 로그인 합니다.
Credentials credentials = Credentials.usernamePassword(username, password, true);
User.loginAsync(credentials, "https://realm.example.com:9443), new User.Callback() {
  @Override
  public void onSuccess(User user) {
    // 동기화된 Realm을 엽니다.
    // 모든 변경은 Realm이 모든 장비에서 동기화합니다
    SyncConfiguration config = new SyncConfiguration.Builder(user, "realm://realm.example.com/~/userRealm").build();
    Realm realm = Realm.getInstance(config);
  }

  @Override
  public void onError(ObjectServerError error) {
    // Handle error
  }
});

이것입니다! 한번 Realm이 이렇게 열리면 어떤 변경이라도 자동으로 해당 사용자의 다른 모든 장비에 동기화됩니다.

기술적인 부분으로 돌아갑시다. Realm 모바일 플랫폼 지원에 따라 몇몇 새로운 클래스와 API가 추가되었습니다.

사용자와 증명

사용자는 Realm 동기화의 핵심적인 컨셉입니다. 모든 Realm은 사용자와 연결되어 있습니다. 사용자는 사용자 이름 / 비밀번호 증명이나 여러 추가적인 인증(Google, Facebook, iCloud 등)을 통해 Realm에 인증할 수 있습니다. 사용자에 대한 자세한 내용은 문서를 참고하세요.

동기화 설정

Realm 동기화를 설정하기 위해 사용자와 원격 Realm 주소(예: realm://realm.example.com:9080/~/userRealm)를 가지고 SyncConfiguration를 생성해야합니다. 자세한 내용은 우리 문서를 참고하세요.

동기화 관리자와 세션

SyncManager는 모든 동기화된 Realm을 관리하는 싱글턴입니다. 여러분은 이제 전역 에러 핸들러나 사용자를 어떻게 다루는지를 지시하기 위해 이것과 상호작용하게 됩니다.

동기화된 개별 Realm은 연관된 Session을 가지는데 상태에 대한 추가적인 정보를 제공합니다. 앞으로의 출시에 더 많은 정보를 추가하려 합니다.

플랫폼 확장은 베타입니다

최근 5년간 Realm의 동기화를 위한 아래단의 기술이 만들어지고 정제되고 안정화를 진행하고 있지만 이를 공개하기 전에 API가 올바른지 확인하고 싶습니다. 그래서 우리는 플랫폼 확장을 베타로 출시합니다. 이 API들은 이후 출시에서 변경될 수 있습니다. 가능한 최상의 제품으로 만들기 위함입니다.

만약 앱에 플랫폼 확장을 사용하지 않는다면 항상 사용했던 안정성을 믿을 수 있습니다. 플랫폼 확장은 Realm을 전적으로 지역적으로 사용하거나 동기화하여 사용할 때 명확하게 다르도록 설계하였습니다. 그래서 앱이 어떤 베타 요소를 사용하는 것을 확인하는 것은 쉽습니다.

모든 베타 API는 코드와 자바독에 @Beta 어노테이션과 태그가 각자 지정되어있습니다.

다른 2.0의 변경 사항

이 출시에 포함된 새로운 기능과 능력의 규모에 따라 큰 버전을 올립니다. 동시에 우리는 Realm Java를 Realm Swfit와 Realm Objective-C에 따라 몇가지 조정을 함으로서 몇몇 부분들이 간소화되었습니다.

Realm Java가 성능 향상과 몇가지 버그 수정을 하기 위해 새로운 파일 포맷을 소개하는 것을 주의하세요. Realm 2.0에서 작성된 파일들은 1.x과 그 이전 버전에서 읽을 수 없습니다. 예전 파일들은 여전히 읽을 수 있습니다.

전역 초기화

Context 레퍼런스는 불필요한 마찰을 줄이기 위해 점차 우리 API 속으로 감추어졌습니다.

우리는 한 걸음 물러나 전역 초기화 함수를 제공합니다.

Realm.init(context)`

이는 API의 여러 부분에서 다음과 같이 컨텍스트를 제거할 수 있게 합니다.

  • RealmConfiguration.Builder() 생성할 때 더 이상 컨텍스트가 필요하지 않습니다.
  • RealmConfiguration.Builder.assetFile()는 더이상 컨텍스트를 요구하지 않습니다.
  • Realm.getDefaultInstance()는 이제 디폴트를 먼저 생성하지 않아도 동작합니다.
  • 네이티브 코드의 읽기가 더 실패에 안전해졌습니다.

이 메서드를 호출하기 자연스러운 곳은 Application의 자식 클래스입니다.

public class MyApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        Realm.init(this);
        // 다른 초기화 루틴
    }
}

기본 값

Realm Java 2.0부터 객체를 생성할 때 기본값을 지원합니다. 이는 필드에 값을 설정하거나 기본 생성자를 통해 기본 값을 지정할 수 있다는 것입니다.

public class Person extends RealmObject {
  private String name = "John";
  private int age;
  
  public Person() {
    this.age = 42;
  }
}

Person p = realm.createObject(Person.class);
p.getName(); // John
p.getAge(); // 42

기본값은 JSON 데이터로 부터 객체들을 생성할 때도 적용합니다. 반면 다이나믹 API를 통해 객체를 생성할 때는 적용되지 않습니다.

RealmLog

공개 API에 새로운 클래스 RealmLog가 추가되었습니다. 이는 Realm이 얼마나 어떻게 로깅을 할지 개인화할 수 있게 합니다. 모바일 플랫폼의 모든 이벤트는 이 클래스를 통합니다.

RealmLog.clear(); // 모든 로거를 제거합니다
RealmLog.add(new AndroidLogger(Log.DEBUG)); // 커스텀 로그를 설정합니다

기본 키들과 객체

여러 단말의 객체를 통합하기 위해 객체의 기본 키에 대한 새로운 두가지 제약이 추가되었습니다.

1) 기본 키는 객체를 생성할 때 제공되어야 합니다. 2) 한번 설정된 기본 키는 바꿀 수 없습니다.

첫번째 제약은 realm.createObject(Class)로 객체를 생성할 때만 보입니다. 이런 경우에 realm.createObject(Class, Object)를 호출하여 기본 키를 정의하는 것이 요구됩니다.

realm.copyToRealm()realm.createObjectFromJson()는 계속 이전처럼 작동합니다.

어떤 이유로 기본 키를 바꾸어야 한다면 새로운 객체를 만들고 기존의 값을 복사해야 합니다. 이는 copyFromRealm()/copyToRealm()를 통해 하십시요.

버그 수정과 기타 변경

전체 변경과 버그 수정은 변경 내역에서 보세요.


읽어주셔서 감사합니다. Realm과 함꼐 위대한 앱을 만들어 앞으로 나아갑시다. 우리는 언제나 Stack Overflow, GitHub, Twitter에 있습니다.

더 읽어보기

Realm 모바일 플랫폼을 소개합니다: 실시간으로 동기화하는 오픈소스 데이터베이스

by /

Realm을 처음 런칭한 2014년도 당시의 저희 목표는 SQLite와 Core data 대신 사용할 수 있는 강력한 기능의 데이터베이스를 제공하여 모바일 개발자들이 더 나은 앱을 보다 빠르게 개발하도록 돕는 것이었습니다. 2년 반이 지난 지금, 수십만 명 이상의 개발자가 실제로 Realm을 사용하고 있으며, Realm을 사용하는 앱은 전세계적으로 수백만명 이상의 개발자가 실제 사용하고 있습니다. Realm이 이처럼 성공할 수 있었던 것은 많은 개발자 커뮤니티에서 저희 제품을 채택하고 지원하며 피드백을 준 덕분입니다. 저희는 이에 깊이 감사하는 마음으로 더 나은 제품을 개발하고자 노력하고 있습니다.

오늘, 저희는 iOS와 안드로이드 클라이언트 부분의 데이터베이스 오픈소스인 Realm 데이터베이스을 서버 부분의 신기술과 통합한 Realm 모바일 플랫폼(RMP)을 공개합니다. Realm 모바일 플랫폼은 실시간 동기화와 충돌 해소, 리액티브 이벤트 핸들링 등 다양한 서버사이드 기능을 지원합니다. RMP를 사용하면 실시간 협업이나 메시지, 오프라인 중심의 기능 등 모바일 개발자들이 앱을 개발할 때 어려움을 겪는 기능을 훨씬 쉽게 개발할 수 있습니다.

 

오늘 선보이는 새로운 플랫폼은 베타 버전으로, 두 가지 에디션으로 제공됩니다. 개발자 에디션은 취미로의 개발부터 작은 상용 규모의 앱까지의 유스 케이스에 사용할 수 있으며 평생 무료로 제공됩니다. 기업 에디션은 시간 제한이 있는 트라이얼 사용이 가능하며, 개발 규모가 큰 유스 케이스에 필요한 모든 것을 지원합니다. 현재 RMP는 Java, Objective-C, Swift를 지원하며, React Native와 Xamarin은 아직 준비 중입니다.

또 다른 소식도 있습니다. 바로 Realm Core의 오픈 소스 공개입니다. 이로써 저희 Realm 모바일 데이터베이스는 완전히 오픈 소스화 됩니다. 소스 저장소는 이곳에서 확인하실 수 있습니다. 앞서 소개한 새 플랫폼을 구성하는 요소이자 모바일 개발자를 위한 독립적인 데이터베이스 옵션을 제공하는 Realm 모바일 데이터베이스는 저희의 핵심 제품입니다. 따라서 Realm Java, Realm Objective-C, Realm React Native, Realm Swift, Realm Xamarin의 전담 개발 팀이 지속적으로 제품을 유지 보수하고 개선해나갈 예정입니다.

The Realm Mobile Platform

다양한 플랫폼 어디서나 같은 객체를 사용

Realm을 오래 사용한 개발자도 Realm의 핵심적인 차별 포인트가 core 레벨의 내장 오브젝트 데이터베이스라는 점을 아직 모를 수 있습니다. 사실 개발자들이 Realm의 장점으로 꼽는 사용의 간편함과 속도는 이러한 특징에서 나옵니다. Realm을 사용하면 객체 관계를 복잡하게 매핑하려고 씨름하지 않아도 됩니다. 오직 오브젝트만을 사용하므로, 데이터베이스 자체를 데이터 모델로 활용할 수 있습니다.

저희는 이러한 관점의 디자인 철학을 새 오브젝트 서버에 담았습니다. Realm 플랫폼의 마법 같은 기능은 저희가 “라이브 오브젝트”라고 명명한 오브젝트에서부터 시작됩니다. 라이브 오브젝트란 서버의 데이터 오브젝트와 온전히 동기화되는 것이 보장되는 기기의 데이터 오브젝트를 뜻합니다. RMP에서는 단 한 줄의 네트워크 연결 코드 없이도 동기화가 자동적이며 연속적으로 이뤄집니다. 또한 전체 오브젝트가 아닌 변경 내용만을 전송하므로 매우 효율적이기까지 합니다. Realm 플랫폼은 충돌 해소 기능 역시 제공하므로, 두 군데 이상에서 라이브 오브젝트를 경쟁적으로 변화하더라도 미리 정해둔 기본 규칙에 따라 자동적으로 충돌 해결이 가능합니다. 대부분의 유스 케이스를 이 기본 규칙으로 커버할 수 있지만, 필요한 경우 충돌 해소 규칙을 직접 원하는 규칙으로 구현 할 수도 있습니다.

Realm을 사용하면 네트워크에 대한 고민을 시작할 필요조차 없습니다. 단지 라이브 오브젝트를 사용해서 앱을 개발하기만 하면 됩니다. 즉, 개발하기 까다로운 실시간 협업이나 메시징 등의 기능을 정말 쉽게 개발할 수 있습니다. 예를 들어 각각 다른 기기를 사용하는 사용자들이 한 화이트보드에서 협업하는 기능을 생각해 보겠습니다. 해당 기능 구현 중 가장 어려운 부분은 변화가 일어날 때 각각의 사용자 UI에 즉각적으로 반영되도록 하는 것입니다. 또한 사용자들이 동시에 같은 영역을 그리거나 지움으로써 생기는 충돌을 잘 해결하는 것도 어렵습니다. Realm 플랫폼을 사용하면 이런 문제를 쉽게 해결할 수 있습니다.

Realm 모바일 플랫폼으로 오프라인 중심 UX 구현하기

Realm 모바일 플랫폼은 인터넷 연결이 끊기더라도 매끄러운 사용자 경험을 제공해야 하는 오프라인 중심 앱을 개발할 때도 유용합니다. 기본적으로는 효율적인 기기 내장 데이터베이스인 Realm 모바일 데이터베이스를 사용하는 것만으로도 인터넷 연결이 끊겼을 때 좋은 사용자 경험을 유지하는데 도움이 됩니다.

그러나 Realm 데이터베이스와 오브젝트 서버를 아우르는 전체 Realm 플랫폼을 사용할 경우 효과가 극대화됩니다. 먼저 백그라운드에서 구동되는 양방향 자동 동기화 기능이 있으므로, 연결이 끊기기 직전까지 기기의 데이터 오브젝트는 최신 상태가 보장됩니다. 연결이 복구되면 다시 자동 동기화가 시작되며, 중간에 발생할 수 있는 충돌 역시 자동적으로 해결되므로 라이브 오브젝트는 다시 최신 상태가 보장됩니다. 따라서 사용자는 아무 일도 없던 것처럼 작업을 계속할 수 있습니다.

이벤트 핸들링

Realm 플랫폼의 기업 버전은 또 다른 핵심 기능인 서버 부분 이벤트 핸들링 프레임워크를 제공합니다. 이는 오브젝트가 바뀔 때마다 서버 부분 로직을 쉽게 발동하도록 하는 기능입니다. 이 프레임워크가 기기 쪽에서 발생한 오브젝트의 변화를 감지하도록 설정하고 이에 반응하는 서버 부분의 코드를 즉각적으로 실행할 수 있습니다. 만약 사용자가 주문 양식을 작성하는 도중에 쿠폰 코드를 입력한다면, 기기 부분의 쿠폰 오브젝트에 변화가 발생하고, 이는 바로 서버에 동기화됩니다. 이런 특정 변화가 이벤트 핸들링 프레임워크로 작용해서 유효한 코드인지 서버 부분 쿠폰 오브젝트에서 확인하는 코드의 트리거가 될 수 있습니다. 이 응답으로 다시 기기 부분의 쿠폰 오브젝트가 동기화되면서 UI를 갱신하는 알림이 작동할 수 있습니다.

Event handling

기존 API와 인프라스트럭쳐를 통합하는 용도로 이벤트 핸들링을 사용할 수도 있습니다. 즉, Realm 오브젝트 서버를 API 브릿지나 모바일화를 위한 미들웨어로 사용할 수 있습니다. 또한 각 특정 트리거마다 독립적인 기능을 구현해서 서버리스 원칙에 맞는 앱을 디자인할 수도 있습니다.

오늘 바로 써보실 수 있습니다

Realm 모바일 플랫폼은 두 가지 버전으로 제공됩니다. 개발자 에디션은 무료이며 베타 버전 사용이 가능합니다. 시작하기 페이지에서 쉽게 사용을 시작해 보세요. 피드백은 언제든 환영입니다. 기업 에디션은 이벤트 핸들링 프레임워크와 쉬운 통합 등 여러 핵심 기능을 포함합니다. 현재 클로즈 베타 프로그램 중이며, 간단한 양식을 입력하시면 대기 목록에 추가하여 준비가 되면 알려드리겠습니다.

더 읽어보기

Realm Java 1.1.0 — 새롭고 빠른 삽입 API!

by /

우리는 Realm Java의 새 버전을 웹사이트와 Bintray에 출시하였습니다. 이 버전은 여러 버그 수정과 새로운 삽입 API를 포함합니다.

삽입 API

Realm의 저장소 엔진은 데이터 삽입에서 SQLite에 비해 항상 빠르지만 몇몇 Realm Java API의 설계 결정 때문에 이점을 상실했습니다. 소량의 자료(<1000)를 삽입할 때는 일반적으로 SQLite 만큼 빠르지만 일괄적으로 더 이상의 항목을 추가하면 느려지기 시작합니다.

v1.1.0에서 몇가지 최적화를 하였고 아래 4개의 새로운 메서드를 제공합니다.

  • void Realm.insert(RealmModel obj)
  • void Realm.insert(Collection collection)
  • void Realm.insertOrUpdate(RealmModel obj)
  • void Realm.insertOrUpdate(Collection collection)
Realm realm = Realm.getDefaultInstance();
realm.beginTransaction();
realm.insertOrUpdate(restApi.getPersons());
realm.commitTransaction();

이 메서드들이 어떠한 객체도 반환하지 않는다는 점에서 일반적인 Realm.copyToRealm()와 크게 다릅니다. 이를 통해 메모리 할당을 거의하지 않고 순수히 비용이었던 많은 확인을 제거합니다.

이렇게 해서 10만여개의 객체를 다룰 때 최적화된 SQLite 구현에 비해 40%가 늦었던 성능을 70% 가량 빠르게 개선하였습니다.

Realm Batch Insert Benchmark

이런 규모를 직접 검증할 수 있게 벤치마크 저장소를 출시합니다. 여기에서 확인해보세요. 위에 측정된 수치는 출시된 안드로이드 6.0.1을 이용하여 Nexus 6P에서 측정하였습니다.

Realm의 자동 갱신 측정 때문에 데이타가 저장되기 전에 질의를 할 수 있고 데이터가 준비되었을 때 통보받을 수 있습니다. 이는 데이터 저장과 데이터 출력을 분리하고자 할 때 큰 이점이 있습니다.

final PersonApi api = new PersonApi();
Realm realm = Realm.getDefaultInstance();
RealmResults<Person> persons = realm.where(Person.class).findAllAsync();
person.addChangeListner(new RealmChangeListener() {
    @Override
    public void onChange(RealmResults<Person> persons) {
      if (!persons.isEmpty()) {
	    // Callback when data is available
      }
  }
});

realm.executeTransactionAsync(new Realm.Transaction() {
    @Override
    public void execute(Realm realm) {
      realm.insertOrUpdate(api.getPersons());
    }
});

버그 수정

  • 비동기 트랜잭션과 비동기 질의가 UI 스레드에서 결합할 때 UI 스레드에서 데이터가 준비되기 전에 트랜잭션의 onSuccess 콜백이 호출될 수 있습니다.

  • 1.0.1에서 소개된 RealmOptionalAPITransformer가 DexGuard와 제대로 동작하지 않아서 이제 비활성화되었습니다.

전체 변경 사항에서 상세 내용을 확인하세요.


읽어주셔서 감사합니다. Realm과 함께 위대한 앱을 만들어 나가 봅시다! 우리는 항상 Stack Overflow, GitHub, Twitter에 있습니다.

더 읽어보기

Realm Xamarin 0.76.0 릴리스

by /

Realm Xamarin 0.76 버전을 릴리스하였습니다. 이 버전은 첫번째 외부 기여인 Joe BrockINotifyPropertyChanged 지원이 포함된 버전입니다. 이는 Xamarin 폼의 데이터 바인딩을 사용할 때 변경 노티피케이션을 여러분의 Realm 객체에 추가합니다. 자세한 정보를 위해 Xamarin 문서의 From Data Bindings to MVVM 를 참고하세요. NuGet은 이미 기존 프로젝트의 라이브러리를 업데이트하거나 새 버전을 새 프로젝트에 추가할 수 있다고 알려줍니다.

주요 변경점

  • RealmObject 클래스는 이제 암묵적으로 INotifyPropertyChanged을 구현합니다. Joe Brock의 기여에 감사드립니다.

사소한 변경

  • long이 질의에 지원됩니다.
  • System.String System.String::Format(System.IFormatProvider,System.String,System.Object)와 같이 보이는 Linker 에러가 수정되었습니다.
  • RealmObject에 대한 두단계 상속과 RealmObject 클래스 내의 정적 프로퍼티는 이제 위버가 적절히 (아직) 지원하지 않는다는 에러를 출력합니다.
  • .Equals()를 독립 객체에 호출할 때 더 이상 예외를 던지지 않습니다.

읽어주셔서 감사합니다. Realm과 함께 위대한 앱을 만들어 갑시다. 우리는 언제나 Stack Overflow, GitHub, Twitter에 있습니다.

더 읽어보기