문서 메뉴

문서 홈애플리케이션 개발Atlas Device SDK

동기화 Realm 구성 및 열기 - Swift SDK

이 페이지의 내용

  • 동기화된 Realms
  • 동기화 Realms과 비동기화 Realms 비교
  • 동기화된 Realm 열기
  • 메모리에서 동기화된 Realm 열기
  • 동기화된 Realm을 다른 동기화 사용자로 열기
  • Swift 동시성 기능으로 Realm 열기
  • 열기 전에 변경 사항 다운로드
  • 오프라인으로 동기화된 Realm 열기

각각 로컬 데이터 사본을 가진 여러 기기 간에 데이터를 자동으로 동기화하도록 영역을 구성할 수 있습니다. 동기화된 영역은 로컬 전용 영역과 다른 구성을 사용하며 동기화 프로세스를 처리하기 위해 Atlas App Services 백엔드가 필요합니다.

애플리케이션은 오프라인 상태에서도 항상 로컬에서 동기화된 Realm 객체를 생성, 수정 및 삭제할 수 있습니다. 네트워크 연결이 가능할 때마다 Realm SDK는 애플리케이션 서버에 대한 연결을 열고 다른 클라이언트와 변경 사항을 동기화합니다. Atlas Device Sync 프로토콜 과 서버 측 운영 변환은 일부 변경 사항이 오프라인에서 발생했거나 순서가 잘못되었더라도 Realm의 완전히 동기화된 모든 인스턴스가 정확히 동일한 데이터를 볼 수 있도록 보장합니다.

동기화 구성 및 사용 방법 알아보기

App Services 앱에서 동기화를 설정하는 방법을 포함하여 Device Sync에 대한 자세한 내용은 데이터 동기화를 참조하세요.

동기화된 영역은 동기화되지 않은 로컬 영역과 다음과 같은 몇 가지가 다릅니다.

  • 동기화된 영역은 백엔드 App Services App과 변경 사항을 동기화하려고 시도하지만, 비동기화 영역은 동기화를 시도하지 않습니다.

  • 동기화된 영역은 인증된 사용자가 액세스할 수 있지만, 동기화되지 않은 영역은 사용자 또는 인증 개념이 없습니다.

  • 동기화된 Realm을 사용하면 Realm을 열기 전에 업데이트를 다운로드 하도록 다운로드 동작을 지정할 수 있습니다. 그러나 Realm을 열기 전에 변경 사항을 다운로드하려면 사용자가 온라인 상태여야 합니다. 동기화되지 않은 Realm은 항상 오프라인에서 사용할 수 있습니다.

동기화되지 않은 영역에서 동기화된 영역으로 또는 그 반대로 데이터를 복사할 수는 있지만, 동기화되지 않은 영역은 동기화할 수 없습니다.

동기화되지 않은 Realm을 구성하고 여는 방법에 대한 자세한 내용은 영역 구성 및 열기 - Swift SDK를 참조하세요.

다음도 참조하세요.

파티션 기반 동기화 Realm을 여는 방법에 대한 자세한 내용은 파티션 기반 동기화 영역 열기를 참조하세요.

동기화된 Realm을 여는 일반적인 절차는 다음과 같습니다.

  1. 사용자 인증하기

  2. 동기화 구성 생성하기

  3. 구성과 동기화된 사용자의 Realm 열기

인증 시 기기의 sync_metadata.realm 파일에 사용자 자격 증명을 캐시합니다.

인증 후 동기화 Realm을 열면 로그인 절차를 우회하고 이미 생성한 것과 동일한 동기화 구성을 사용하여 동기화 Realm 열기로 바로 이동할 수 있습니다.

캐시된 자격 증명을 사용하면 다음을 수행할 수 있습니다.

  • 에 있는 데이터와 동기화된 영역을 즉시 엽니다. 이 방법은 오프라인 또는 온라인에서 사용할 수 있습니다.

  • 앱에서 변경 사항을 다운로드한 후 동기화된 Realm을 엽니다. 이를 위해서는 사용자가 인터넷에 연결되어 있어야 합니다.

Flexible Sync를 사용하는 경우 flexibleSyncConfiguration()을(를) 사용하여 동기화된 Realm을 엽니다.

앱이 async/await 컨텍스트에서 Realm에 액세스하는 경우 코드를 @MainActor(으)로 표시하여 스레드 관련 충돌을 방지합니다.

let realm = try await openFlexibleSyncRealm()
// Opening a realm and accessing it must be done from the same thread.
// Marking this function as `@MainActor` avoids threading-related issues.
@MainActor
func openFlexibleSyncRealm() async throws -> Realm {
let app = App(id: APPID)
let credentials = emailPasswordCredentials(app: app)
let user = try await app.login(credentials: credentials)
var config = user.flexibleSyncConfiguration()
// Pass object types to the Flexible Sync configuration
// as a temporary workaround for not being able to add complete schema
// for a Flexible Sync app
config.objectTypes = [Task.self, Team.self]
let realm = try await Realm(configuration: config, downloadBeforeOpen: .always)
print("Successfully opened realm: \(realm)")
return realm
}

