오늘은 Core Data를 이용해 연락처 데이터를 저장하고 불러오는 과정을 학습했다. 프로젝트에 PokemonContacts라는 Core Data 모델을 추가하고, 이를 활용하여 사용자 데이터를 영구적으로 저장하는 방법을 익혔다. 아래는 내가 오늘 배운 내용을 정리한 것이다.
Core Data는 애플에서 제공하는 데이터 관리 프레임워크로, 앱의 데이터를 영구적으로 저장하고 관리할 수 있다. 일반적인 데이터베이스처럼 사용할 수도 있지만, 데이터의 상태를 추적하거나 관계를 정의하는 데 더 강력한 기능을 제공한다. 쉽게 말하면 앱이 종료되어도 데이터를 유지하도록 도와주는 똑똑한 도구라고 할 수 있다.
Core Data를 사용하려면 먼저 .xcdatamodeld라는 파일을 프로젝트에 추가해야 한다. 이 파일은 데이터베이스의 구조를 정의하는 역할을 한다.
내가 한 작업:
파일 생성: Xcode에서 PokemonContacts라는 이름의 .xcdatamodeld 파일을 만들었다.
엔티티(Entity) 생성: 연락처 정보를 저장할 Contact라는 엔티티를 만들고, 다음 속성을 추가했다:
name (String): 연락처 이름
phoneNumber (String): 전화번호
profileImageURL (String): 프로필 이미지를 Base64로 저장할 문자열
Core Data가 데이터를 관리할 수 있도록 Core Data 스택을 초기화했다. 이 작업은 AppDelegate 파일에서 처리되며, persistentContainer라는 객체를 통해 데이터베이스와 상호작용할 수 있다.
중요한 코드:
lazy var persistentContainer: NSPersistentContainer = {
let container = NSPersistentContainer(name: "PokemonContacts")
container.loadPersistentStores { _, error in
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
}
return container
}()
persistentContainer: Core Data와 연결된 데이터 저장소를 관리하는 객체.
데이터베이스 파일 이름: PokemonContacts와 .xcdatamodeld 파일 이름이 동일해야 한다.
사용자가 입력한 연락처 정보를 저장하는 로직을 구현했다. 데이터를 저장하려면 다음 단계를 따른다:
Contact라는 엔티티의 새로운 객체를 생성.
이름, 전화번호, 프로필 이미지 데이터를 해당 객체에 설정.
컨텍스트(Context)를 통해 데이터를 실제 데이터베이스에 저장.
@objc private func saveContact() {
guard let context = (UIApplication.shared.delegate as? AppDelegate)?.persistentContainer.viewContext else { return }
let contact = Contact(context: context) // 새로운 Contact 객체 생성
contact.name = nameField.text ?? ""
contact.phoneNumber = phoneField.text ?? ""
if let image = imageView.image, let imageData = image.pngData() {
contact.profileImageURL = imageData.base64EncodedString() // 이미지를 Base64로 변환해 저장
} else {
contact.profileImageURL = "" // 기본값
}
// 데이터 저장
do {
try context.save()
navigationController?.popViewController(animated: true) // 메인 화면으로 돌아가기
} catch {
print("Failed to save contact: \(error)")
showAlert(title: "오류", message: "연락처 저장에 실패했습니다.")
}
}
작업하며 느낀 점:
이미지를 Base64 문자열로 변환해 저장하는 방식이 신기했다. Core Data는 직접 이미지를 저장할 수 없기 때문에 이렇게 처리하는 것이다.
데이터를 저장한 뒤 context.save()를 호출해야 변경 사항이 실제 데이터베이스에 반영된다는 점도 중요했다.
저장한 데이터를 불러와 메인 화면에 표시하기 위해 fetchRequest를 사용했다. 이는 Core Data에서 데이터를 검색하는 기본 도구다.
불러오기 코드:
func fetchAllContacts() -> [Contact] {
let fetchRequest: NSFetchRequest<Contact> = Contact.fetchRequest()
fetchRequest.sortDescriptors = [NSSortDescriptor(key: "name", ascending: true)]
do {
return try context.fetch(fetchRequest)
} catch {
print("Failed to fetch contacts: \(error)")
return []
}
}
작업하며 느낀 점:
fetchRequest를 통해 데이터를 조건에 따라 정렬할 수 있어서 유용했다. 여기서는 연락처를 이름 순으로 정렬했다.
에러 발생 시 빈 배열을 반환하여 앱이 크래시되지 않도록 안전하게 처리했다.
불러온 데이터를 테이블 뷰에 표시하기 위해 다음 작업을 수행했다:
데이터를 배열에 저장.
배열의 데이터를 기반으로 테이블 뷰의 셀을 구성.
사용자가 연락처를 추가하면 데이터를 다시 불러와 테이블 뷰를 갱신.
테이블 뷰 데이터 소스 코드:
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return contacts.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ContactCell", for: indexPath) as! ContactTableViewCell
cell.configure(with: contacts[indexPath.row]) // Contact 데이터 전달
return cell
}
Core Data가 이렇게 강력한 도구인지 몰랐다:
SQL이나 직접 파일로 데이터를 관리하는 것보다 훨씬 간단하고 유연한 방식이었다.
특히, 데이터 모델 정의(.xcdatamodeld)부터 데이터 관리 로직까지 모두 iOS 환경에 최적화되어 있었다.
데이터 저장과 불러오기 로직의 중요성:
단순히 데이터를 저장하는 것에서 끝나는 게 아니라, 유효성을 검사하고 정렬하는 과정을 추가하면서 데이터 관리가 얼마나 중요한지 알게 되었다.