Docs Menu
Docs Home
/ /
Atlas Device SDK
/ /

managed Flexible Sync 구독 - Java SDK

이 페이지의 내용

  • 개요
  • 쿼리 가능 필드 구독
  • 구독 추가
  • 구독 변경 사항이 Sync될 때까지 기다리기
  • 새 쿼리로 구독 업데이트하기
  • 구독 제거
  • Flexible Sync RQL 요구 사항 및 제한 사항
  • 인덱싱된 쿼리 가능 필드 구독 요구 사항
  • Flexible Sync에서 지원되지 않는 쿼리 연산자
  • 목록 쿼리
  • 임베디드 또는 링크된 객체
  • 쿼리 크기 제한

Flexible Sync는 구독 및 권한을 사용하여 앱과 동기화할 데이터를 결정합니다.

SDK에서 Flexible Sync를 사용하는 방법은 다음과 같습니다.

  • 백엔드에서 Flexible Sync 구성

  • 앱 초기화

  • 클라이언트 프로젝트에서 사용자를 인증합니다.

  • Flexible Sync 구성으로 동기화 Realm 열기

  • 클라이언트 애플리케이션에 구독 추가

쿼리 구독을 추가, 업데이트 및 제거하여 클라이언트 장치에 동기화할 데이터를 결정할 수 있습니다.

다음도 참조하세요.

이 페이지에서는 Flexible Sync에 대한 구독을 managed하는 방법에 대해 자세히 설명합니다.

백그라운드에서 변경 사항을 동기화하거나 동기화 세션을 일시 중지하는 방법 등 SDK와 함께 Atlas Device Sync를 사용하는 방법에 대한 일반적인 내용은 Realm Mobile Sync를 참조하세요.

Flexible Sync의 권한 설정에 대한 자세한 내용은 Flexible Sync 규칙 및 권한을 참조하세요.

백엔드에서 Flexible Sync를 구성할 때 클라이언트 애플리케이션에서 쿼리할 수 있는 필드를 지정합니다. 클라이언트 애플리케이션에서 subscriptions API를 사용하여 쿼리 가능 필드의 특정 쿼리에 대한 구독 세트를 managed합니다. Java SDK의 유창한 인터페이스 또는 RealmQL를 사용하여 쿼리를 구성할 수 있습니다.

중요

Flexible Sync 는 RQL에서 사용할 수 있는 모든 연산자를 지원하지 않습니다. 자세한 내용은 Flexible Sync RQL 제한 사항 을 참조하세요.

다음을 수행할 수 있습니다.

  • 구독 추가

  • 구독 상태에 React

  • 새 쿼리로 구독 업데이트

  • 객체 유형에 대한 개별 구독 또는 모든 구독 제거

사용자가 적절한 권한을 가진 구독과 일치하는 데이터는 클라이언트와 백엔드 애플리케이션 간에 동기화됩니다.

구독에 대한 선택적 문자열 이름을 지정할 수 있습니다.

항상 구독 이름 지정

애플리케이션에서 여러 개의 구독을 사용하는 경우 항상 구독 이름을 지정합니다. 이렇게 하면 앱의 다른 곳에서 구독을 더 쉽게 조회, 업데이트 및 삭제할 수 있습니다.

구독을 생성하면 Realm은 특정 객체 유형에 대한 쿼리와 일치하는 데이터를 찾습니다. 서로 다른 객체 유형에 대해 여러 개의 구독 집합을 가질 수 있습니다. 동일한 객체 유형에 대해 여러 개의 쿼리를 가질 수도 있습니다.

명시적인 이름으로 구독을 만들 수 있습니다. 그런 다음 해당 구독을 이름으로 검색하여 업데이트하거나 제거할 수 있습니다.

SyncConfiguration config = new SyncConfiguration.Builder(app.currentUser())
.initialSubscriptions(new SyncConfiguration.InitialFlexibleSyncSubscriptions() {
@Override
public void configure(Realm realm, MutableSubscriptionSet subscriptions) {
// add a subscription with a name
subscriptions.add(Subscription.create("frogSubscription",
realm.where(Frog.class)
.equalTo("species", "spring peeper")));
}
})
.build();
Realm.getInstanceAsync(config, new Realm.Callback() {
@Override
public void onSuccess(Realm realm) {
Log.v("EXAMPLE", "Successfully opened a realm.");
// later, you can look up this subscription by name
Subscription subscription = realm.getSubscriptions().find("frogSubscription");
}
});
val config = SyncConfiguration.Builder(app.currentUser())
.initialSubscriptions { realm, subscriptions ->
// add a subscription with a name
subscriptions.add(
Subscription.create(
"frogSubscription",
realm.where(Frog::class.java)
.equalTo("species", "spring peeper")
)
)
}
.build()
Realm.getInstanceAsync(config, object : Realm.Callback() {
override fun onSuccess(realm: Realm) {
Log.v("EXAMPLE", "Successfully opened a realm.")
// later, you can look up this subscription by name
val subscription =
realm.subscriptions.find("frogSubscription")
}
})

