Core Data를 처음 다루면 이런 코드부터 마주하게 되죠 👇
final class DiaryCoreDataManager {
static let shared = DiaryCoreDataManager()
private init() {}
private lazy var persistentContainer: NSPersistentContainer = {
let container = NSPersistentContainer(name: "EmotionDiaryModel")
container.loadPersistentStores { _, error in
if let error = error {
LogManager.print(.error, "Core Data 초기화 실패: \(error.localizedDescription)")
}
}
return container
}()
private var context: NSManagedObjectContext {
persistentContainer.viewContext
}
func saveContext() {
guard context.hasChanges else { return }
do {
try context.save()
LogManager.print(.success, "Core Data 저장 성공")
} catch {
LogManager.print(.error, "Core Data 저장 실패: \(error.localizedDescription)")
}
}
}
처음 보면 이름도 낯설고, 구조도 복잡해 보입니다.
하지만 사실 이 세 가지 요소만 알면 완전히 이해할 수 있습니다 👇
🧩 Core Data의 세 가지 핵심
| 구성요소 | 역할 | 비유 |
| 🏗️ persistentContainer | Core Data의 “엔진” (전체 저장소 관리) | 📦 저장소 관리자 |
| 🧠 context | 실제 데이터 CRUD를 수행하는 공간 | ✏️ 작업 메모장 |
| 💾 saveContext() | 변경사항을 실제 DB에 반영 | 💡 저장 버튼 |
이 세 가지가 Core Data의 모든 동작을 담당합니다.
🏗️ 1️⃣ persistentContainer — “Core Data의 엔진”
private lazy var persistentContainer: NSPersistentContainer = {
let container = NSPersistentContainer(name: "EmotionDiaryModel")
container.loadPersistentStores { _, error in
if let error = error {
LogManager.print(.error, "Core Data 초기화 실패: \(error.localizedDescription)")
}
}
return container
}()
💡 설명
Core Data의 모든 핵심 구성요소(모델, 저장소, 컨텍스트) 를 자동으로 세팅하는 객체입니다.
이름 "EmotionDiaryModel" 은 .xcdatamodeld 파일 이름과 동일해야 합니다.
즉, persistentContainer는
📦 “데이터베이스 파일을 관리하고, Core Data를 구동시키는 엔진 역할”
을 합니다.
🧠 2️⃣ context — “작업 메모장”
private var context: NSManagedObjectContext {
persistentContainer.viewContext
}
💡 설명
context는 메모리 상에서 데이터를 조작하는 임시 공간이에요.
우리가 save, fetch, delete 같은 작업을 할 때 실제로 실행되는 곳이 바로 여기입니다.
📘 예시:
let diary = EmotionDiaryEntity(context: context)
diary.content = "오늘은 행복한 하루였어요." // 메모리상에서만 변경됨
아직 이 시점에서는 데이터베이스에 저장되지 않았어요.
메모리 속에서만 임시로 작업 중인 상태죠.
💾 3️⃣ saveContext() — “저장 버튼”
func saveContext() {
guard context.hasChanges else { return }
do {
try context.save()
LogManager.print(.success, "Core Data 저장 성공")
} catch {
LogManager.print(.error, "Core Data 저장 실패: \(error.localizedDescription)")
}
}
💡 설명
context 안에서 바뀐 데이터를 실제 데이터베이스(SQLite)에 반영하는 역할입니다.
context.hasChanges를 통해 변경사항이 있을 때만 저장합니다.
context.save()를 실행하면 Core Data가 내부적으로 SQLite 파일에 내용을 기록합니다.
즉,
💾 “메모장에서 쓴 내용을 실제 파일로 저장하는 과정”입니다.
🔄 전체 흐름 다이어그램
┌────────────────────────────────────────┐
│ EmotionDiaryModel.xcdatamodeld |
| (데이터 모델 정의) │
└────────────────────────────────────────┘
│
▼
┌────────────────────────────────────────┐
│ persistentContainer │
│ (Core Data 스택 구성: 모델 + 저장소 + 컨텍스트) │
└────────────────────────────────────────┘
│
▼
┌────────────────────────────────────────┐
│ context (임시 작업 공간) │
│ → 데이터 생성 / 수정 / 삭제 / 조회 │
└────────────────────────────────────────┘
│
▼
┌────────────────────────────────────────┐
│ saveContext() │
│ → 변경사항을 실제 DB(SQLite)에 반영 │
└────────────────────────────────────────┘
⚙️ 실무에서 중요한 추가 포인트
| 항목 | 설명 |
| ⚡ Lazy 초기화 | 앱 실행 시점에 바로 로드하지 않고, 실제 사용 시점에 초기화 (성능 향상) |
| 🔄 context.hasChanges | 변경이 있을 때만 저장해서 불필요한 I/O 방지 |
| 🧠 viewContext vs backgroundContext | viewContext: 메인 스레드용 / backgroundContext: 비동기 저장용 |
| 🔍 모델명 일치 | NSPersistentContainer(name:)의 이름은 .xcdatamodeld 파일명과 동일해야 함 |
| 🪵 에러 로깅 | LogManager나 print()를 통해 저장 실패 시 원인 파악 필수 |
💬 쉽게 비유하자면…
| Core Data 구성 | 비유 | 역할 |
| persistentContainer | 📦 “문서 보관함” | 실제 DB 파일 관리 |
| context | ✏️ “임시 메모장” | 데이터를 수정하는 공간 |
| saveContext() | 💾 “저장 버튼” | 수정된 내용을 파일에 기록 |
✨ 즉, Core Data는 "자동 저장"이 아니라
“메모장에서 편집 → 저장 버튼 누르기” 구조로 동작합니다.
✅ 한 줄 정리
🧠 context에서 데이터를 만들고,
💾 saveContext()로 영구 저장하며,
🏗️ persistentContainer가 그 전 과정을 관리한다.
'감정일기(가칭)' 카테고리의 다른 글
| 🧠 Swift Concurrency — “Capture of 'self' with non-sendable type” 완전 정리 (1) | 2025.10.19 |
|---|---|
| 💾 왜 Core Data의 Read는 반드시 async여야 할까? (0) | 2025.10.18 |
| ☁️ Core Data에서 Firebase로 확장하는 iOS 데이터 구조 설계 (0) | 2025.10.18 |
| 🧩 Core Data 매니저 네이밍, 어떻게 하는 게 좋을까? (0) | 2025.10.18 |
| 📒 감정일기 앱의 데이터 로딩 전략 설계 — 동기 로딩 vs 점진적 로딩(Pagination) (0) | 2025.10.17 |