⭐️CoreData Relationship⭐️
Swift의 CoreData는 관계형 데이터 모델을 구성할 수 있는 기능이 있다.
관계형 데이터 모델에서 엔티티들의 관계를 나타내기 위해 'Relationship'을 사용한다.
Relationshipdms 엔티티 간의 연결을 나타내는 속성으로, 1 : 1 / 1 : N / N : N 관계를 설정할 수 있다.
Xcode의 모델 파일에서 inspector를 보면 Relationship type을 설정할 수 있다. (단일 관계 / 다중 관계)
Xcode14 이전까지는 여러 엔티티들의 Relationship을 도식화 해서 보여주는 기능이 있었는데
무슨 이유인지 갑자기 사라졌다..;;
학습 예시로 사용했던 엔티티의 관계도는 아래와 같다.
각 엔티티의 attribute가 어떤 것들이 있는지, 어떤 엔티티와 관계를 가지고 있는지 한 눈에 보인다.
또한 단방향/양방향도 화살표를 통해 알 수 있다. (위 사진에서 Inverse 옵션)
대체 왜 없앤거야 애플..?
학습을 하면서 느꼈던 점은 그냥 쿼리를 하는 느낌이었다.
데이터테이블을 관리하고 조인을 해서 원하는 데이터를 뽑아내는 그런 느낌.. 사실 근데 이 느낌이 맞다 ㅋㅋ
먼저 여기서 다룰 엔티티는 회사 / 부서 / 직원 총 세 개이다.
회사(BusinessEntity)
회사는 부서와 양방향 관계를 가지고 있고 회사 안에는 여러 부서가 있다.(To Many 타입)
회사는 직원과도 양방향 관계를 가지고 있고, 여러 직원이 있다.(To Many 타입)
-> 회사 안에는 여러 부서가 있고, 여러 직원이 있다. 당연한 말이다.
부서(DepartmentEntity)
부서는 회사와 양방향 관계를 가지고 있고, 다양한 회사에 속할 수 있다.
->즉 개발부서가 있으면 이 회사 저 회사에 파견갈 수 있다는 뜻.(예시를 위한 예시다)
부서는 직원과 양방향 관계를 가지고 있고 여러 직원이 속할 수 있다. (To Many 타입)
직원(EmployeeEntity)
직원은 부서/회사와 양방향 관계를 가지고 있고 한 곳에만 속할 수 있다.(To One 타입)
*여러 부서/ 여러 회사에 발 걸치는 것이 안된다는 의미.
예시 뷰
차례대로 Business Entity, DepartmentEntity, EmployeeEntity를 생성하고 있다.
처음에는 Business name만 나오다가 점차 데이터들이 Department, Employee와 연결되는 것을 볼 수 있다.
여기서는 반대로 Employee Entity를 만들고 새로운 Department Entity를 만들고, 새로운 Business Entity를 만들고 연결하고 있다.
싱글톤 패턴을 활용한 코어데이터 매니저 예시 코드
* 싱글톤: 앱 전체에서 단 하나의 인스턴스만 생성하는 클래스를 구현하는 방법.
해당 인스턴스는 전역적으로 접근 가능하며, 여러 곳에서 공유해서 사용할 수 있다.
다만 전역 상태 관리가 필요하기 때문에 의존성/결합성 문제가 있을 수 있고 라이프 사이클 내내 유지되기 때문에 메모리 누수 가능성도 있다.또한 멀티 스레드 환경에서 경합 문제가 발생할 수도 있다. 장점도 있지만 단점도 명확하기에 적절하게 사용할 필요가 있다 :)
final class CoreDataManager {
//singleton
static let shared = CoreDataManager()
let container: NSPersistentContainer
let context: NSManagedObjectContext
private init() {
container = NSPersistentContainer(name: "CoreDataContainer")
container.loadPersistentStores { description, error in
if let error = error {
print("Error loading Core data: \(error)")
}
}
context = container.viewContext
}
func save() {
do {
try context.save()
print("Saved successfully")
} catch let error {
print("Error saving Core Data: \(error)")
}
}
}
뷰모델 코드 예시
class CoreDataRelationshipViewModel: ObservableObject {
//싱글톤 객체
let manager = CoreDataManager.shared
//엔티티 배열로 관리
@Published var businesses: [BusinessEntity] = []
@Published var departments: [DepartmentEntity] = []
@Published var employees: [EmployeeEntity] = []
//READ fetch
init() {
getBusinesses()
getDepartments()
getEmployees()
}
//엔티티 추가
func addBusiness() {
let newBusiness = BusinessEntity(context: manager.context)
newBusiness.name = "Apple"
//기존 부서를 새로운 회사에 추가하는 경우
//배열 인덱싱으로 직접 추가도 가능하고, .add~ 메서드 활용도 가능.
// add existing departments to the new business
// newBusiness.departments = []
// add existing employees to the new business
// newBusiness.employees = []
// add new business to existing department
// newBusiness.addToDepartments(<#T##value: DepartmentEntity##DepartmentEntity#>)
// add new business to existing employy
// newBusiness.addToEmployees(<#T##value: EmployeeEntity##EmployeeEntity#>)
//저장
save()
}
//READ. fetch 코드
func getBusinesses() {
let request = NSFetchRequest<BusinessEntity>(entityName: "BusinessEntity")
//정렬이 필요한 경우
let sort = NSSortDescriptor(keyPath: \BusinessEntity.name, ascending: true)
request.sortDescriptors = [sort]
//필터링이 필요한 경우
//filter
// NSPredicate 클래스는 데이터 필터링 및 쿼리 수행을 위한 Cocoa 프레임워크의 일부임
//아래 조건식은 name이라는 속성이 "Apple"과 일치한다는 조건
// let filter = NSPredicate(format: "name == %@", "Apple")
// request.predicate = filter
do {
businesses = try manager.context.fetch(request)
} catch let error {
print("Error fetching: \(error.localizedDescription)")
}
}
...
func save() {
businesses.removeAll()
departments.removeAll()
employees.removeAll()
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
self.manager.save()
self.getBusinesses()
self.getDepartments()
self.getEmployees()
}
}
}
아마 실제 비즈니스앱에서 코어데이터를 사용한다면 엔티티, 어트리뷰트도 어마하게 많고 복잡할 것 같다..
엔티티간 relationship을 잘 설정하고 관리하는 것도 꽤 어려운 작업이 될 것 같다.🤔
'SwiftUI > SwiftUI(Intermediate)' 카테고리의 다른 글
5. AVAudioPlayer 사운드 재생/ 열거형 (원시값,연관값) (0) | 2023.05.23 |
---|---|
4. typealias 타입앨리어스 (0) | 2023.05.22 |
2. CoreData 코어데이터 기본 CRUD (0) | 2023.05.21 |
1. sorted / filter / map / compactMap (0) | 2023.05.21 |
0. Identifiable / Hashable (0) | 2023.05.20 |