쿼리로 구독을 검색할 수도 있습니다. 구독을 생성할 때 이름을 생략하는 경우 이것이 구독을 조회할 수 있는 유일한 방법입니다.

SyncConfiguration config = new SyncConfiguration.Builder(app.currentUser())
.initialSubscriptions(new SyncConfiguration.InitialFlexibleSyncSubscriptions() {
@Override
public void configure(Realm realm, MutableSubscriptionSet subscriptions) {
// add a subscription without assigning a name
subscriptions.add(Subscription.create(
realm.where(Frog.class)
.equalTo("species", "spring peeper")));
}
})
.build();
Realm.getInstanceAsync(config, new Realm.Callback() {
@Override
public void onSuccess(Realm realm) {
Log.v("EXAMPLE", "Successfully opened a realm.");
// later, you can look up this subscription by query
Subscription subscription = realm.getSubscriptions().find(realm.where(Frog.class)
.equalTo("species", "spring peeper"));
}
});
val config = SyncConfiguration.Builder(app.currentUser())
.initialSubscriptions { realm, subscriptions ->
// add a subscription without assigning a name
subscriptions.add(
Subscription.create(
realm.where(Frog::class.java)
.equalTo("species", "spring peeper")
)
)
}
.build()
Realm.getInstanceAsync(config, object : Realm.Callback() {
override fun onSuccess(realm: Realm) {
Log.v("EXAMPLE", "Successfully opened a realm.")
// later, you can look up this subscription by query
val subscription =
realm.subscriptions.find(
realm.where(
Frog::class.java
).equalTo("species", "spring peeper")
)
}
})

참고

중복 구독

구독 이름은 고유해야 합니다. 기존 구독과 동일한 이름으로 구독을 추가하면 오류가 발생합니다.

구독에 명시적으로 이름을 지정하지 않고 이름이 지정되지 않은 동일한 쿼리를 두 번 이상 구독하면 Realm은 구독 세트에 대한 중복 쿼리를 유지하지 않습니다.

같은 쿼리를 다른 이름으로 두 번 이상 구독하면 Realm은 구독 세트에 대한 두 구독을 모두 유지합니다.

구독 쓰기 블록에서 구독을 추가합니다. 클라이언트의 Realm 구독에 각각의 새 구독을 추가합니다.

SyncConfiguration config = new SyncConfiguration.Builder(app.currentUser())
.initialSubscriptions(new SyncConfiguration.InitialFlexibleSyncSubscriptions() {
@Override
public void configure(Realm realm, MutableSubscriptionSet subscriptions) {
subscriptions.add(Subscription.create("subscriptionName",
realm.where(Frog.class)
.equalTo("species", "spring peeper")));
}
})
.build();
// instantiate a realm instance with the flexible sync configuration
Realm.getInstanceAsync(config, new Realm.Callback() {
@Override
public void onSuccess(Realm realm) {
Log.v("EXAMPLE", "Successfully opened a realm.");
}
});
val config = SyncConfiguration.Builder(app.currentUser())
.initialSubscriptions { realm, subscriptions ->
subscriptions.add(
Subscription.create(
"subscriptionName",
realm.where(Frog::class.java)
.equalTo("species", "spring peeper")
)
)
}
.build()
// instantiate a realm instance with the flexible sync configuration
Realm.getInstanceAsync(config, object : Realm.Callback() {
override fun onSuccess(realm: Realm) {
Log.v("EXAMPLE", "Successfully opened a realm.")
}
})

참고

객체 링크

링크된 객체를 보려면 객체와 해당 링크된 객체를 모두 구독 세트에 추가해야 합니다.

