Core Data
- 앱의 데이터를 안전하고 체계적으로 보관하고 관리하는 프레임워크
- 데이터들을 앱이 꺼지거나 휴대폰이 재부팅되어도 사라지지 않게 디스크에 저장하고, 필요할 때마다 검색, 수정, 삭제하는 역할
| 기능 | 설명 |
|---|
| 저장소 관리 | 데이터를 파일(DB)에 저장하고 꺼냄 |
| 검색 | 특정 조건에 맞는 데이터만 빠르게 가져옴 |
| 객체 관계 관리 | 관계형 모델 지원 (1\:N, N\:M 등) |
| 메모리 캐싱 | 메모리에 객체를 캐시해서 성능 향상 |
| Undo/Redo 지원 | 변경 이력 추적 기능도 있음 |
구성 요소
1. NSManagedObjectModel
- 창고 설계도
- 창고에 어떤 종류의 물건을(데이터 모델), 어떤 형태로 보관할지(속성) 정의하는 설계도(Entity)
- 예: '일기'라는 물건은 '제목', '내용', '날짜'라는 공간에 보관한다고 미리 설계하는 것
2. NSPersistentStoreCoordinator
- 창고 관리 총책임자
- 설계도를 보고 실제 창고(데이터 저장소)를 지휘하는 총책임자
- 작업 감독관(
Context)에게 "이 물건은 저 선반에 넣어!" 또는 "저 선반에 있는 물건 좀 가져와!"라고 지시하며 실제 창고와의 통신 담당
3. NSManagedObjectContext
- 작업 공간 & 작업 감독관
- 가장 중요한 직원이며, 우리가 직접 소통하는 대상
- 창고에서 물건을 가져오거나, 새 물건을 넣거나, 기존 물건을 바꿀 때, 우리는 이 감독관에게 요청(데이터를 CRUD하는 공간)
- 감독관은 '작업 공간(메모리)'이라는 임시 공간에 물건들을 올려두고 모든 작업을 처리한 뒤, "이제 이대로 창고에 반영해줘!"라고 총책임자에게 보고 (메모리 내 임시 작업 영역)
- 임시 공간에서 작업하기 때문에 실수로 작업을 잘못해도 쉽게 취소할 수 있고, 여러 작업을 한 번에 처리할 수 있어 효율적
4. NSPersistentContainer
- 창고 관리 사무소
- 위에서 설명한 설계도, 총책임자, 작업 감독관 등 모든 직원을 한 번에 채용하고 관리하는 편리한 사무소
- Core Data의 설정과 저장소를 초기화/관리
5. NSManagedObject
- 창고에 보관된 실제 물건
- 작업 감독관(
Context)이 관리하는, 창고에 저장되는 실제 데이터 객체
- 예: '7월 4일의 일기'가 하나의
NSManagedObject가 됨
💡 요약
- 우리는 작업 감독관(
Context)에게 "이런 물건(Object)을 설계도(Model)에 맞게 창고에 넣어줘/가져와줘" 라고 요청
- 나머지 복잡한 일은 알아서 처리해줌
UserDefaults vs Core Data
| 기능 | UserDefaults | Core Data |
|---|
| 용도 | 간단한 설정 저장 | 복잡한 데이터 관리 |
| 검색 조건 | 없음 | 있음 (필터링, 정렬 등) |
| 관계형 구조 | 없음 | 가능 |
| 성능 | 낮음 | 캐싱, 옵저버, 배치 처리로 빠름 |
| 데이터 양 | 소량 | 대량도 문제 없음 |
'할 일 목록' 앱
- CRUD: 데이터를 다루는 가장 기본적인 4가지 작업
- 생성(Create), 읽기(Read), 수정(Update), 삭제(Delete)
1. 할 일 생성 (Create)
Todo라는 Entity 생성
- 속성:
title: String, isDone: Bool
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
let newTodo = Todo(context: context)
newTodo.title = "코어 데이터 공부하기"
newTodo.isDone = false
do {
try context.save()
print("저장 성공!")
} catch {
print("저장 실패: \(error)")
}
2. 할 일 목록 불러오기 (Read)
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
do {
let todoList = try context.fetch(Todo.fetchRequest()) as! [Todo]
for todo in todoList {
print("할 일: \(todo.title ?? ""), 완료 여부: \(todo.isDone)")
}
} catch {
print("불러오기 실패: \(error)")
}
3. 할 일 수정 (Update)
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
let fetchRequest = Todo.fetchRequest()
fetchRequest.predicate = NSPredicate(format: "title == %@", "코어 데이터 공부하기")
do {
let specificTodoList = try context.fetch(fetchRequest)
if let todoToUpdate = specificTodoList.first {
todoToUpdate.isDone = true
try context.save()
print("수정 및 저장을 완료했습니다!")
} else {
print("해당하는 할 일을 찾지 못했습니다.")
}
} catch {
print("데이터를 찾거나 저장하는 데 실패했습니다: \(error)")
}
- 조건을
NSPredicate를 이용해 만들고, 작업 감독관(Context)에게 이 요청서와 함께 "물건을 찾아달라(fetch)"고 부탁
4. 할 일 삭제 (Delete)
context.delete(todoToDelete)
do {
try context.save()
print("삭제 성공!")
} catch {
print("삭제 실패: \(error)")
}