ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Meet SwiftData (feat. WWDC 2023)
    SwiftData 2023. 6. 8. 05:06

    안녕하세요. 그린입니다🍏
    이번 포스팅부터 SwiftData 카테고리를 만들어 WWDC 2023에서 소개해주는 SwiftData에 대해 다뤄보려합니다.
    그 첫번째 주자는 Meet SwiftData입니다.
    아마 SwiftData를 딥하게 들어가기전 소개하는 섹션일것 같아요.
     

    SwiftData

    SwiftData는 이번 WWDC 2023에서 소개된 데이터 모델링 및 관리를 위한 프레임워크로 Swift 앱의 향상을 돕습니다.
    SwiftUI와 마찬가지로 외부 파일 형식이 없는 코드에 전적으로 집중하고 Swift의 새로운 매크로 시스템을 사용해 원활한 API를 제공해주죠.
    특히 SwiftUI와 자연스럽게 통합되며 CloudKit 및 Widgets과 같은 다른 플랫폼 기능과도 함께 작동됩니다.
    일전에 코어데이터를 통해 로컬 데이터 같은것을 지속 가능하게 저장하고 사용했다면 이제 새로운 시스템이 나온것이라 볼 수 있죠.
     

    자 그럼 한번 천천히 봐볼까요?

     

    Using the model macro

    @Model 매크로와 Swift 코드에서 직접 데이터를 모델링하는 기능을 봐볼까요?
    @Model은 Swift 코드에서 모델의 스키마를 정의하는데 도움을 주는 Swift 매크로입니다.
    SwiftData 스키마는 일반적인 Swift 코드지만 필요한 경우 추가 메타데이터로 프로퍼티에 기능을 달 수 있죠.

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

    위와 같이 간단히 @Model 매크로를 붙여줌으로 클래스의 저장된 프로퍼티를 변환해 지속 가능한 persisted 프로퍼티로 전환해줍니다.
     
    SwiftData는 기본적으로 프로퍼티로 즉시 사용할 수 있도록 값 유형 프로퍼티를 조정합니다.
    프로퍼티에는 기존과 동일하게 기본적인 자료형이나 컬렉션을 포함해 모든 가능한 유형들을 가질 수 있죠.
     
    SwiftData 모델은 타입을 관계로 참조합니다.
    모델 유형간 링크를 만들 수 있죠.
     
    특히 SwiftData가 프로퍼티의 메타데이터를 사용해 스키마를 구축하는 방식에 영향을 미칠 수 있습니다.
    @Attribute 매크로를 사용해 고유성 제약 조건을 추가할 수 있습니다.
    @Relationship 매크로로 반전 선택을 제어하고 전파 규칙 삭제를 지정할 수 있죠.
    이는 모델간의 링크 동작을 변경해줍니다.
    또한 @Transient 매크로를 통해 SwiftData에 특정 속성을 포함하지 않도록 지시할 수 있습니다.
     

    그럼 위 예시로 한번 메타데이터를 추가해 SwiftData의 스키마 생성을 조정해볼까요?

    import SwiftData
    
    @Model
    class Trip {
      @Attribue(.unique) var name: String
      var destination: String
      var endDate: Date
      var startDate: Date
      
      @Relationship(.cascade) var bucketList: [BucketListItem]? = []
      var livingAccommodation: LivingAccommodation?
    }

    @Attribute 매크로로 해당 값은 고유함을 지정합니다.
    @Relationship 매크로로 버킷리스트아이템과의 관계를 맺고 여행이 삭제될 때 마다 SwiftData에 관련 버킷 리스트 항목을 삭제할 수 있습니다.
     

    좀 더 자세히 보려면 Model your schema with SwiftData 섹션을 봐야 될것 같아요😃

     

    Working with your data

    모델 유형으로 작업하는 방법과 작업을 구동하는데 사용할 주요 개체인 ModelContainer와 ModelContext를 살펴보겠습니다.
     

    Model Container

    모델 컨테이너는 모델 유형에 대한 지속적인 백엔드를 제공합니다.
    스키마를 지정하기만 하면 기본 설정을 사용하거나 구성 및 마이그레이션 옵션으로 사용자 정의를 할 수 있어요.
    즉 저장하려는 모델 유형 목록을 지정하기만 하면 모델 컨테이너를 만들 수 있습니다.
     
    아래와 같이 모델 컨테이너를 추가로 사용자 지정하려는 경우 URL, CloudKit 및 그룹 컨테이너 식별자 그리고 마이그레이션 옵션을 변경할 수 있습니다.

     
    이보다 더 간단하게 SwiftUI에서는 쉽게 컨테이너를 설정하고 뷰의 환경에서 자동으로 설정되도록 할 수 있습니다.

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

     

    그럼 이제 모델 컨테이너를 담아줬으니 사용을 해봐야겠죠?

     

    Model Context

    모델 컨텍스트는 모델에 대한 모든 변경 사항을 관찰하고 이에 대해 작동할 많은 작업을 제공해줍니다.
    업데이트 추적, 데이터 가져오기, 저장 및 삭제 등의 기능을 말이죠.

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

    일반적으로 모델 컨테이너 생성 후 뷰의 environment로 모델 컨텍스트를 가져옵니다.
    물론 뷰 계층 구조 외부에서 컨텍스트를 제공하도록 모델 컨테이너에 요청하거나 주어진 모델 컨테이너에 대해 새 컨텍스트를 인스턴스화 할 수도 있습니다.

     
    이제 데이터를 가져올 준비가 끝났습니다.
    데이터 패치를 위해서 Predicate, FetchDescriptor와 같은 새로운 Swift Native 타입 유형과 SortDescriptor에 대한 개선된 이점을 제공해줍니다.

     

    Predicate & FetchDescriptor

    iOS 17의 새로운 기능인 #predicate 매크로가 있습니다.
    NSPredicate를 대체할 수 있습니다.
    자동 완성과 같은 Xcode 지원으로 구현도 쉽다고 합니다.

    @Query(
      FetchDescriptor(
        predicate: #Predicate { $0.age > 20 }
      )
    ) private var people: [Person]

    이런식으로 쿼리를 조건에 따라 커스텀하게 짜줄 수 있습니다.
     

    SortDescriptor

    FetchDescriptor과 함께 작동하는 SortDescriptor는 기본 Swift 타입 및 키 경로를 지원하기 위해 몇가지 업데이트를 받고 있고 이 구현을 통해 모델을 정렬해줄 수 있습니다.

    @Query(
      FetchDescriptor(
        predicate: #Predicate { $0.age > 20 },
        sortBy: [SortDescriptor(\.age, order: .reverse)]
      )
    ) private var people: [Person]

    요런식으로 말이죠.
     

    그 외에도 prefetch할 개체를 지정하고 결과 수를 제한하고 결과에서 저장되지 않는 변경 사항을 제외하는 등의 작업을 FetchDescriptor 옵션에서 해줄 수 있습니다.

     

    Modifying your data

    SwiftData를 사용하면 모델 컨텍스트를 이용해 데이터를 쉽게 생성, 추가, 삭제 및 변경 해줄 수 있습니다.
    특히 변경은 @Model 매크로로 저장된 프로퍼티를 수정하면 모델 컨텍스트가 변경 사항을 자동으로 추적하고 다음 저장 작업에 포함하도록 알아서 잘 딱 깔끔하고 센스있게 해줍니다!
     

    좀 더 자세한 컨테이너 및 컨텍스트와 작동 방식에 대해서는 Dive Deeper into SwiftData 세션을 봐야할것 같아요🙌

     

    Use SwiftData with SwiftUI

    SwiftData 자체가 이미 SwiftUI를 염두에 두고 구축되었기에 함께 사용하는게 너무나도 쉽습니다🕺🏻
    위에서 계속 봤지만 쉬운 이유중 하나가 @Query 프로퍼티 래퍼가 한몫합니다.
    즉, 컨테이너 설정이 되면 데이터 사용을 위해 간단히 @Query로 구성해줄 수 있습니다.
    한줄의 코드로 DB에 저장된 모든 항목을 쉽게 로드하고 필터링 할 수 있죠!

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

    이제 더이상 관찰하고 업데이트를 위해 @Published가 필요없습니다.
    자동으로 업데이트 해줍니다.

    마무리

    @Model, 컨테이너, 컨텍스트, 쿼리 메모메모!
     

    참고 자료

    https://developer.apple.com/videos/play/wwdc2023/10187/

     

    Meet SwiftData - WWDC23 - Videos - Apple Developer

    SwiftData is a powerful and expressive persistence framework built for Swift. We'll show you how you can model your data directly from...

    developer.apple.com

    'SwiftData' 카테고리의 다른 글

    Model your schema with SwiftData (feat. WWDC 2023)  (11) 2023.06.13
    Build an app with SwiftData (feat. WWDC 2023)  (12) 2023.06.13
Designed by Tistory.