구독 결과에 결과에 포함되지 않은 객체에 연결되는 속성이 있는 객체가 포함된 경우 해당 링크는 null로 표시됩니다. 해당 속성 값이 실제 null인지, 아니면 링크된 객체가 존재하지만 쿼리 구독의 표시 영역에서 벗어난 것인지 구분할 방법이 없습니다.

로컬에서 구독 설정하다 에 대한 업데이트 를 기록하는 것은 구독 변경의 한 구성 요소일 뿐입니다. 로컬 구독 변경 후 클라이언트 는 서버 와 동기화하여 구독 변경으로 인한 데이터 업데이트를 해결합니다. 이는 동기화된 영역 에서 데이터를 추가하거나 제거하는 MEAN 할 수 있습니다. waitForInitialRemoteData() 빌더 메서드를 사용하여 영역 을 열기 전에 클라이언트 구독 데이터가 백엔드 와 동기화될 때까지 애플리케이션 을 강제로 차단 합니다.

SyncConfiguration config = new SyncConfiguration.Builder(app.currentUser())
.initialSubscriptions(new SyncConfiguration.InitialFlexibleSyncSubscriptions() {
@Override
public void configure(Realm realm, MutableSubscriptionSet subscriptions) {
subscriptions.add(Subscription.create("my subscription",
realm.where(Frog.class)
.equalTo("species", "poison dart")));
}
})
.waitForInitialRemoteData(2112, TimeUnit.MILLISECONDS)
.build();
Realm.getInstanceAsync(config, new Realm.Callback() {
@Override
public void onSuccess(Realm realm) {
Log.v("EXAMPLE", "Successfully opened a realm.");
}
});
val config = SyncConfiguration.Builder(app.currentUser())
.initialSubscriptions { realm, subscriptions ->
subscriptions.add(
Subscription.create(
"my subscription",
realm.where(Frog::class.java)
.equalTo("species", "poison dart")
)
)
}
.waitForInitialRemoteData(
2112,
TimeUnit.MILLISECONDS
)
.build()
Realm.getInstanceAsync(config, object : Realm.Callback() {
override fun onSuccess(realm: Realm) {
Log.v("EXAMPLE", "Successfully opened a realm.")
}
})

SubscriptionSet.waitForSynchronization() 동기화 연결을 인스턴스화한 후 구독 동기화 가 완료될 때까지 실행을 지연하려면 또는 SubscriptionSet.waitForSynchronizationAsync() 를 호출합니다.

또한 SubscriptionSet.State 열거형을 사용하여 구독 세트의 상태를 볼 수 있습니다. 구독 상태를 사용하여 다음을 수행할 수 있습니다.

  • 데이터를 다운로드하는 동안 진행률 표시기를 표시합니다.

  • 구독 세트가 대체되는 시기를 확인하세요.

SubscriptionSet.getState()를 사용하여 애플리케이션의 구독 세트 상태에 액세스할 수 있습니다.

참고

구독 상태 "완료"

구독 세트 상태 "완료" 는 "동기화가 완료됨" 또는 "모든 문서가 동기화됨" 을 의미하지 않습니다. "완료" 는 다음 두 가지를 의미합니다:

  • 구독이 현재 서버와 동기화되고 있는 활성 구독 세트가

  • 이제 구독이 서버로 전송될 때 구독과 일치했던 문서가 로컬 장치에 존재합니다. 여기에는 현재 구독과 일치하는 모든 문서가 반드시 포함되는 것은 아닙니다.

Realm SDK는 구독과 일치하는 모든 문서가 기기에 동기화되었는지 확인하는 방법을 제공하지 않습니다.

SUPERSEDED 다른 스레드가 구독 세트의 다른 인스턴스에 구독을 쓸 때 발생할 수 있는 SubscriptionSet.State 입니다. 상태가 SUPERSEDED 이 되면 구독 세트에 쓰려면 먼저 구독 세트의 새 인스턴스를 가져와야 합니다.

SubscriptionSet.update() 를 사용하여 구독을 업데이트할 수 있습니다. 이 예제에서는 MutableSubscriptionSet.addOrUpdate() 를 사용하여 'myfrog 구독'이라는 구독에 대한 쿼리를 업데이트합니다.

