Dev.YoungKyu
YoungKyu's Devlog
전체 방문자
오늘
어제
  • 분류 전체보기
    • 부스트캠프
    • iOS
    • visionOS
    • Backend
    • 알고리즘
    • CS
    • Git
    • Python
    • 끄적끄적

블로그 메뉴

  • 홈
  • 🌝 티스토리 홈
  • ⭐️ 깃허브
  • 태그

공지사항

인기 글

최근 댓글

최근 글

태그

  • AutoLayout
  • SwiftUI
  • swift
  • ios
  • ImageResource
  • 오블완
  • jekyll
  • 티스토리챌린지
  • Git
  • 소프트웨어공학
  • AVAudioSession
  • image
  • CS
  • constraint
  • 모듈화
  • 알고리즘
  • Python
  • 소프트웨어 공학
  • if let
  • Swift5.7
  • boj
  • 백준
  • alamofire
  • 소프트웨어 테스트
  • 부스트캠프
  • Concurrency
  • guard
  • Optional
  • authenticationinterceptor
  • MVC

티스토리

hELLO · Designed By 정상우.
Dev.YoungKyu
iOS

CoreData 개요 및 동시성

CoreData 개요 및 동시성
iOS

CoreData 개요 및 동시성

2025. 5. 21. 14:47

CoreData란?

CoreData는 Apple에서 제공하는 객체 그래프(Object Graph) 및 영속성(Persistence) 관리 프레임워크입니다.
SQLite를 기반으로 로컬 데이터베이스로도 사용할 수 있지만, 단순히 데이터베이스 기능뿐만 아니라 객체 간의 관계 관리, 상태 추적, 변경 감지, iCould 연동, Undo/Redo, Lazy Loading 등 다양한 기능을 제공합니다.

객체 그래프란?

객체 그래프란 참조를 통해 서로 연결되어 있는 객체들의 구조를 말합니다.
아래 코드 예시를 보면 Person과 Dog는 서로 참조를 가지고 있고, 이를 도식화하면 그래프 형태로 나타낼 수 있습니다.
CoreData는 이 객체들 사이의 관계를 정의하고, 이를 저장소에 관계형 데이터처럼 변환하여 저장합니다.


  
class Person {
var name: String
var dog: Dog?
}
class Dog {
var name: String
weak var owner: Person?
}

CoreData의 저장 구조

CoreData의 저장 구조는 아래와 같은 계층 구조를 가집니다.


  
NSManagedObject // DB에 저장될 객체
⬇️
NSManagedObjectContext // 변경 사항을 추적하는 작업 공간
⬇️
NSPersistentStoreCoordinator // 저장소와 Context를 연결
⬇️
저장소 (SQLite, CloudKit, In-Memory 등)

NSManagedObject: CoreData를 통해 자동으로 생성 및 관리되는 객체로, 속성 및 관계를 포함하며 DataBase의 Scheme 역할을 합니다.

NSManagedObjectContext: 트랜잭션 단위의 작업 공간으로, 변경사항을 추적하고 save() 를 통해 저장할 수 있습니다.

NSPersistentStoreCoordinator: 실제 저장소와 Context를 연결하는 역할을 합니다.

NSPersistentContainer는 CoreData Stack을 구성하는데 필요한 객체들을 담는 역할을 합니다. CoreData를 설정할 때 주로 사용됩니다.

NSManagedObject 생성

MyModel.xcdatamodeld 라는 CoreData Model을 만든 다음,

Entites 에 저장하고 싶은 객체를 모델링하면

NSManagedObject가 자동으로 생성되고, 코드에서 참조할 수 있게 됩니다.

멀티스레드 환경에서 CoreData 다루기

CoreData에서 이뤄지는 트랜잭션들은 NSManagedObjectContext를 통해 이뤄지는데, Context는 기본적으로 메인스레드에서 실행됩니다.

따라서 대량의 데이터 처리나 저장 작업을 백그라운드에서 처리하지 않으면 메인스레드가 버벅이게 되어 UX에 영향을 줄 수 있습니다.

NSManagedObjectContextConcurrencyType