중요

Flexible Sync에는 구독이 필요합니다.

앱이 Device Sync를 사용하는 경우 구독을 하나 이상 추가할 때까지 Flexible Sync Realm을 사용할 수 없습니다. 구독을 추가하는 방법을 알아보려면 구독 추가하기를 참조합니다.

이는 데이터 수집 에는 적용되지 않습니다. AsymmetricObject 에 대한 구독을 생성할 수 없습니다.

버전 10.46.0의 새로운 기능

.realm 파일이나 관련 보조 파일을 생성하지 않고 동기화된 데이터베이스를 메모리에서 완전히 열 수 있습니다. 대신 SDK는 Realm이 열려 있는 동안 메모리에 객체를 저장하고 모든 인스턴스가 닫히면 즉시 삭제합니다.

메모리에서 동기화된 Realm을 열려면 Realm 구성의 inMemoryIdentifier 속성을 문자열 식별자로 설정합니다.

// Instantiate the app and get a user.
let app = App(id: APPID)
let user = try await app.login(credentials: Credentials.anonymous)
// Create a configuration.
var configuration = user.flexibleSyncConfiguration()
configuration.objectTypes = [Task.self, Team.self]
// Specify an in-memory identifier for the configuration.
configuration.inMemoryIdentifier = "YOUR-IDENTIFIER-STRING"
// Open a Realm with this configuration.
let realm = try await Realm(configuration: configuration)
print("Successfully opened realm: \(realm)")
// Add subscriptions and work with the realm

버전 10.23.0의 새로운 기능

동기화된 Realm을 다른 동기화 사용자로 열려면 writeCopy(configuration: ) 메서드를 사용하여 새 사용자의 동기화 구성과 함께 사용할 동기화된 Realm의 복사본을 만들 수 있습니다. 아래 예에서는 다른 동기화 구성과 함께 사용할 수 있는 기존 데이터가 모두 포함된 동기화된 Realm의 복사본을 만듭니다.

새 동기화 사용자의 구성을 위한 Realm을 복사한 후에는 복사본을 해당 사용자의 동기화된 Realm으로 열 수 있습니다.

참고

동일 유형 동기화만 가능

이 방법은 다른 파티션 기반 동기화 사용자를 위한 파티션 기반 동기화 구성 복사 또는 다른 Flexible Sync 사용자를 위한 Flexible Sync 구성 복사만 지원합니다. 이 방법을 사용하여 파티션 기반 동기화 Realm과 Flexible Sync Realm 간에 또는 그 반대로 변환할 수 없습니다.

앱이 async/await 컨텍스트에서 Realm에 액세스하는 경우 코드를 @MainActor(으)로 표시하여 스레드 관련 충돌을 방지합니다.

try await convertSyncedRealmForAnotherUser()
// Opening a realm and accessing it must be done from the same thread.
// Marking this function as `@MainActor` avoids threading-related issues.
@MainActor
func convertSyncedRealmForAnotherUser() async throws {
let app = App(id: YOUR_APP_SERVICES_APP_ID)
// Log in the user whose realm you want to use with another sync user
let frodoBaggins = try await app.login(credentials: Credentials.anonymous)
var frodoConfig = frodoBaggins.configuration(partitionValue: "Some Partition Value")
frodoConfig.objectTypes = [QsTask.self]
// Open the synced realm, and confirm it contains the data we want
// the other user to be able to access.
let frodoRealm = try await Realm(configuration: frodoConfig, downloadBeforeOpen: .always)
let frodoRealmTasks = frodoRealm.objects(QsTask.self)
let frodoSyncedTasks = frodoRealmTasks.where { $0.owner == "Frodo" }
XCTAssertEqual(frodoSyncedTasks.count, 3)
print("Successfully opened frodo's realm and it contains this many tasks: \(frodoSyncedTasks.count)")
// Log in as the user who will work with frodo's synced realm
let samwiseGamgee = try await app.login(credentials: Credentials.anonymous)
var samConfig = samwiseGamgee.configuration(partitionValue: "Some Partition Value")
samConfig.objectTypes = [QsTask.self]
// Specify an output directory for the copied realm
// We're using FileManager here for tested code examples.
guard let outputDir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { return }
// Append a file name to complete the path
let copiedRealmFilePath = outputDir.appendingPathComponent("copied.realm")
// Update the config file path to the path where you want to save the copied realm
samConfig.fileURL = copiedRealmFilePath
// Make a copy of frodo's realm that uses sam's config
try frodoRealm.writeCopy(configuration: samConfig)
// Open sam's realm, and see that it contains the same data as frodo's realm
let samRealm = try await Realm(configuration: samConfig)
let samRealmTasks = samRealm.objects(QsTask.self)
var samSyncedTasks = samRealmTasks.where { $0.owner == "Frodo" }
print("Successfully opened sam's realm and it contains this many tasks: \(samSyncedTasks.count)")
XCTAssertEqual(frodoSyncedTasks.count, samSyncedTasks.count)
// Add a task to sam's realm
let task = QsTask(value: ["name": "Keep an eye on that Gollum", "owner": "Sam"])
try! samRealm.write {
samRealm.add(task)
}
// See that the new task reflects in sam's realm, but not frodo's
samSyncedTasks = samRealmTasks.where { $0.owner == "Sam" }
XCTAssertEqual(samSyncedTasks.count, 1)
let samTasksInFrodoRealm = frodoRealmTasks.where { $0.owner == "Sam" }
XCTAssertEqual(samTasksInFrodoRealm.count, 0)
}

