동기화 Realm 구성 및 열기 - Swift SDK
이 페이지의 내용
동기화된 Realms
각각 로컬 데이터 사본을 가진 여러 기기 간에 데이터를 자동으로 동기화하도록 영역을 구성할 수 있습니다. 동기화된 영역은 로컬 전용 영역과 다른 구성을 사용하며 동기화 프로세스를 처리하기 위해 Atlas App Services 백엔드가 필요합니다.
애플리케이션은 오프라인 상태에서도 항상 로컬에서 동기화된 영역 객체를 생성, 수정 및 삭제 수 있습니다. 네트워크 연결이 가능할 때마다 Realm SDK 는 애플리케이션 서버 에 대한 연결을 열고 다른 클라이언트와 변경 사항을 동기화합니다. Atlas Device Sync 프로토콜 및 서버 측 운영 변환은 일부 변경 사항이 오프라인에서 발생했거나 순서대로 수신되지 않은 경우에도 영역 의 완전히 동기화된 모든 인스턴스가 정확히 동일한 데이터를 볼 수 있도록 보장합니다.
동기화 Realms과 비동기화 Realms 비교
동기화된 영역은 동기화되지 않은 로컬 영역과 다음과 같은 몇 가지가 다릅니다.
동기화된 영역은 백엔드 App Services App과 변경 사항을 동기화하려고 시도하지만, 비동기화 영역은 동기화를 시도하지 않습니다.
동기화된 영역은 인증된 사용자가 액세스할 수 있지만, 동기화되지 않은 영역은 사용자 또는 인증 개념이 없습니다.
동기화된 영역을 사용하면 영역을 열기 전에 업데이트를 다운로드하도록 다운로드 동작을 지정할 수 있습니다. 그러나 영역을 열기 전에 변경 사항을 다운로드하도록 요구하려면 사용자가 온라인 상태여야 합니다. 동기화되지 않은 영역은 항상 오프라인으로 사용할 수 있습니다.
동기화되지 않은 영역 에서 동기화된 영역 으로 데이터를 복사하거나 그 반대로 복사할 수 있지만 동기화 되지 않은 영역 은 동기화할 수 없습니다. 동기화되지 않은 영역 을 동기화된 영역 으로 변환하려면 로컬 전용 앱을 동기화가 활성화된 앱으로 마이그레이션에설명된 프로세스 를 따르세요.
동기화되지 않은 영역을 구성하고 여는 방법에 대한 자세한 내용은 영역 구성 및 열기 - Swift SDK를 참조하세요.
동기화된 Realm 열기
동기화된 영역을 여는 일반적인 절차는 다음과 같습니다.
동기화 구성 생성하기
구성과 동기화된 사용자의 영역 열기
인증 시 기기의 sync_metadata.realm
파일에 사용자 자격 증명을 캐시합니다.
인증 후 동기화 영역을 열면 로그인 절차를 우회하고 이미 생성한 것과 동일한 동기화 구성을 사용하여 동기화 영역 열기로 바로 이동할 수 있습니다.
캐시된 자격 증명을 사용하면 다음을 수행할 수 있습니다.
에 있는 데이터와 동기화된 영역을 즉시 엽니다. 이 방법은 오프라인 또는 온라인에서 사용할 수 있습니다.
앱에서 변경 사항을 다운로드한 후 동기화된 영역을 엽니다. 이를 위해서는 사용자가 인터넷에 연결되어 있어야 합니다.
Flexible Sync를 사용하는 경우 flexibleSyncConfiguration()
을(를) 사용하여 동기화된 영역을 엽니다.
팁
앱이 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. 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에는 구독이 필요합니다.
메모리에서 동기화된 Realm 열기
버전 10.46.0의 새로운 기능
.realm
파일이나 관련 보조 파일을 생성하지 않고 동기화된 데이터베이스를 메모리에서 완전히 열 수 있습니다. 대신 SDK는 영역이 열려 있는 동안 메모리에 객체를 저장하고 모든 인스턴스가 닫히면 즉시 삭제합니다.
메모리에서 동기화된 영역을 열려면 영역 구성의 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
동기화된 Realm을 다른 동기화 사용자로 열기
버전 10.23.0의 새로운 기능
동기화된 영역을 다른 동기화 사용자로 열려면 writeCopy(configuration: ) 메서드를 사용하여 새 사용자의 동기화 구성과 함께 사용할 동기화된 영역의 복사본을 만들 수 있습니다. 아래 예시에서는 다른 동기화 구성과 함께 사용할 수 있는 기존 데이터가 모두 포함된 동기화 영역의 복사본을 만듭니다.
새 동기화 사용자의 구성을 위한 영역을 복사한 후에는 복사본을 해당 사용자의 동기화된 영역으로 열 수 있습니다.
참고
동일 유형 동기화만 가능
이 방법은 다른 파티션 기반 동기화 사용자를 위한 파티션 기반 동기화 구성 복사 또는 다른 Flexible Sync 사용자를 위한 Flexible Sync 구성 복사만 지원합니다. 이 방법을 사용하여 파티션 기반 동기화 영역과 Flexible Sync 영역 간에 또는 그 반대로 변환할 수 없습니다.
팁
앱이 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. 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 열기
Swift 동시성 기능을 사용하여 동기화된 영역을 행위자 격리 영역으로 열 수 있습니다.
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) }
행위자 격리형 영역 작업에 대한 자세한 내용은 행위자와 영역 사용 - Swift SDK를 참조하세요.
열기 전에 변경 사항 다운로드
버전 10.15.0의 새로운 기능.
Swift SDK로 동기화된 영역을 열 때 downloadBeforeOpen
매개변수를 전달하여 영역을 열기 전에 앱에서 변경 세트를 다운로드할지 여부를 지정할 수 있습니다. 이 매개 변수는 OpenBehavior
열거형의 사례를 허용합니다.
never
: 기기에서 즉시 영역을 엽니다. 사용자가 인터넷에 연결되어 있을 때 백그라운드에서 변경 사항을 다운로드하되 영역 열기를 차단하지 않도록 합니다.always
: 영역을 열 때마다 변경 사항을 확인합니다. 사용자가 인터넷에 연결되어 있어야 합니다.once
: 영역을 처음 열기 전에 데이터를 다운로드하지만 이후 열 때 변경 사항을 다운로드하지 않고 열 수 있습니다. 이렇게 하면 초기 데이터로 영역을 채울 수 있지만 이후 열 때 오프라인 우선 기능을 사용할 수 있습니다.
팁
앱이 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 을 열기 전에 클라이언트 앱에서 변경 사항을 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)")