realm.getSubscriptions().update(new SubscriptionSet.UpdateCallback() {
@Override
public void update(MutableSubscriptionSet subscriptions) {
// to update a named subscription, create a replacement with
// the same name and add it to the subscription set
subscriptions.addOrUpdate(
Subscription.create("my frog subscription",
realm.where(Frog.class)
.equalTo("name",
"Benedict Cumberburger")));
}
});
realm.subscriptions.update { subscriptions ->
// to update a named subscription, create a replacement with
// the same name and add it to the subscription set
subscriptions.addOrUpdate(
Subscription.create(
"my frog subscription",
realm.where(Frog::class.java)
.equalTo(
"name",
"Benedict Cumberburger"
)
)
)
}

이름 없이 생성된 구독은 업데이트할 수 없습니다. 그러나 쿼리로 이름이 지정되지 않은 구독을 조회하고 구독 세트에서 제거한 다음 업데이트된 쿼리로 새 구독을 추가할 수 있습니다.

realm.getSubscriptions().update(new SubscriptionSet.UpdateCallback() {
@Override
public void update(MutableSubscriptionSet subscriptions) {
// to update an unnamed subscription, remove it from the
// subscription set, then add your new query to the set
Subscription mySubscription = subscriptions.find(realm.where(Frog.class)
.equalTo("species",
"cane toad"));
subscriptions.remove(mySubscription);
subscriptions.addOrUpdate(
Subscription.create(
realm.where(Frog.class)
.equalTo("species",
"albino cane toad")));
}
});
realm.subscriptions.update { subscriptions ->
// to update an unnamed subscription, remove it from the
// subscription set, then add your new query to the set
val mySubscription =
subscriptions.find(
realm.where(
Frog::class.java
).equalTo(
"species",
"cane toad"
)
)
subscriptions.remove(mySubscription)
subscriptions.addOrUpdate(
Subscription.create(
realm.where(Frog::class.java)
.equalTo(
"species",
"albino cane toad"
)
)
)
}

구독을 제거하려면 다음과 같이 하세요:

  • 단일 구독 쿼리 제거

  • 특정 객체 유형에 대한 모든 구독을 제거합니다.

  • 모든 구독 삭제

구독 쿼리를 제거하면 Realm은 클라이언트 장치에서 쿼리와 일치하는 동기화된 데이터를 비동기적으로 제거합니다.

MutableSubscriptionSet.remove() 를 사용하여 특정 구독 쿼리를 제거할 수 있습니다. 이름으로 구독을 조회한 다음 반환된 구독을 remove() 에 전달하거나 구독 이름을 remove() 에 직접 전달할 수 있습니다.

realm.getSubscriptions().update(new SubscriptionSet.UpdateCallback() {
@Override
public void update(MutableSubscriptionSet subscriptions) {
Subscription mySubscription = subscriptions.find("mySubscription");
subscriptions.remove(mySubscription);
}
});
realm.subscriptions.update { subscriptions ->
val mySubscription =
subscriptions.find("mySubscription")
subscriptions.remove(mySubscription)
}

특정 객체 유형에 대한 모든 구독을 제거하려면 removeAll() 메서드에 클래스를 전달합니다.

realm.getSubscriptions().update(new SubscriptionSet.UpdateCallback() {
@Override
public void update(MutableSubscriptionSet subscriptions) {
subscriptions.removeAll(Frog.class);
}
});
realm.subscriptions.update { subscriptions ->
subscriptions.removeAll(
Frog::class.java
)
}

구독 설정하다 에서 모든 구독을 제거 하려면 인수 없이 removeAll() 을 사용합니다.

경고

모든 구독을 제거하고 새 구독을 추가하지 않으면 오류가 발생합니다. flexible sync 구성으로 열린 영역의 경우, 서버와 동기화하려면 하나 이상의 구독이 필요합니다.

realm.getSubscriptions().update(new SubscriptionSet.UpdateCallback() {
@Override
public void update(MutableSubscriptionSet subscriptions) {
subscriptions.removeAll();
}
});
realm.subscriptions.update { subscriptions -> subscriptions.removeAll() }

앱에 인덱싱된 쿼리 가능 필드 를 추가하면 강력하게 분할된 데이터에 대한 간단한 쿼리의 성능을 향상시킬 수 있습니다. 예를 들어 user_id == $0, “641374b03725038381d2e1fb” 와 같이 쿼리가 데이터를 기기, 스토어 또는 사용자에 강력하게 매핑하는 앱은 인덱싱된 쿼리 가능 필드의 좋은 후보입니다. 그러나 인덱싱된 쿼리 가능 필드에는 쿼리 구독에 사용하기 위한 특정 요구 사항이 있습니다.

  • 인덱싱된 쿼리 가능 필드는 모든 구독 쿼리에서 사용해야 합니다. 쿼리에서 누락되어서는 안 됩니다.

  • 인덱싱된 쿼리 가능 필드는 구독 쿼리에서 상수에 대해 == 또는 IN 비교를 한 번 이상 사용해야 합니다. 예를 들어 user_id == $0, "641374b03725038381d2e1fb" 또는 store_id IN $0, {1,2,3}입니다.