이를 위해 CoreData는 Context를 초기화할 때 NSManagedObjectContextConcurrencyType 옵션을 제공합니다.
옵션으로 .mainQueue 또는 .privateQueue 를 사용할 수 있고,
.mainQueue 는 메인 스레드에서 .privateQueue는 백그라운드 스레드에서 실행되므로 UI와 관련된 작업만 mainQueue에서 수행하는게 좋습니다.

또는 newBackgroundContext() 메소드를 통해 내부적으로 .privateQueueConcurrencyType으로 설정된 Context를 생성할 수도 있습니다.


  
let backgroundContext = persistentContainer.newBackgroundContext()

.mainQueueConcurrencyType으로 설정된 viewContext도 생성할 수 있습니다.


  
let viewContext = persistentContainer.viewContext

perform, performAndWait

Context에서의 작업은 perform 또는 performAndWait을 통해 안전하게 실행할 수 있습니다.
perform은 비동기, performAndWait은 동기 방식으로 동작합니다.

큐에 작업이 등록되고 순차적으로 실행되어 데이터 레이스 문제를 방지할 수 있습니다.


  
// 비동기
backgroundContext.perform {
let entity = SomeEntity(context: backgroundContext)
entity.title = "Test"
try? backgroundContext.save()
}
// 동기
backgroundContext.performAndWait {
let entity = SomeEntity(context: backgroundContext)
entity.title = "Test"
try? backgroundContext.save()
}

MergePolicy

멀티스레드 환경에서 서로 다른 NSManagedObjectContext가 동일한 객체를 수정하고 저장하려고 하면 충돌(Conflict)이 발생합니다.


  
func saveAsync() {
let viewContext = container.viewContext // 메인 스레드
let bgContext = container.newBackgroundContext() // 백그라운드 스레드
// 동일한 객체 참조
let object1 = try? viewContext.existingObject(with: id) as? SomeEntity
let object2 = try? bgContext.existingObject(with: id) as? SomeEntity
// 수정
object1.title = "title1"
object2.title = "title2"
try? viewContext.save() // 저장됨
bgContext.perform {
// bgContext의 스냅샷과 db의 객체 상태가 다름을 감지
// NSMergeConflict 발생
// mergePolicy가 .error(기본값)이므로 저장 실패
try? bgContext.save()
}
}

이러한 문제를 해결하기 위한 정책이 MergePolicy입니다.

MergePolicy를 설정하지 않으면 기본값은 .error로 충돌이 발생했을 때 저장에 실패합니다.

MergePolicy 종류는 아래와 같습니다.

.error: 충돌 시 저장 실패
.mergeByPropertyObjectTrump: 현재 Context 값으로 덮어쓰기 (충돌된 속성만)
.mergeByPropertyStoreTrump: DB 값이 우선
.overwrite: 현재 Context 값으로 덮어쓰기 (객체 전부)
.rollback: 현재 Context의 변경사항을 모두 되돌림

저작자표시 (새창열림)

'iOS' 카테고리의 다른 글

번역) SwiftUI 커스텀 뷰 선언하기  (0) 2025.06.06
애플 로그인 서버부터 클라이언트까지(Swift + Nest.js + TypeScript)  (1) 2025.05.22
Alamofire 기능 정리  (0) 2025.05.12
테스트 가능한 오디오 관리 객체 설계하기  (0) 2025.04.17
AVFAudio - AVAudioSession  (1) 2025.03.29
  • CoreData란?
  • 객체 그래프란?
  • CoreData의 저장 구조
  • NSManagedObject 생성
  • 멀티스레드 환경에서 CoreData 다루기
  • NSManagedObjectContextConcurrencyType
  • perform, performAndWait
  • MergePolicy
'iOS' 카테고리의 다른 글
  • 번역) SwiftUI 커스텀 뷰 선언하기
  • 애플 로그인 서버부터 클라이언트까지(Swift + Nest.js + TypeScript)
  • Alamofire 기능 정리
  • 테스트 가능한 오디오 관리 객체 설계하기
Dev.YoungKyu
Dev.YoungKyu
iOS를 공부하고 있습니다

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.