CloudKit(iCloud) 정리 이론 #2
CloudKit(iCloud) 정리 이론 #2
CloudKit 정리 환경설정 #1
https://rldd.tistory.com/607
CloudKit 정리 이론 #2
https://rldd.tistory.com/619
CloudKit 정리 코드 예제 #3
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
인덱스
이는 데이터베이스에서 검색을 위해 사용하는 구조.
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.")
}
}