SwiftData 알아보기 (1)

doyeonjeong_·2023년 6월 20일

WWDC

목록 보기
3/4
post-thumbnail

Hits

WWDC 영상 바로가기 : Meet SwiftData

안녕하세요 비비입니다!
WWDC23 영상을 탐방하다가 SwiftData에 관심이 생겨 보던 중
보기만하면 기억에 남지 않을 것 같아서 기록을 시작해봅니다.

개인적으로는 JAVA의 SpringBoot 프레임워크가 생각나서
뭔가 CoreData 보다 친숙한 느낌이라 얼른 사용해보고싶네요!

정리한 내용 중 오역이 있다면 언제든지 말씀해주세요 😄


🌲 SwiftData란?

데이터 모델링 및 관리를 위한 프레임워크입니다.
SwiftUI와 마찬가지로 외부 파일 형식이 없는 코드에 전적으로 집중하고,
원활한 API 경험을 위해 새로운 Swift 매크로가 제공하는 표현력에 의존합니다.
또한 SwiftUI와 자연스럽게 통합되며 CloudKit 및 Widgets와 같은 다른 플랫폼 기능과 함께 작동합니다.


🌲 Using the model

@Model 매크로 사용하기

  • Swift 코드에서 모델의 스키마를 정의하는 데 사용됩니다.
  • 클래스를 장식하는걸로 간단하게 스키마를 생성할 수 있습니다.
import SwiftData

@Model
class Trip {
    var name: String
    var destination: String
    var endDate: Date
    var startDate: Date
 
    var bucketList: [BucketListItem]? = []
    var livingAccommodation: LivingAccommodation?
}

*스키마(Schema): Database의 구조와 제약조건에 관해 전반적인 명세를 기술한 것. 즉 어떤 속성(Attribute)들로 이루어진 개체(Entity)들과, 그 개체들끼리의 관계(Relation)에 대한 정의 및 제약조건들을 기술한 것 입니다.

🌿 속성(Attributes)

🌱 Attributes inferred from properties
속성으로 즉시 사용할 수 있도록 값 유형 속성을 조정합니다.

🌱 Support for basic value types
String, Int 및 Float와 같은 기본 값 유형이 포함됩니다.

🌱 Complex value types

  • Struct
  • Enum
  • Codable
  • Collections of value types

컬렉션을 포함하여 구조체, 열거형 및 코딩 가능한 유형과 같은 보다 복잡한 값 유형을 포함할 수 있습니다.
즉, @Model 매크로만으로 속성을 쉽게 정의할 수 있습니다.

🌿 관계(Relationships)

🌱 Relationships are inferred from reference types

  • Other model types
  • Collections of model types

SwiftData 모델은 유형을 관계로 참조합니다.
관계 및 모델 유형 컬렉션을 사용하여 모델 유형 간에 연결할 수 있습니다.

🌿 Additional metadata

🌱 @Model 은 저장된 모든 속성을 수정할 수 있습니다.

🌱 아래의 매크로를 이용해 속성과 관계를 정의합니다.

  • @Attribute
  • @Relationship

🌱 @Transient로 속성을 제외할 수 있습니다.
👉🏻 이건 Model your schema with SwiftData 에서 자세히 봐야겠습니다!

@Model
class Trip {
    @Attribute(.unique) var name: String // Unique 지정
    var destination: String
    var endDate: Date
    var startDate: Date
 
    @Relationship(.cascade) var bucketList: [BucketListItem]? = [] // Trip 객체 삭제시 같이 삭제되도록 설정
    var livingAccommodation: LivingAccommodation?
}

🌲 Working with your data

데이터 바인딩에 사용되는 2가지 주요 개체 ModelContainer 및 ModelContext 를 살펴볼게요!

🌿 Model Container

저장하려는 모델 유형 목록을 지정하기만 하면 모델 컨테이너를 만들 수 있습니다.
컨테이너를 설정하여 모델 컨텍스트로 데이터를 가져오고 저장할 준비를 할 수 있습니다.

🌱 Persistence Backend
모델 유형에 대한 영구 백엔드 제공

🌱 Customized with configurations & Provides schema migration options
configurations 속성으로 URL, CloudKit 및 그룹 컨테이너 식별자, 마이그레이션 옵션 등을 커스터마이징할 수 있습니다.

// Initialize with only a schema
let container = try ModelContainer([Trip.self, LivingAccommodation.self])

// Initialize with configurations
let container = try ModelContainer(
    for: [Trip.self, LivingAccommodation.self],
    configurations: ModelConfiguration(url: URL("path"))
)

🧐 이 부분에서는 Trip과 LivingAccommodation을 동시에 container에 담는 것 같은데
DeepDive하면서 어떻게 정의되는건지 한번 더 살펴봐야겠습니다.

🌱 SwiftUI에서 사용하는 방법

import SwiftUI

@main
struct TripsApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
        .modelContainer(
            for: [Trip.self, LivingAccommodation.self]
        )
    }
}

🌿 Model Context

🌱 Tracking updates
🌱 Fetching model
🌱 Saving changes
🌱 Undoing changes

업데이트 추적, 데이터 가져오기, 변경 사항 저장하기, 변경 사항 실행 쉬소하기 기능의 인터페이스입니다.