Swift 동시성 기능을 사용하여 동기화된 Realm을 행위자 격리 Realm으로 열 수 있습니다.

@MainActor
func mainThreadFunction() async throws {
// Initialize the app client and authenticate a user
let app = App(id: APPID)
let user = try await app.login(credentials: Credentials.anonymous)
// Configure the synced realm
var flexSyncConfig = user.flexibleSyncConfiguration(initialSubscriptions: { subs in
subs.append(QuerySubscription<Todo>(name: "all_todos"))})
flexSyncConfig.objectTypes = [Todo.self]
// Open and use the synced realm
let realm = try await Realm(configuration: flexSyncConfig, actor: MainActor.shared, downloadBeforeOpen: .always)
try await useTheSyncedRealm(realm: realm)
}

행위자 격리형 Realm 작업에 대한 자세한 내용은 행위자와 Realm 사용 - Swift SDK를 참조하세요.

버전 10.15.0의 새로운 기능.

Swift SDK로 동기화된 Realm을 열 때 downloadBeforeOpen 매개변수를 전달하여 Realm을 열기 전에 앱에서 변경 세트를 다운로드할지 여부를 지정할 수 있습니다. 이 매개 변수는 OpenBehavior 열거형의 사례를 허용합니다.

  • never: 기기에서 즉시 Realm을 엽니다. 사용자가 인터넷에 연결되어 있을 때 백그라운드에서 변경 사항을 다운로드하되 Realm 열기를 차단하지 않도록 합니다.

  • always: Realm을 열 때마다 변경 사항을 확인합니다. 사용자가 인터넷에 연결되어 있어야 합니다.

  • once: Realm을 처음 열기 전에 데이터를 다운로드하지만 이후 열 때 변경 사항을 다운로드하지 않고 열 수 있습니다. 이렇게 하면 초기 데이터로 Realm을 채울 수 있지만 이후 열 때 오프라인 우선 기능을 사용할 수 있습니다.

앱이 async/await 컨텍스트에서 Realm에 액세스하는 경우 코드를 @MainActor(으)로 표시하여 스레드 관련 충돌을 방지합니다.

func getRealmAfterDownloadingUpdates() async throws -> Realm {
let app = App(id: APPID)
let user = try await app.login(credentials: Credentials.anonymous)
var configuration = user.flexibleSyncConfiguration()
configuration.objectTypes = [FlexibleSync_Task.self, FlexibleSync_Team.self]
let realm = try await Realm(configuration: configuration, downloadBeforeOpen: .always)
print("Successfully opened realm after downloading: \(realm)")
return realm
}
let realm = try await getRealmAfterDownloadingUpdates()
print("The open realm is: \(realm)")
// Add subscription and work with the realm

Realm 애플리케이션이 사용자를 인증하면 사용자의 자격 증명을 캐시합니다. 기존 사용자 자격 증명을 확인하여 로그인 흐름을 우회하고 캐시된 사용자에 액세스할 수 있습니다. 이 기능을 사용하여 오프라인에서 Realm을 열 수 있습니다.

참고

최초 로그인 시에는 네트워크 연결이 필요합니다.

사용자가 앱에 가입하거나 클라이언트의 기존 계정으로 처음으로 로그인하는 경우 클라이언트가 네트워크에 연결되어 있어야 합니다. 캐시된 사용자 자격 증명을 확인하면 오프라인에서 Realm을 열 수 있지만 이는 사용자가 이전에 온라인 상태에서 로그인한 적이 있는 경우에만 가능합니다.

Realm 을 열기 전에 클라이언트 앱에서 변경 사항always 다운로드할 필요가 없는 경우에만 동기화된 Realm을 오프라인에서 열 수 있습니다.

앱이 async/await 컨텍스트에서 Realm에 액세스하는 경우 코드를 @MainActor(으)로 표시하여 스레드 관련 충돌을 방지합니다.

// Log the user into the backend app.
// The first time you login, the user must have a network connection.
func getUser() async throws -> User {
// Check for an existing user.
// If the user is offline but credentials are
// cached, this returns the existing user.
if let user = app.currentUser {
return user
} else {
// If the device has no cached user
// credentials, log them in.
let app = App(id: YOUR_APP_SERVICES_APP_ID)
let loggedInUser = try await app.login(credentials: Credentials.anonymous)
return loggedInUser
}
}
let user = try await getUser()
var configuration = user.configuration(partitionValue: "Some Partition Value")
// Open a Realm with this configuration.
// If you do not require the app to download updates
// before opening the realm, the realm just opens, even if
// offline.
let realm = try await Realm(configuration: configuration)
print("Successfully opened realm: \(realm)")
← 앱에 Device Sync 추가 - Swift SDK