apple/Docs, iOS, Swift

CloudKit(iCloud) 정리 이론 #2

lgvv 2024. 8. 6. 00:32

CloudKit(iCloud) 정리 이론 #2


CloudKit 정리 환경설정 #1

https://rldd.tistory.com/607
CloudKit 정리 이론 #2
https://rldd.tistory.com/619
CloudKit 정리 코드 예제 #3

https://rldd.tistory.com/631

 

Intro

- CloudKit Console 분석

- Schema

   - Indexes

   - Record Types

   - Security Roles

   - History

- Data

   - Records

   - Zones

   - Subscriptions - CKSyncEngine (iOS 17이후)

 

Schema

메타데이터

메타 데이터

 

 createdTimestamp: 생성한 시각 (DATE/TIME)

 createdUserRecordName: 레코드 생성한 식별자. (REFERENCE)

 ___etag: 레코드의 변경을 추적하기 위한 태그

 modifiedTimestamp: 수정한 시각 (DATE/TIME)

 modifiedUserRecordName: 마지막 수정한 사용자 (REFERENCE)

 recordName: 레코드 이름 (REFERENCE)

 

* REFERENCE 타입 설명: CloudKit에서 다른 레코드에 대한 참조. 이 필드를 통해 레코드 어떤 사용자가 생성했는지 알 수 있음.

 

Single Field Indexes는 특정 레코드 타입의 필드를 인덱싱하여 검색 성능을 향상시키는 기능

• 인덱스는 데이터베이스에서 검색할 때 빠른 조회를 가능.

 

빠른 검색: 인덱스가 설정된 필드에 대해 검색할 때 성능이 크게 향상. 특히, 대용량 데이터베이스에서 검색 시간이 줄어듬.

정렬: 인덱스를 사용하면 정렬된 결과를 빠르게 얻을 수 있음.

필터링: 쿼리에서 조건을 사용하여 데이터를 필터링할 때 유용.

 

설정하는 방법은 Shemea > Indexes에서 설정 이는 뒤에서 설명

 

 

레코드 필드

레코드 추가

 

레코드 이름을 지정하고 그에 맞는 타입을 설정

Encrypted가 붙은 타입은 CloudKit에서 사용자의 민감한 데이터를 보호하기 위해 암호화된 상태로 저장되는 필드 타입.

데이터는 CloudKit 서버에 암호화 된 형태로 저장되고, 필요시에만 복호화 된다.

 

(참고)

복호화 성능: 암호화된 필드는 복호화 과정이 필요해서 성능에 영향을 미칠 수 있음.

 

 

 

Schema

 

인덱스

Index



이는 데이터베이스에서 검색을 위해 사용하는 구조.

 

1. Queryable

 

설명: Queryable 속성은 필드가 쿼리에서 조건으로 사용될 수 있도록 인덱싱하는 설정.

 

용도: 특정 필드 값을 기준으로 레코드를 필터링하는 쿼리에서 사용.

예시: 사용자의 나이를 기준으로 30세 이상인 사용자를 검색하는 쿼리.

 

let predicate = NSPredicate(format: "age >= %d", 30)
let query = CKQuery(recordType: "User", predicate: predicate)

 

2. Sortable

 

설명: Sortable 속성은 필드가 쿼리 결과를 정렬하는 데 사용될 수 있도록 인덱싱하는 설정.

 

용도: 쿼리 결과를 특정 필드 값에 따라 오름차순 또는 내림차순으로 정렬하는 경우에 사용됩니다.

예시: 사용자의 이름을 알파벳 순서로 정렬하는 쿼리.

 

let query = CKQuery(recordType: "User", predicate: NSPredicate(value: true))
query.sortDescriptors = [NSSortDescriptor(key: "name", ascending: true)]

 

3. Searchable

 

설명: Searchable 속성은 필드가 텍스트 검색에서 사용될 수 있도록 인덱싱하는 설정.

 

용도: 텍스트 필드에서 키워드 검색을 수행하는 경우에 사용됩니다.

예시: 사용자의 소개 글에서 특정 키워드를 검색하는 쿼리.

let predicate = NSPredicate(format: "self contains %@", "developer")
let query = CKQuery(recordType: "User", predicate: predicate)

 

Security Roles

시큐리티 롤 예제 스크린샷

 

1. Creator

 

설명: 레코드를 생성한 사용자.

권한: 기본적으로 자신이 생성한 레코드에 대한 읽기 및 쓰기 권한을 가짐.

사용 예시: 사용자가 자신의 데이터를 생성하고, 해당 데이터에만 접근할 수 있도록 제한할 때 사용

 

