Core Data Stack은 Core Data의 핵심으로 Core Data를 움직이는 객체들의 모음이다. 공식문서에서는 앱의 모델 계층을 관리하고 유지한다고 설명한다.
NSManagedObjectModel
은 앱에서 쓰이는 데이터 모델의 object 타입 (entity), 가질 수 있는 속성 (attribute), 이들 간의 관계(relation)를 나타낸다. Core Data Stack의 다른 곳에서는 해당 model을 사용해 object를 만들고 속성을 저장하고 데이터를 저장한다.
NSManagedObjectModel
을 데이터베이스 스키마로 생각할 수도 있지만, 이것은 Core Data Stack이 내부에서 SQLite를 사용하는 경우에만 해당될 수 있다. Core Data는 SQLite 이외에 다양한 영구 저장소를 사용하기 때문에 데이터베이스 스키마 보단 좀 더 일반적인 용어로 생각하는게 좋다.
NSPersistentStore
는 데이터를 읽고 쓰는 역할을 한다. Core Data는 기본적으로 4가지 유형의 NSPersistentStore를 제공하는데 3개는 atomic 성질을 띄고 1개는 non-atomic 성질을 띈다.
- 직렬화(Serialization)란?
: 객체를 직렬화하여 전송 가능한 형태로 만드는 것.
객체들의 데이터를 연속적인 데이터로 변형하여 Stream을 통해 데이터를 읽을 수 있도록 해주며 주로 객체들을 통째로 파일로 저장 및 전송하고 싶을때 사용- 역직렬화(Deserialization)란?
직렬화된 파일 등을 역으로 직렬화하여 다시 객체의 형태로 만드는 것.
저장된 파일을 읽거나 전송된 Stream 데이터를 읽어 원래 객체의 형태로 복원
아래는 저장소의 종류이다.
SQLite 데이터베이스에 의해 지원되며, Core Data가 지원하는 유일한 non-atomic 저장소로 가볍고 효율적인 메모리 공간을 제공한다. 대부분의 iOS 프로젝트에 적합하고 Xcode의 Core Data 템플릿은 기본적으로 이 저장소 타입을 사용한다.
XML 파일로 지원되며 모든 저장소 타입 중 읽기 가장 쉽다. 하지만 atomic 저장소이므로 메모리 공간이 클 수 있다. OS X에서만 해당 타입을 사용할 수 있다.
바이너리 데이터 파일로 지원되며, NSXMLStoreType과 마찬가지로 atomic 저장소이기 때문에 전체 바이너리 파일을 메모리에 로드해야 작업을 수행할 수 있다. 실제 애플 어플리케이션에서는 이 타입을 사용하는 것을 거의 찾을 수 없다.
메모리 내 영구 저장소 타입으로, 해당 타입은 실제로 영구적이지 않다. 앱을 종료하거나 디바이스를 끄면 해당 유형에 저장된 데이터가 사라진다. 이 저장소는 단위 테스트나 캐싱에 도움이 될 수 있다.
JSON 파일이나 CSV 파일로 지원되는 영구 저장소는 NSIncrementalStore를 상속받아 만들 수 있다. 해당 옵션이 궁금하다면 Apple의 Incremental Store Programming Guide 참고.
NSPersistentStoreCoordinator
는 object model과 store(저장소)를 연결하는 다리 역할을 한다. NSManagedObjectModel
을 이용하여 entity를 만들고, 이미 entity가 존재하고 있다면 NSPersistentStore로 부터 데이터를 로드한다.
NSPersistentStoreCoordinator
는 실제 DB 작업을 수행하는 곳이며, NSManagedObjectContext
의 요청에 대한 답을 주고, data에 대한 validation도 수행한다.
코드를 작성할 땐 항상 NSManagedObjectContext를 사용하기 때문에 context가 작동하는 방식을 꼭 이해해야한다.
let managedContext = employee.managedObjectContext
NSPersistentContainer
는 iOS 10부터 제공되며, 위 4가지 클래스를 모두 orchestrate하는 클래스이다. 우리는 4개의 stack 컴포넌트를 모두 연결하기 위해 보일러 플레이트 코드를 작성하지 않고, NSPersistentContainer
를 초기화 한 뒤 저장소를 로드하면된다.
@available(iOS 10.0, *)
open class NSPersistentContainer : NSObject {
open var name: String { get }
open var viewContext: NSManagedObjectContext { get }
open var managedObjectModel: NSManagedObjectModel { get }
open var persistentStoreCoordinator: NSPersistentStoreCoordinator { get }
// Creates a container using the model named `name` in the main bundle
public convenience init(name: String)
public init(name: String, managedObjectModel model: NSManagedObjectModel)
// Load stores from the storeDescriptions property that have not already been successfully added to the container. The completion handler is called once for each store that succeeds or fails.
open func loadPersistentStores(completionHandler block: @escaping (NSPersistentStoreDescription, Error?) -> Void)
}
Xcode에서 제공해주는 Core Data 템플릿을 이용하지 않고 직접 Core Data Stack을 구축해서 Core Data를 사용할 수 있다. Core Data가 어떻게 작동하는지 정말 알고 싶다면 자신의 Core Data Stack을 구축하는게 필수라고 한다.
자신의 Core Data Stack을 구축한다는게 엄청 대단한 일처럼 느껴질 수 있지만,
커스텀 wrapper를 만든다는 의미인 것 같다.
class CoreDataStack {
private let modelName: String
lazy var managedContext: NSManagedObjectContext = {
return self.storeContainer.viewContext
}()
init(modelName: String) {
self.modelName = modelName
}
private lazy var storeContainer: NSPersistentContainer = {
let container = NSPersistentContainer(name: self.modelName)
container.loadPersistentStores { _, error in
if let error = error as NSError? {
print("Unresolved error \(error), \(error.userInfo)")
}
}
return container
}()
func saveContext() {
guard managedContext.hasChanges else { return }
do {
try managedContext.save()
} catch let error as NSError {
print("Unresolved error \(error), \(error.userInfo)")
}
}
}
CoreDataStack 생성은 아래와 같이 할 수 있다.
lazy var coreDataStack = CoreDataStack(modelName: "ModelName")
해당 포스팅에서는 class의 이름을 CoreDataStack이라고 명명했지만 다른 포스팅에서는 PersistentManager, PersistentContainer등 다양한 이름으로 쓰인다.
https://aroundck.tistory.com/4733
raywenderlich - Core Data by Tutorials