인덱싱된 쿼리 가능 필드가 == 또는 IN을 사용하여 상수와 한 번 이상 직접 비교되는 경우, 선택적으로 AND 비교를 포함할 수 있습니다. 예를 들어 store_id IN {1,2,3} AND region=="Northeast" 또는 store_id == 1 AND (active_promotions < 5 OR num_employees < 10) 입니다.

인덱싱된 쿼리 가능 필드에 대한 유효하지 않은 Flexible Sync 쿼리에는 다음과 같은 쿼리가 포합됩니다.

  • 인덱싱된 쿼리 가능 필드가 AND를 나머지 쿼리와 함께 사용하지 않는 경우.예를 들어 store_id IN {1,2,3} OR region=="Northeast"AND 대신 OR을 사용하므로 유효하지않습니다. 마찬가지로 store_id == 1 AND active_promotions < 5 OR num_employees < 10AND가 전체 쿼리가 아니라 옆에 있는 용어에만 적용되므로 유효하지 않습니다.

  • 인덱싱된 쿼리 가능 필드가 동등 연산자에 사용되지 않는 경우.예를 들어 store_id > 2 AND region=="Northeast"> 연산자만 인덱싱된 쿼리 가능 필드에 사용하고 동등 비교는 없기 때문에 유효하지 않습니다.

  • 인덱싱된 쿼리 가능 필드가 쿼리에서 완전히 누락된 경우.예를 들어region=="Northeast 또는 truepredicate는 인덱싱된 쿼리 가능 필드를 포함하지 않으므로 유효하지 않습니다.

Flexible Sync는 RQL 연산자를 사용할 때 몇 가지 제한 사항이 있습니다. 동기화할 데이터를 결정하는 쿼리 구독 을 작성할 때 서버는 이러한 쿼리 연산자를 지원하지 않습니다. 그러나 전체 RQL 기능을 사용하여 클라이언트 애플리케이션에서 동기화된 데이터 세트를 쿼리할 수 있습니다.

연산자 유형
지원되지 않는 연산자
집계 연산자
@avg, @count, @max, @min, @sum
쿼리 접미사
DISTINCT, SORT, LIMIT

대소문자를 구분하지 않는 쿼리([c])은(는) 인덱스를 효과적으로 사용할 수 없습니다. 대소문자를 구분하지 않는 쿼리는 성능 문제를 일으킬 수 있으므로 사용하지 않는 것이 좋습니다.

Flexible Sync는 배열 필드에 대해 @count만 지원합니다.

Flexible Sync는 IN 연산자를 사용하여 목록 쿼리를 지원합니다.

상수 목록을 쿼리하여 쿼리 가능 필드 값이 포함되어 있는지 확인할 수 있습니다:

// Query a constant list for a queryable field value
"priority IN { 1, 2, 3 }"

쿼리 가능한 필드에 배열 값이 있는 경우 해당 에 상수 값이 포함되어 있는지 쿼리할 수 있습니다.

// Query an array-valued queryable field for a constant value
"'comedy' IN genres"

경고

Flexible Sync 쿼리에서는 두 목록을 비교하는 것이 불가능합니다. 이 구문은 Flexible Sync 쿼리 외에는 유효한 Realm Query Language 구문이라는 점에 유의하세요.

// Invalid Flexible Sync query. Do not do this!
"{'comedy', 'horror', 'suspense'} IN genres"
// Another invalid Flexible Sync query. Do not do this!
"ANY {'comedy', 'horror', 'suspense'} != ANY genres"

Flexible Sync는 내장된 객체 또는 링크의 속성에 대한 쿼리를 지원하지 않습니다. 예시: obj1.field == "foo"

구독 설정하다 에 있는 특정 쿼리 구독 의 크기 제한256 KB 입니다. 이 제한을 초과하면 LimitsExceeded 오류가 발생합니다.

돌아가기

구성 & 동기화된 Realm 열기