2. Owner

 

설명: 레코드의 소유자.

권한: 레코드에 대한 모든 권한(읽기, 쓰기, 삭제)을 가짐.

사용 예시: 사용자가 자신의 데이터를 완전히 관리할 수 있도록 하고자 할 때 사용.

 

3. Authenticated

 

설명: Apple ID로 인증된 사용자.

권한: 인증된 모든 사용자에게 적용되는 권한을 정의.

사용 예시: 앱 사용자가 인증된 상태에서만 특정 데이터에 접근할 수 있도록 제한하고자 할 때 사용.

 

4. World

 

설명: 모든 사용자. 인증 여부와 관계없이 접근할 수 있는 권한.

권한: 모든 사용자에게 적용되는 권한을 정의.

사용 예시: 모든 사용자가 접근할 수 있는 공용 데이터를 만들고자 할 때 사용.

 

Schema History

그냥 변경 히스토리 볼 수 있음.


Records

Database는 총 3가지로 분류.

 

1. Public Database

 

설명:

Public Database는 모든 사용자가 접근할 수 있는 공용 데이터베이스.
모든 사용자가 읽을 수 있고, 애플리케이션의 공용 데이터나 모든 사용자에게 공유해야 하는 데이터를 저장하는 데 적합

 

특징:

모든 사용자가 접근 가능

읽기 권한은 기본적으로 모든 사용자에게 허용됨

쓰기 권한은 애플리케이션 설정에 따라 달라질 수 있음

사용 예시: 공용 게시판, 공용 설정 데이터, 공용 컨텐츠 목록

 

2. Private Database

 

설명:

Private Database는 각 사용자마다 별도로 제공되는 개인 데이터베이스.
해당 사용자가 인증된 경우에만 접근할 수 있습니다. 개인 정보나 사용자별 데이터를 저장하는 데 적합.

 

특징:

사용자별로 분리된 데이터베이스

데이터는 각 사용자의 iCloud 계정과 연계

읽기 및 쓰기 권한은 기본적으로 해당 사용자에게만 허용

사용 예시: 개인 메모, 사용자 설정, 개인 파일 저장

 

3. Shared Database

 

설명:

Shared Database는 사용자가 다른 사용자와 공유할 수 있는 데이터베이스.
초대받은 사용자들만 접근할 수 있으며, 협업이나 데이터 공유 기능을 구현하는 데 적합합니다.

 

특징:

데이터를 특정 사용자 그룹과 공유 가능

공유된 레코드에 대해 읽기 및 쓰기 권한을 조정 가능

사용 예시: 공유 프로젝트, 공동 작업 문서, 공유 일정

 

Zone

CloudKit Zones는 레코드를 그룹화하고, 동시성 및 충돌 관리, 백업 및 복원, 효율적인 동기화 등 다양한 면에서 유용.

존 분리 예시


1. 효율적인 동기화

 

설명: Zone 단위로 데이터를 동기화할 수 있음. 이는 전체 데이터베이스를 동기화하는 것보다 효율적.

 

장점: 특정 Zone의 데이터만 동기화함으로써 네트워크 트래픽과 동기화 시간을 절약할 수 있음.

예시: 특정 프로젝트나 카테고리의 데이터만 동기화가 필요할 때 해당 Zone만 동기화.

(참고)
코드로 작성해보면 알겠지만, CloudKit에서 데이터 일정 수준 이상으로 동기화하는데 생각보다 시간이 오래걸림

 

2. 백업 및 복원

 

설명: Zone을 나누어 관리하면 Zone 단위로 데이터를 백업하고 복원할 수 있음.

 

장점: 특정 Zone의 데이터를 손쉽게 백업하고 필요할 때 복원할 수 있어 데이터 복구 작업이 용이.

예시: 중요한 데이터가 저장된 Zone을 주기적으로 백업하고, 문제가 발생했을 때 해당 Zone만 복원할 수 있음.

(참고)

개인 앱에서 private database에 백업 데이터 만들 때 zone으로 처리할 때 용이했음.

 

3. 데이터 분할 및 정리

 

설명: Zone을 사용하여 데이터를 논리적으로 그룹화하고 관리.

 

장점: 데이터베이스를 논리적인 구획으로 나누어 관리하면 데이터 구조가 명확해지고 유지보수가 쉬움.

예시: 프로젝트별, 사용자별, 기능별로 Zone을 나누어 데이터를 관리할 수 있음.

(참고)

개인 앱에서 (메모, 캘린더)를 같은 Record로 운영하고 Zone을 나누어서 관리

 

4. 성능 향상

 

