Swift Data 간단 소개
Apple의 ORM (Object Relational Mapping)
ORM이란 Application 내부 객체와 DB 상의 객체를 연결시켜 주는 기술입니다. 어떤 언어나 어떤 DB를 써도 쉽게 찾아볼 수 있는 기술이지만, Apple의 레전드라면 이게 이번년도 (2023년)에 나왔다는 것입니다...
즉, Swift Data를 쓴 프로젝트를 구동하려면 iOS 15 이상이 필요하고, 자연스럽게 개인 토이 프로젝트 아니면 현실적으로 쓸 수 없습니다. 하지만 저는 토이 프로젝트를 하니 과감하게 iOS 15 미만은 고객에서 포기하고 써 봤습니다.
Swift Data를 쓰기 위해서는 3가지 단계를 거치면 됩니다.
- Model을 정의
- ModelContainer를 주입
- context나 Property Wrapper를 사용해서 CRUD
더 자세한건 Swift Data로 Core Data 대체하기를 참고해 주세요!
CloudKit도 간단 소개
간단한 NoSQL DB, Apple의 Firebase
Apple 제품들을 쓰면 자연스럽게 쓸 수 밖에 없는 기능이 iCloud입니다. 손쉽게 Apple 기기간 연동을 해 주고, 백업도 해 줍니다. CloudKit은 이 iCloud의 정보를 저장하는 곳이라고 생각하시면 됩니다.
개발자 입장에서 알아야 할 것은 CloudKit은 여러 독립된 Container로 이루어져 있고 (보통 1개의 앱이 1개의 Container를 사용합니다) Container 안에는 3종류의 Database가 있습니다. Public/Private/Shared인데, 각각 어떤 용도인지는 아래 표에 정리했습니다. RDS에서 Table을 정의하듯, CloudKit에서는 Record Type을 정의할 수 있습니다. Record Type에 맞게 데이터가 생성되면 그걸 Record라고 부릅니다.
용어 | 설명 |
Container | 앱 별로 CloudKit의 여러 요소들을 분리하기 위한 그릇이라고 생각하면 좋습니다 |
Public Database | 앱을 쓰는 모든 유저가 접근할 수 있는 데이터 |
Private Database | 유저 개인만 접근할 수 있는 데이터, 심지어 개발자/애플도 접근 불가! 유저의 iCloud 용량을 써서 개발자가 추가로 낼 돈도 없습니다 |
Shared Database | 특정 유저들끼리 제한적으로 접근 |
Record Type | 데이터의 형식 RDS에서는 Table, OOP에서는 객체 등으로 불립니다 미리 Property와 Data Type을 정해논 데이터 종류? 입니다 |
Record | Record Type에 맞춰 생성한 데이터 |
Index | Record 들을 더 빠르게 불러오기 위해 추가로 생성하는 데이터 읽기가 빨라지는 대신 추가/수정/삭제는 느려집니다 근데 읽기가 보통 압도적으로 많아서 오히려 이득입니다 |
CloudKit에는 개발용 환경 (Development) / 운영용 환경 (Product)이 나뉘어 있는데 운영용 환경에 1번 Deploy 된 Record Type은 무슨 일이 있어도 지울 수 없습니다. 실수로 Deploy 하셨다면 Container를 새로 만드셔야 합니다.
Swift Data에서 CloudKit을 우아하게 쓰기
Swift Data를 쓰더라도 CoreData를 쓸 때와 마찬가지로 CKContainer를 써서 CRUD를 하고자 하는 충돌에 사로잡힐 수도 있지만, 정말 그걸 원하시나요? Cloudkit을 직접 조작하고 싶지 않으시고, Private Database만 쓴다면 훨씬 더 간단한 해결책이 있습니다. CloudKit을 전혀 쓰지 않고 간단한 설정만으로 Swift Data에 iCloud 기능을 추가할 수 있습니다. (사실 Swift Data 내부적으로 CloudKit을 사용해 모든 처리를 하고 있는 거긴 합니다... 🥲)
- CloudKit을 활성화 시킨다
- (강력추천) CloudKit Console에서 직접 생성하지 말고 XCode에서 Container를 생성한다
- Background Modes에서 Remote Notifications 기능을 추가한다
1. CloudKit을 활성화 시킨다
우선 XCode를 열고 가장 위의 파일을 선택한 후, Signing & Capabilities에 가 주면 이런 화면이 나올 겁니다.
여기서 왼쪽 위의 + Capability를 눌러 iCloud를 추가한 후, CloudKit을 선택해 줍니다.
2. XCode에서 Container를 생성한다
물론 CloudKit Console (https://icloud.developer.apple.com/)에서 직접 Container를 생성할 수도 있지만, XCode에서 직접 생성하시길 강력히 추천드립니다. 제가 직접 생성해서 하려 하니깐 오류로 몇 시간을 고생했습니다... 물론 이미 기존에 Container가 있으면 그걸 연결하면 됩니다. (이 경우는 오류가 없길 기도메타... 🙏)
3. Background Modes에서 Remote Notifications 기능을 추가한다
마지막으로 Background Modes에서 Remote Notifications를 선택해 주면 됩니다. 이 기능은 알림을 위해 있는게 아니고, CloudKit의 데이터에 변경이 생겼을 때 App에 알려주는 역할을 합니다. iCloud의 동기화가 바로 이 기능으로 동작하는 겁니다!
Swift Data의 Model Container 초기화 할 때 CloudKit Database에 Record Type 자동으로 만들기
이렇게 간단히 CloudKit에 Container를 만들어도 아쉽게도 Swift Data의 struct와 CloudKit의 Record Type을 연결시키기 위해서는 CloudKit에 Swift Data의 struct에 맞게 Record Type을 만들어야 합니다.
이 과정에서 알아야 할 것도 많고 실수한 건덕지도 어마어마하게 많은데요. 그래서 저는 직접 만드는건 때려치고 검색을 반복한 끝에 CloudKit에 Swift Data에 맞는 Record Type을 만드는는 script를 짰습니다. 한 줄 한 줄 설명해 드리겠습니다!
let config = ModelConfiguration()
#if DEBUG
try! autoreleasepool {
let description = NSPersistentStoreDescription(url: config.url)
description.cloudKitContainerOptions = NSPersistentCloudKitContainerOptions(containerIdentifier: 컨테이너_이름)
description.shouldAddStoreAsynchronously = false
if let mom = NSManagedObjectModel.makeManagedObjectModel(for: [스위프트_데이터_모델들]) {
let container = NSPersistentCloudKitContainer(name: "tracker", managedObjectModel: mom)
container.persistentStoreDescriptions = [description]
container.loadPersistentStores { _, err in
if let err { fatalError(err.localizedDescription) }
}
try container.initializeCloudKitSchema()
}
}
#endif
- 우선 #if DEBUG와 #endif는 compile time에 이 코드를 포함시킬 지 말지 결정하는 아이입니다. 이 경우는 DEBUG일 때만 이 코드를 실행한다는 겁니다. Record Type을 생성하는 코드를 실제 앱에 포함시킬 이유는 전혀 없기에 개발 환경에서만 실행하도록 했습니다.
- 다음으로 CloudKit Container를 만들 때 Record Type 생성에 적합한 환경을 설정해 줍니다. 어떤 Container에 생성할지 알려주고, 굳이 async 하게 동작할 필요가 없으면 sync하게 동작하게 하고 등등입니다.
- 이제 ObjectModel을 만들고 여기서 config를 더해 CloudKit Container를 만듭니다.
- Persistence Store들을 load 해 주고, 에러가 나면 종료합니다. (Persistence Store가 없으면 Swift Data와 CloudKit 연동은 무용지물입니다!)
- 마지막으로 CloudKitSchema를 생성해 줍니다.
- 개발환경이기 때문에 오류 과정에서 바로 FatalError를 뱉도록 했습니다.
'👨💻 프로그래밍 > 🍎 iOS 개발' 카테고리의 다른 글
🍎 iOS에서 서버를 거치지 않고 알림 보내기 (UserNotifications) (0) | 2024.08.02 |
---|---|
🍎 XCTest로 Swift에서 Unit Test 하기 (0) | 2024.07.28 |
🍎 SwiftUI에서 숫자 입력하면 실시간으로 구분자(,) 붙이기 (0) | 2024.07.21 |
🍎 WidgetKit 이용해서 애플 위젯 개발하기 (0) | 2024.06.22 |
🍎 취미 iOS 앱 개발 후기 (0) | 2023.08.03 |