import SwiftUI

struct ContextView : View {
    @Environment(\.modelContext) private var context
}
import SwiftData

// 1. 일반적으로 모델 컨테이너를 생성한 후 뷰의 환경에서 modelContext를 가져오는 경우
let context = container.mainContext

// 뷰 계층 구조 외부에서 공유된 기본 액터 바인딩 컨텍스트를 제공하도록 모델 컨테이너에 요청하거나
// 2. 주어진 모델 컨테이너에 대한 새 컨텍스트를 간단히 인스턴스화 하는 경우
let context = ModelContext(container)

컨텍스트가 있으면 데이터를 가져올 준비가 된 것입니다.

🧐 라고 소개는 되어있지만, 정확하게 context가 뭘 의미하는건지는 조금 더 알아봐야겠습니다. 왜냐하면 위에서 modelContainer 가 [Trip.self, LivingAccommodation.self]으로 2개의 model을 동시에 가지고 있는데 context를 활용하여 데이터를 어떻게 가져온다는건지 이 코드만 보고 확신할 수는 없네요..!

🌿 Fetching your data

🌱  새로운 Swift 기본 유형

  • Predicate
  • FetchDescriptor

🌱  SortDescriptor의 개선 사항

🪴 Predicate

let today = Date()
let tripPredicate = #Predicate<Trip> { 
    $0.destination == "New York" && // 목적지 : 뉴욕
    $0.name.contains("birthday") && // 키워드 : 생일
    $0.startDate > today // 오늘 이후, 계획된 여행 탐색
}

메모리의 데이터를 필터링 하여 가져오기 위한 쿼리 조건이라고 해야할까요
CoreData 에서 사용하던 NSPredicate의 iOS 17 버전이라고 할 수 있습니다.

🪴 FetchDescriptor

let descriptor = FetchDescriptor<Trip>(predicate: tripPredicate)

let trips = try context.fetch(descriptor)

FetchDescriptor는 SwiftData 쿼리를 맞춤화하는 방법을 제공합니다.
위와같이 필터 조건을 지정한 후 FetchDescriptor를 통해 가져올 수 있습니다.

🪴 SortDescriptor

🌱 Updated to support all Comparable types Swift native keypaths
기본 Swift 유형 및 키 경로를 지원하기 위해 모든 비교 유형을 지원하도록 업데이트 되었습니다.

let descriptor = FetchDescriptor<Trip>(
    sortBy: SortDescriptor(\Trip.name),
    predicate: tripPredicate
)

let trips = try context.fetch(descriptor)

SortDescriptor를 사용하여 가져온 여행을 구성할 순서를 지정할 수 있습니다.

🌿 More FetchDescriptor options

Predicate 및 SortDescriptor 외에도 prefetch할 관련 개체를 지정하고
결과 수를 제한하고 결과에서 저장되지 않은 변경 사항을 제외하는 등의 작업을 수행할 수 있습니다.

🌱 Relationships to prefetch
🌱 Result limits
🌱 Exclude unsaved changes

🌿 Modifying your data

ModelContext를 사용하여 이러한 작업을 구동함으로써 데이터를 쉽게 생성, 삭제 및 변경할 수 있습니다.

🌱 Basic operations (CRUD)

  • Inserting
  • Deleting
  • Saving
  • Changing
var myTrip = Trip(name: "Birthday Trip", destination: "New York")

// Insert a new trip
context.insert(myTrip)

// Delete an existing trip
context.delete(myTrip)

// Manually save changes to the context
try context.save()

@Model 매크로는 ModelContext가 변경 사항을 자동으로 추적하고 다음 저장 작업에 포함하도록 돕는다고 합니다.


🌲 Using SwiftData with SwiftUI

  • SwiftUI와의 원활한 통합
  • 쉬운 구성
  • 자동으로 데이터 Fetching

🌿 View Modifiers

데이터 저장소를 구성하고, 옵션을 변경하고, 실행 취소를 활성화하고, 자동 저장을 전환할 수 있습니다.

🌱 Leverage scene and view modifiers (뭐라고 해석하면 좋을지 혹시 아시는 분 계실까요 ?)
🌱 .modelContainer를 사용하여 데이터 저장소 구성
🌱 SwiftUI environment로 등록하여 사용하기

설정한 후 데이터 사용을 시작하는 가장 쉬운 방법은 새로운 @Query 속성 래퍼입니다.
한 줄의 코드로 데이터베이스에 저장된 모든 항목을 쉽게 로드하고 필터링할 수 있습니다.

import SwiftUI

struct ContentView: View  {
    @Query(sort: \.startDate, order: .reverse) var trips: [Trip]
    @Environment(\.modelContext) var modelContext
    
    var body: some View {
       NavigationStack() {
          List {
             ForEach(trips) { trip in 
                 // ...
             }
          }
       }
    }
}

🌲 마무리하며…

Meet SwiftData는 소개하는 내용이 많아 구체적인 코드를 살펴보기엔 짧은 감이 있네요 !
다음은 Build an app with SwiftData를 보고 조금 더 DeepDive 해보겠습니다!
부족한 글이지만 읽어주셔서 감사합니다 😊

profile
블로그 이사중 🚚 byukbyak.tistory.com

0개의 댓글