설명: Zone을 사용하면 특정 Zone의 데이터에만 접근할 수 있어 데이터베이스 쿼리 성능이 향상.

 

장점: 필요한 데이터에만 접근함으로써 불필요한 데이터 접근을 줄이고, 쿼리 속도를 향상가능.

예시: 사용자 인터페이스에서 특정 Zone의 데이터만 표시해야 할 때 해당 Zone에 대해 쿼리를 수행하여 빠르게 데이터 가져올 수 있음.

(참고)

데이터 좀만 커져도 불러오는데 오래걸림. 전체 로드할 때 페이지네이션 둬서 limit 20정도로 처리했음.

 

Subscriptions

Subscriptions는 특정 조건에 맞는 레코드가 생성, 수정, 삭제될 때 사용자에게 알림을 보내는 기능. 이 기능을 통해 실시간으로 데이터 변경 사항을 감지하고, 사용자에게 알림을 제공할 수 있음.
Subscriptions는 다양한 유형이 있으며, 이를 통해 다양한 시나리오에 맞게 알림을 설정할 수 있음.

구독

Subscription 유형

 

CloudKit에는 다음과 같은 주요 Subscription 유형이 있음.

 

1. Query Subscription

 

설명:

Query Subscription은 특정 조건에 맞는 레코드에 대해 알림을 설정.
사용자가 설정한 쿼리에 따라 레코드가 추가, 수정, 삭제될 때 알림을 받음.

 

특징:

특정 조건에 맞는 레코드에 대한 알림 설정

NSPredicate를 사용하여 조건 지정 가능

사용 예시: 특정 사용자의 새로운 게시물, 특정 카테고리의 데이터 업데이트

 

let predicate = NSPredicate(format: "category == %@", "News")
let subscription = CKQuerySubscription(
    recordType: "Post",
    predicate: predicate,
    options: [.firesOnRecordCreation, .firesOnRecordUpdate, .firesOnRecordDeletion]
)

let notificationInfo = CKSubscription.NotificationInfo()
notificationInfo.alertBody = "A new post has been added or updated."
subscription.notificationInfo = notificationInfo

let database = CKContainer.default().publicCloudDatabase
database.save(subscription) { savedSubscription, error in
    if let error = error {
        print("Error saving subscription: \(error.localizedDescription)")
    } else {
        print("Subscription saved successfully.")
    }
}

 

firesOnRecordCreation: 레코드가 새로 생성될 때 알림을 트리거

firesOnRecordUpdate: 레코드가 수정될 때 알림을 트리거

firesOnRecordDeletion: 레코드가 삭제될 때 알림을 트리거

 

 

2. Record Zone Subscription

 

설명:

Record Zone Subscription은 특정 Zone 내에서 발생하는 모든 레코드 변경 사항에 대해 알림을 설정.

해당 Zone에서 레코드가 생성, 수정, 삭제될 때 알림을 받음.

 

특징:

특정 Zone 내의 모든 레코드 변경에 대한 알림 설정

Zone 단위로 레코드 변경 사항 감지

사용 예시: 특정 프로젝트나 그룹의 데이터 변경 사항

 

let zoneID = CKRecordZone.ID(zoneName: "CustomZone", ownerName: CKCurrentUserDefaultName)
let subscription = CKRecordZoneSubscription(zoneID: zoneID)

let notificationInfo = CKSubscription.NotificationInfo()
notificationInfo.alertBody = "Records in the zone have been modified."
subscription.notificationInfo = notificationInfo

let database = CKContainer.default().privateCloudDatabase
database.save(subscription) { savedSubscription, error in
    if let error = error {
        print("Error saving subscription: \(error.localizedDescription)")
    } else {
        print("Subscription saved successfully.")
    }
}

 

3. Database Subscription

 

설명:

Database Subscription은 데이터베이스 전체에서 발생하는 모든 레코드 변경 사항에 대해 알림을 설정.
주로 Private Database에서 사용되며, 데이터베이스 수준의 변경 사항을 감지.

 

특징:

데이터베이스 전체의 레코드 변경에 대한 알림 설정

Private Database에서 주로 사용

사용 예시: 사용자의 모든 데이터 변경 사항 추적

 

let subscription = CKDatabaseSubscription(subscriptionID: "database-subscription")

let notificationInfo = CKSubscription.NotificationInfo()
notificationInfo.alertBody = "Database records have been modified."
subscription.notificationInfo = notificationInfo

let database = CKContainer.default().privateCloudDatabase
database.save(subscription) { savedSubscription, error in
    if let error = error {
        print("Error saving subscription: \(error.localizedDescription)")
    } else {
        print("Subscription saved successfully.")
    }
}