스트리밍은 대부분의 브라우저와
Developer 앱에서 사용할 수 있습니다.
-
SwiftData 만나보기
SwiftData는 Swift를 위해 구축된 강력하고 표현력 있는 지속성 프레임워크입니다. 데이터를 Swift 코드에서 직접 모델링할 수 있는 방법, SwiftData를 사용해 모델과 작업할 수 있는 방법, SwiftUI에 통합할 수 있는 방법을 소개합니다.
챕터
- 0:00 - Intro
- 1:07 - Using the model macro
- 3:17 - Working with your data
- 7:02 - Use SwiftData with SwiftUI
- 8:10 - Wrap-up
리소스
관련 비디오
WWDC23
-
다운로드
♪ ♪
전 벤 트럼블이고 SwiftData를 소개해 드리겠습니다
SwiftData는 데이터 모델링과 관리 프레임워크로 여러분의 최신 Swift 앱을 더 업그레이드시켜 줍니다 SwiftUI처럼 다른 포맷은 제외하고 코드에만 집중하며 Swift의 새 매크로 시스템을 사용해 매끄러운 API를 만들죠
SwiftData는 매끄러운 API 경험을 만들기 위해 Swift 언어 매크로에서 제공하는 표현성에 의존합니다 SwiftUI와도 자연스럽게 통합되어 CloudKit, Widget과 같은 다른 플랫폼 기능과도 작동하죠 이번 세션에서는 Swift에 있는 데이터를 직접 모델링하는 새로운 @Model 매크로와 그 힘에 대해 알아보겠습니다 먼저 SwiftData로 데이터를 가져오고 수정하는 법 그 다음 SwiftData와 매끄럽게 작동하는 다른 플랫폼 프레임워크를 간략하게 소개해 드리죠 먼저 @Model에 대해서 더 알아볼까요? @Model은 Swift 코드에서 데이터베이스 스키마 정의를 돕는 새 Swift 매크로입니다 SwiftData 스키마는 보통의 Swift 코드이지만 필요한 경우 추가 메타데이터를 프로퍼티에 주석화할 수 있죠 이 스키마로 모델 객체에 강력한 기능 추가가 가능합니다 @Model 매크로에서 클래스를 장식해 스키마를 생성하는 것만큼이나 간단한 작업입니다 SwiftData의 모델들은 사용 앱의 스키마에 대한 진실 공급원이며 유지 경험을 이끌어내는데요 이 경험의 일부는 클래스에 저장된 프로퍼티에 변화를 주어 유지되는 프로퍼티로 바꿉니다 모델에 @Model을 추가하면 새로운 가능성의 세계가 열리죠 SwiftData는 자연적으로 값 타입 프로퍼티가 곧바로 속성으로 사용되도록 적응시킵니다 문자열, 정수형, 실수형 등 기본 값 타입이 여기 포함되죠 구조체, 열거형과 같은 더 복잡한 값 타입도 포함되고 컬렉션 등 변환 가능한 타입도 포함됩니다 SwiftData는 참조형 타입을 관계로 설계합니다 모델 타입과 모델 타입의 관계 그리고 컬렉션 사이에 링크를 생성할 수가 있습니다 @Model은 타입에 대한 저장 프로퍼티를 모두 수정하죠 SwiftData가 프로퍼티에 대한 메타데이터를 사용해 스키마 구축 방식에 영향을 줄 수 있습니다 @Attribute으로는 유일한 제약조건 추가가 가능합니다 @Relationship으로는 인버스 선택을 통제하고 삭제 전파 규칙을 지정할 수 있습니다 이렇게 모델 간 링크의 행동을 바꿀 수 있죠 @Transient로는 특정 프로퍼티를 포함하지 말라고 SwiftData에 명령할 수 있습니다 아까 보았던 Trip 앱 예시인데요 저장된 프로퍼티에 메타데이터를 추가함으로써 SwiftData의 스키마 생성을 조정해 볼게요
@Attribute로 이것을 가리켜 유일해야 한다고 지정합니다 @Relationship을 추가해 버킷리스트 관계를 장식하고 이 앱에서 삭제된 모든 관련 버킷리스트 항목을 SwiftData에게 삭제하라고 명령할 수 있죠 SwiftData 모델링에 대해 좀 더 알아보기 위해 'SwiftData로 스키마 모델링하기' 세션을 확인해 보세요 이제 모델 타입으로 작업하는 방식과 운영을 이끌어내기 위해 사용할 두 가지 주요 객체를 소개하죠 바로 ModelContainer와 ModelContext입니다 ModelContainer는 모델 타입에 유지되는 백엔드를 제공합니다 스키마를 지정함으로써 기본 설정을 사용하거나 구성과 마이그레이션 옵션으로 커스텀할 수 있고요 저장하고픈 모델 타입 목록을 지정하기만 하면 모델 컨테이너를 생성할 수 있습니다 컨테이너를 커스텀을 더 하고 싶다면 구성을 사용해 URL CloudKit, 그룹 컨테이너 식별자 마이그레이션 옵션을 바꿀 수 있습니다 컨테이너가 설정되면 ModelContext로 데이터를 가져와 저장할 준비가 끝납니다 아니면 SwiftUI의 뷰, 씬 수식어를 사용함으로써 컨테이너를 설정헤 뷰 환경에 자동으로 구축할 수도 있고요 ModelContext는 모델에 생기는 모든 변화를 관찰하고 모델에서 작동하는 조치 중 많은 것들을 제공합니다 업데이트를 추적하고 데이터를 가져오며 변경 사항을 저장하거나 실행 취소도 하는 인터페이스죠 SwiftUI에서는 모델 컨테이너를 만든 후에 뷰 환경에서 ModelContext를 얻을 수가 있습니다 뷰 계층 구조 밖에서는 모델 컨테이너에게 공통의 메인 액터 바운드 컨텍스트를 달라고 요청하거나 주어진 컨테이너에 대한 새로운 컨텍스트를 인스턴스화할 수도 있죠 컨텍스트를 가지면 데이터를 가져올 준비가 된 거고요 Predicate, FetchDescriptor와 같은 새 Swift 네이티브 타입과 SortDescriptor 개선에서 SwiftData의 혜택을 느껴보세요
iOS 17에 새로 등장하는 Predicate는 Swift 네티이브 타입과 작동하고 강력하게 유형화된 구조를 위해 Swift 매크로를 사용합니다 완전한 타입 검사가 이루어져 NSPredicate를 대체하고요 자동 완성과 같은 Xcode의 지원만 있다면 서술자 구현도 쉽습니다 샘플 Trip 앱에 대한 서술자 구축 예시를 살펴봅시다 우선 '뉴욕'이 목적지인 여행을 모두 지정할 수 있습니다 쿼리 범위를 생일과 연관된 여행들로만 줄일 수도 있고 과거의 모험과 정반대로 향후 계획된 여행에만 관심이 있다고 지정할 수도 있습니다 가져오고자 하는 여행이 무엇인지 결정했다면 새로운 FetchDescriptor 타입을 사용하여 ModelContext에 해당 여행을 가져오라고 명령할 수 있습니다 SortDescriptor는 FetchDescriptor와 함께 일부 업데이트되어 네이티브 Swift 타입과 키패스를 지원합니다 가져온 여행이 구성되었으면 하는 순서를 지정하는 데에 사용할 수도 있고요 이외에도 FetchDescriptor가 쿼리에 맞추는 방식은 많습니다 서술자와 정렬 외에도 관련 객체를 지정해 미리 가져오거나 미저장 변경 사항을 제외해 결과 카운트를 제한하는 등 많은 것들을 할 수 있죠 ModelContext를 사용해 이러한 운영을 이끌어냄으로써 데이터 생성, 삭제, 수정을 아주 쉽게 만들기도 합니다 다른 Swift 클래스와 같은 모델 객체를 만든 후 컨텍스트에 추가하고 변화 추적 및 유지와 같은 SwiftData 기능 사용을 시작할 수 있고요 ModelContext에 삭제 표시만 하면 유지 객체 삭제가 가능하고 아직 저장되지 않은 변경 사항들을 저장하려면 ModelContext에 그것들을 저장하고 지속 컨테이너에 커밋하라고 요청하면 됩니다 모델 객체에 대한 프로퍼티 값을 바꾸는 것은 평상시 프로퍼티 세터를 사용하는 것만큼이나 쉽습니다 @Model 매크로는 저장된 프로퍼티를 수정해 ModelContext가 변경 사항을 자동 추적하고 다음 저장 운영에 포함시키는 것을 돕죠 SwiftData 컨테이너와 컨텍스트 그리고 운영을 이끌어내는 방법은 'SwiftData 심도 있게 살펴보기' 세션에서 확인하실 수 있습니다 SwiftData는 SwiftUI를 고려하여 만들어졌기에 둘이 함께 사용하는 것은 굉장히 쉽습니다 SwiftUI는 SwiftData 사용을 시작할 수 있는 가장 쉬운 방법이죠 SwiftData 컨테이너를 설정하는 것이든 데이터를 가져오거나 뷰 업데이트를 이끌어내는 것이든 우리는 이 프레임워크를 직접 통합하는 AIP를 구축했습니다 새 SwiftUI 씬, 뷰 수정자는 SwiftData 앱 구축을 시작할 수 있는 가장 쉬운 방법입니다 SwiftUI를 통해 데이터 스토어 구성 옵션 변경, 실행 취소 자동저장 토글이 가능합니다 SwiftUI는 모델 컨텍스트를 환경에 전파하고요 일단 설정하고 나면 가장 쉬운 데이터 사용 방식은 새로운 @Query 프로퍼티 래퍼입니다 단 한 줄의 코드만으로 데이터베이스에 저장된 무엇이든 쉽게 로딩하고 필터링할 수 있죠 SwiftData는 모델 프로퍼티에 대해 완전 새로운 식별 가능 기능을 지원합니다 SwiftUI는 식별 프로퍼티의 변경 사항을 자동 새로 고침할 거고요 SwiftUI와 SwiftData는 힘을 합쳐 여러분의 매력적이고 강력한 앱 구축을 도울 겁니다 이 프레임워크들을 함께 사용하는 법은 'SwiftData로 앱 구축하기' 세션을 확인해 보세요
SwiftData는 Swift 기능에 대한 최고 지원이 가능하도록 설계된 강력하고 새로운 데이터 관리 솔루션입니다 여러분의 코드에 맞는 새 매크로 시스템을 사용하죠 @Model 매크로를 사용해 스키마를 설정하고 @ModelContainer로 유지 경험을 구성하세요 지속, 실행 취소, 재실행 iCloud 동기화 위젯 개발 등이 손쉬워질 겁니다 SwiftUI의 매끄러운 통합을 이용해 지금 바로 앱에 SwiftData를 구축해 보세요 여러분이 SwiftData로 만들어 낼 결과물을 기대하겠습니다 시청해 주셔서 감사합니다 ♪ ♪
-
-
1:27 - Adding @Model to Trip
import SwiftData @Model class Trip { var name: String var destination: String var endDate: Date var startDate: Date var bucketList: [BucketListItem]? = [] var livingAccommodation: LivingAccommodation? }
-
2:46 - Providing options for @Attribute and @Relationship
@Model class Trip { @Attribute(.unique) var name: String var destination: String var endDate: Date var startDate: Date @Relationship(.cascade) var bucketList: [BucketListItem]? = [] var livingAccommodation: LivingAccommodation? }
-
3:43 - Initialize a ModelContainer
// 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")) )
-
3:58 - Creating a model container in SwiftUI
import SwiftUI @main struct TripsApp: App { var body: some Scene { WindowGroup { ContentView() } .modelContainer( for: [Trip.self, LivingAccommodation.self] ) } }
-
4:20 - Accessing the environment's ModelContext
import SwiftUI struct ContextView : View { @Environment(\.modelContext) private var context }
-
5:13 - Building a predicate
let today = Date() let tripPredicate = #Predicate<Trip> { $0.destination == "New York" && $0.name.contains("birthday") && $0.startDate > today }
-
5:32 - Fetching with a FetchDescriptor
let descriptor = FetchDescriptor<Trip>(predicate: tripPredicate) let trips = try context.fetch(descriptor)
-
5:46 - Fetching with fetch and sort descriptors
let descriptor = FetchDescriptor<Trip>( sortBy: SortDescriptor(\Trip.name), predicate: tripPredicate ) let trips = try context.fetch(descriptor)
-
6:15 - Working with a ModelContext
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()
-
7:38 - Using @Query in SwiftUI
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 // ... } } } } }
-
-
찾고 계신 콘텐츠가 있나요? 위에 주제를 입력하고 원하는 내용을 바로 검색해 보세요.
쿼리를 제출하는 중에 오류가 발생했습니다. 인터넷 연결을 확인하고 다시 시도해 주세요.