๐ŸŽ Apple/WWDC

[SwiftData] 01. Meet SwiftData (SwiftData ๋งŒ๋‚˜๋ณด๊ธฐ)

JINiOS 2024. 8. 14. 12:57
728x90

 

SwiftData ๋งŒ๋‚˜๋ณด๊ธฐ WWDC ์˜์ƒ ๋ฒˆ์—ญ/์ •๋ฆฌ๋ณธ์ž…๋‹ˆ๋‹ค.

 

 

  •  ๋ชฉ์ฐจ
    • 00:00 Intro
    • 01:07 Using the model macro | Swift์— ์žˆ๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์ง์ ‘ ๋ชจ๋ธ๋งํ•˜๋Š” ์ƒˆ๋กœ์šด @Model ๋งคํฌ๋กœ
    • 03:17 Working with your data | SwiftData๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๊ณ  ์ˆ˜์ •ํ•˜๋Š” ๋ฒ•
    • 07:02 Use SwiftData with SwiftUI | SwiftData์™€ ๋งค๋„๋Ÿฝ๊ฒŒ ์ž‘๋™ํ•˜๋Š” ๋‹ค๋ฅธ ํ”Œ๋žซํผ ํ”„๋ ˆ์ž„์›Œํฌ ์†Œ๊ฐœ
    • 08:10 Wrap-up
  • doc

 

0. Intro

SwiftData๋Š” ๋ฐ์ดํ„ฐ ๋ชจ๋ธ๋ง ๋ฐ ๊ด€๋ฆฌ ํ”„๋ ˆ์ž„์›Œํฌ๋กœ ์ตœ์‹  Swift ์•ฑ์„ ๋” ์—…๊ทธ๋ ˆ์ด๋“œ์‹œ์ผœ ์ค๋‹ˆ๋‹ค.

SwiftUI์™€ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ํ†ตํ•ฉ๋˜๊ธฐ ๋•Œ๋ฌธ์— CloudKit, Widget ๊ฐ™์€ ๊ธฐ๋Šฅ๊ณผ ๊ฐ™์ด ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

1. Using the model macro

@Model

  • Powerful new Swift macro
  • Define your schema with code
  • Add SwiftData funcionality to model types

@Model์€ Swift ์ฝ”๋“œ์—์„œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์Šคํ‚ค๋งˆ ์ •์˜๋ฅผ ๋•๋Š” ์ƒˆ๋กœ์šด Swift ๋งคํฌ๋กœ์ž…๋‹ˆ๋‹ค.

SwiftData ์Šคํ‚ค๋งˆ๋Š” ๋ณดํ†ต์˜ Swift ์ฝ”๋“œ์ด๋ฉฐ, ํ•„์š”ํ•œ ๊ฒฝ์šฐ ์ถ”๊ฐ€ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ํ”„๋กœํผํ‹ฐ์— ์ฃผ์„ํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

Trip ํด๋ž˜์Šค์— @Model ๋งคํฌ๋กœ๋ฅผ ์ถ”๊ฐ€ํ•ด ์Šคํ‚ค๋งˆ๋ฅผ ์ƒ์„ฑํ•ด๋ณผ๊นŒ์š”?

class Trip {
	var name: String
	var destination: String
	var endData: Date
	var startData: Date
	
	var bucketList: [BucketListItem]? = []
	var livingAccommodation: LivingAccommodation?
}
import SwiftData

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

SwiftData์˜ ๋ชจ๋ธ๋“ค์€ ์•ฑ์˜ ์Šคํ‚ค๋งˆ์— ๋Œ€ํ•œ Source of Truth์ด๋ฉฐ, ์œ ์ง€ํ•˜๋Š” ๊ฒฝํ—˜์„ ์ค„ ์ˆ˜ ์žˆ๋Š”๋ฐ์š”. ํด๋ž˜์Šค์˜ ์ €์žฅ ํ”„๋กœํผํ‹ฐ์— ๋ณ€ํ™”๋ฅผ ์ฃผ์–ด ์œ ์ง€๋˜๋Š” ํ”„๋กœํผํ‹ฐ๋กœ ๋ฐ”๊ฟ‰๋‹ˆ๋‹ค.

 

Attributes

  • Attributes inferred from properties
  • Support for basic value types
  • Complex value types
    • Struct, Enum, Codable, Collections of value types

SwiftData๋Š” ์ž์—ฐ์ ์œผ๋กœ ๊ฐ’ ํƒ€์ž… ํ”„๋กœํผํ‹ฐ๊ฐ€ ๋ฐ”๋กœ ์†์„ฑ์œผ๋กœ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ๋ฌธ์ž์—ด, ์ •์ˆ˜ํ˜•, ์‹ค์ˆ˜ํ˜• ๋“ฑ ๊ธฐ๋ณธ ๊ฐ’ ํƒ€์ž…์ด ํฌํ•จ๋ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ, ๊ตฌ์กฐ์ฒด, ์—ด๊ฑฐํ˜•๊ณผ ๊ฐ™์€ ๋” ๋ณต์žกํ•œ ๊ฐ’ ํƒ€์ž…๋„ ํฌํ•จ๋˜๊ณ  ์ปฌ๋ ‰์…˜ ๋“ฑ ๋ณ€ํ™˜ ๊ฐ€๋Šฅํ•œ ํƒ€์ž…๋„ ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.

 

Relationships

  • Relationships are inferred from reference types
    • Other model types
    • Collections of model types

SwiftData๋Š” ์ฐธ์กฐํ˜• ํƒ€์ž…์„ ๊ด€๊ณ„๋กœ ์„ค๊ณ„ํ•ฉ๋‹ˆ๋‹ค.

๋ชจ๋ธ ํƒ€์ž…๊ณผ ๋ชจ๋ธ ํƒ€์ž…์˜ ๊ด€๊ณ„ ๊ทธ๋ฆฌ๊ณ  ์ปฌ๋ ‰์…˜ ์‚ฌ์ด์— ๊ด€๊ณ„๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

Additional metadata

  • @Model์€ ํƒ€์ž…์— ๋Œ€ํ•œ ์ €์žฅ ํ”„๋กœํผํ‹ฐ๋ฅผ ๋ชจ๋‘ ์ˆ˜์ •ํ•ฉ๋‹ˆ๋‹ค.
  • ํ”„๋กœํผํ‹ฐ์— ๋Œ€ํ•œ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•ด ์Šคํ‚ค๋งˆ ๊ตฌ์ถ• ๋ฐฉ์‹์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    • @Attribute์œผ๋กœ๋Š” ์œ ์ผํ•œ ์ œ์•ฝ์กฐ๊ฑด ์ถ”๊ฐ€๊ฐ€ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.
    • @Relationship์œผ๋กœ๋Š” ์ธ๋ฒ„์Šค ๋ฐฉ์‹์„ ์„ ํƒํ•˜๊ณ , ์‚ญ์ œ ์ „ํŒŒ ๊ทœ์น™์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • @Transient๋กœ๋Š” ํŠน์ • ํ”„๋กœํผํ‹ฐ๋ฅผ ํฌํ•จํ•˜์ง€ ๋ง๋ผ๊ณ  SwiftData์— ๋ช…๋ นํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

Trip ์˜ˆ์‹œ์—์„œ, ์ €์žฅ ํ”„๋กœํผํ‹ฐ์— ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ SwiftData์˜ ์Šคํ‚ค๋งˆ ์ƒ์„ฑ์„ ์กฐ์ •ํ•ด๋ณผ๊นŒ์š”?

 

import SwiftData

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

 

import SwiftData

@Model
class Trip {
	@Attribute(.unique) var name: String // @Attribute(.unique)๋กœ ํ”„๋กœํผํ‹ฐ๊ฐ€ ์œ ์ผํ•˜๋„๋ก ์ง€์ •
	var destination: String
	var endData: Date
	var startData: Date
	
	@Relationship(.cascade) var bucketList: [BucketListItem]? = [] // @Relationship๋กœ ๊ด€๊ณ„๋ฅผ ์„ค์ •ํ•˜๊ณ , (.cascade)๋กœ ๊ด€๋ จ๋œ ํ•ญ๋ชฉ์€ ๊ฐ™์ด ์‚ญ์ œ๋˜๋„๋ก ์„ค์ •
	var livingAccommodation: LivingAccommodation?
}

 

SwiftData ๋ชจ๋ธ๋ง์— ๋Œ€ํ•ด ์ข€ ๋” ์•Œ์•„๋ณด๋ ค๋ฉด 'Model your schema with SwiftData' ์„ธ์…˜์„ ํ™•์ธํ•ด ๋ณด์„ธ์š”.

 

2. Working with your data

@Model ํƒ€์ž…์œผ๋กœ ์ž‘์—…ํ•˜๊ณ  ์šด์˜์„ ์œ„ํ•ด ์‚ฌ์šฉํ•ด์•ผํ•˜๋Š” ๋‘ ๊ฐ€์ง€ ์ฃผ์š” ๊ฐ์ฒด ModelContainer, ModelContext๋ฅผ ์•Œ์•„๋ณผ๊นŒ์š”?

 

ModelContainer

  • Persistence backend
  • Customized with configurations
  • Provides schema migration options

ModelContainer๋Š” ๋ชจ๋ธ ํƒ€์ž…์— ์œ ์ง€๋˜๋Š” ๋ฐฑ์—”๋“œ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ์Šคํ‚ค๋งˆ๋ฅผ ์ง€์ •ํ•˜์—ฌ, ๊ธฐ๋ณธ ์„ค์ •์„ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ ๊ตฌ์„ฑํ•˜๊ฑฐ๋‚˜ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ์˜ต์…˜์œผ๋กœ ์ปค์Šคํ…€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

์ €์žฅํ•˜๊ณ ํ”ˆ ๋ชจ๋ธ ํƒ€์ž… ๋ชฉ๋ก์„ ์ง€์ •ํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๋ชจ๋ธ ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ์„ค์ •๋˜๋ฉด ModelContext๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์™€ ์ €์žฅํ•  ์ค€๋น„๊ฐ€ ๋๋‚ฉ๋‹ˆ๋‹ค.

1) ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์ปค์Šคํ…€ํ•˜๊ณ  ์‹ถ์€ ๊ฒฝ์šฐ, configuration์„ ์‚ฌ์šฉํ•ด URL, CloudKit, ๊ทธ๋ฃน ์ปจํ…Œ์ด๋„ˆ ์‹๋ณ„์ž ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ์˜ต์…˜์„ ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

import SwiftData

// ๊ธฐ๋ณธ
let container = try ModelContainer([Trip.self, LigingAccommodation.self]) 

// ์ปค์Šคํ…€
let customContainer = try ModelContainer(for: [Trip.self, LigingAccommodation.self],
																				configurations: ModelConfiguration(url: URL("path"))) 

 

 

2) SwiftUI์—์„œ ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์„ค์ •ํ•ด ๋ทฐ ํ™˜๊ฒฝ์—์„œ ๋ฐ”๋กœ ์ƒ์„ฑํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

import SwiftData
import SwiftUI

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

 

ModelContext

  • Tracking updates
  • Fetching models
  • Saving changes
  • Undoing changes

ModelContext๋Š” ๋ชจ๋ธ์˜ ๋ชจ๋“  ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ๊ด€์ฐฐํ•˜๊ณ  ๋ชจ๋ธ์— ์ ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋งŽ์€ ์ž‘์—…์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ModelContext๋Š” ์—…๋ฐ์ดํŠธ๋ฅผ ์ถ”์ ํ•˜๊ณ  ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋ฉฐ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ์ €์žฅํ•˜๊ฑฐ๋‚˜ ์‹คํ–‰ ์ทจ์†Œ๋ฅผ ํ•˜๋Š” ์ธํ„ฐํŽ˜์ด์Šค์ž…๋‹ˆ๋‹ค.

 

์‚ฌ์šฉ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋ณผ๊นŒ์š” !?

  • SwiftUI ๋ทฐ ์•ˆ์—์„œ ์‚ฌ์šฉํ•˜๊ธฐ
    SwiftUI์—์„œ๋Š” ModelContainer๋ฅผ ์ƒ์„ฑํ•œ ํ›„์— ํ›„์— ๋ทฐ ๊ณ„์ธต์—์„œ ModelContext๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
import SwiftData
import SwiftUI

struct ContextView: View {
	@Environment(\\.modelContext) private var context
}
  • ๋ทฐ๊ฐ€ ์•„๋‹Œ ๊ณณ์—์„œ ์‚ฌ์šฉํ•˜๊ธฐ
    • ๋ฐฉ๋ฒ• 1) ๋ทฐ ๊ณ„์ธต ๊ตฌ์กฐ ๋ฐ–์—์„œ๋Š” ๋ชจ๋ธ ์ปจํ…Œ์ด๋„ˆ์—๊ฒŒ ๊ณตํ†ต์˜ ๋ฉ”์ธ ์•กํ„ฐ ๋ฐ”์šด๋“œ ์ปจํ…์ŠคํŠธ๋ฅผ ๋‹ฌ๋ผ๊ณ  ์š”์ฒญํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    • ๋ฐฉ๋ฒ• 2) ๋˜๋Š”, ์ฃผ์–ด์ง„ ์ปจํ…Œ์ด๋„ˆ์— ๋Œ€ํ•œ ์ƒˆ๋กœ์šด ์ปจํ…์ŠคํŠธ๋ฅผ ์ธ์Šคํ„ด์Šคํ™”ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
import SwiftData

let context = container.mainContext // ๋ฐฉ๋ฒ• 1
let context = ModelContext() // ๋ฐฉ๋ฒ• 2

 

์ปจํ…์ŠคํŠธ๋ฅผ ๊ฐ€์ ธ์™”์œผ๋‹ˆ, ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ค€๋น„๊ฐ€ ์ •๋ง ๋‹ค ๋˜์—ˆ์Šต๋‹ˆ๋‹ค!!

 

Fetching your data

  • New Swift native types
    • Predicate
    • PetchDescriptor
  • Improvements to SortDescriptor

Predicate, FetchDescriptor์™€ ๊ฐ™์€ ์ƒˆ Swift ๋„ค์ดํ‹ฐ๋ธŒ ํƒ€์ž…๊ณผ SortDescriptor์˜ ๊ฐœ์„ ์—์„œ SwiftData์˜ ์žฅ์ ์„ ๋ˆ„๋ฆด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค !

 

Predicate

  • Fully type checked
  • #Predicate construction instead of text parsing
  • Autocompleted keypaths

iOS 17์— ์ƒˆ๋กœ ๋“ฑ์žฅํ•˜๋Š” Predicate๋Š” Swift ๋„ค์ดํ‹ฐ๋ธŒ ํƒ€์ž…๊ณผ ํ•จ๊ป˜ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ฐ•๋ ฅํ•˜๊ฒŒ ํ˜•์‹ํ™”(๋ถ„๋ฅ˜)๋œ ๊ตฌ์กฐ๋ฅผ ์œ„ํ•ด Swift ๋งคํฌ๋กœ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ์™„์ „ํ•œ ํƒ€์ž… ๊ฒ€์‚ฌ๊ฐ€ ์ด๋ฃจ์–ด์ ธ NSPredicate๋ฅผ ๋Œ€์ฒดํ•˜๋ฉฐ, Xcode๋งŒ ์žˆ๋‹ค๋ฉด ์ž๋™์™„์„ฑ ๊ธฐ๋Šฅ์œผ๋กœ ๊ตฌํ˜„ํ•˜๊ธฐ๋„ ์‰ฝ์Šต๋‹ˆ๋‹ค.

์ƒ˜ํ”Œ Trip ์•ฑ์— ๋Œ€ํ•œ ์„œ์ˆ ์ž ๊ตฌ์ถ• ์˜ˆ์‹œ๋ฅผ ์‚ดํŽด๋ด…์‹œ๋‹ค.

let tripPredicate = #Predicate<Trip> { 
	$0.destination == "New York" && // ‘๋‰ด์š•'์ด ๋ชฉ์ ์ง€์ธ ์—ฌํ–‰์„ ์ง€์ •
	$0.name.contains("birthday") && // ์ƒ์ผ๊ณผ ์—ฐ๊ด€๋œ ์—ฌํ–‰๋“ค๋กœ ์ฟผ๋ฆฌ ๋ฒ”์œ„ ์ค„์ด๊ธฐ
	$0.startDate > today // ํ–ฅํ›„ ๊ณ„ํš๋œ ์—ฌํ–‰์—๋งŒ ๊ด€์‹ฌ์ด ์žˆ๋‹ค๊ณ  ์ง€์ •
}

 

๊ฐ€์ ธ์˜ค๊ณ ์ž ํ•˜๋Š” ์—ฌํ–‰์ด ๋ฌด์—‡์ธ์ง€ ๊ฒฐ์ •ํ–ˆ๋‹ค๋ฉด ์ƒˆ๋กœ์šด FetchDescriptor ํƒ€์ž…์„ ์‚ฌ์šฉํ•˜์—ฌ ModelContext์— ํ•ด๋‹น ์—ฌํ–‰์„ ๊ฐ€์ ธ์˜ค๋ผ๊ณ  ๋ช…๋ นํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

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

let trips = try context.fetch(descriptor)

 

SortDescriptor

  • Updated to support all Comparable types
  • Swift native keypaths

SortDescriptor๋Š” FetchDescriptor์™€ ํ•จ๊ป˜ ์ผ๋ถ€ ์—…๋ฐ์ดํŠธ๋˜์–ด, ๋„ค์ดํ‹ฐ๋ธŒ Swift ํƒ€์ž…๊ณผ ํ‚คํŒจ์Šค๋ฅผ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

 

SortDescriptor๋ฅผ ํ™œ์šฉํ•ด ์—ฌํ–‰์˜ ์ˆœ์„œ๋ฅผ ์ง€์ •ํ•˜๋Š” ๋ฐ์— ์‚ฌ์šฉํ•ด๋ณผ๊นŒ์š”?

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

let trips = try context.fetch(descriptor)

 

More FetchDescriptor options

"FetchDescriptor"๋Š” ์—ฌ๋Ÿฌ๋ถ„์˜ SwiftData์˜ ๋งž์ถคํ˜• ์ฟผ๋ฆฌ๋ฅผ ์œ„ํ•ด ๋‹ค์–‘ํ•œ ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

  • Relationships to prefetch
  • Result limits
  • Exclude unsaved changes

Predicate์™€ Sort ์™ธ์—๋„ ๊ด€๋ จ ๊ฐ์ฒด๋ฅผ ์ง€์ •ํ•ด ๋ฏธ๋ฆฌ ๊ฐ€์ ธ์˜ค๊ฑฐ๋‚˜ ์ €์žฅ๋˜์ง€ ์•Š์€ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ์ œ์™ธํ•ด ๊ฒฐ๊ณผ ์นด์šดํŠธ๋ฅผ ์ œํ•œํ•˜๋Š” ๋“ฑ ๋งŽ์€ ๊ฒƒ๋“ค์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

Modifying your data

ModelContext๋ฅผ ์‚ฌ์šฉํ•ด ๋ฐ์ดํ„ฐ ์ƒ์„ฑ, ์‚ญ์ œ, ์ˆ˜์ •์„ ์•„์ฃผ ์‰ฝ๊ฒŒ ๋งŒ๋“ค๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค.

  • Basic operations
    • Inserting
    • Deleting
    • Saving
    • Changing

์•„๋ž˜ ์ฝ”๋“œ์™€ ๊ฐ™์ด Swift ํด๋ž˜์Šค์™€ ๊ฐ™์€ ๋ชจ๋ธ ๊ฐ์ฒด๋ฅผ ๋งŒ๋“  ํ›„ ์ปจํ…์ŠคํŠธ์— ์ถ”๊ฐ€ํ•˜์—ฌ ๋ณ€ํ™” ์ถ”์  ๋ฐ ์œ ์ง€์™€ ๊ฐ™์€ SwiftData ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

var myTrip = Trip(name: "Birthday Trip",  destination: "New York")
// ...

// ์ถ”๊ฐ€ ๋ฐฉ๋ฒ•
context.insert(myTrip)

// ์‚ญ์ œ ๋ฐฉ๋ฒ•
context.delete(myTrip)

// ๋ณ€๊ฒฝ์‚ฌํ•ญ ์ €์žฅ ๋ฐฉ๋ฒ• (ModelContext์— ๊ฐ’์„ ์ €์žฅํ•˜๊ณ  ์ง€์† ์ปจํ…Œ์ด๋„ˆ์— ์ปค๋ฐ‹ํ•˜๋ผ๊ณ  ์š”์ฒญ) 
try context.save()

 

Modifying your data

  • @Model macro modifies setters for change tracking and observation
  • Updates automatically by the ModelContext

๋ชจ๋ธ ๊ฐ์ฒด์— ๋Œ€ํ•œ ํ”„๋กœํผํ‹ฐ ๊ฐ’์„ ๋ฐ”๊พธ๋Š” ๊ฒƒ์€ ํ‰์ƒ์‹œ ํ”„๋กœํผํ‹ฐ setter๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ๋งŒํผ์ด๋‚˜ ์‰ฝ์Šต๋‹ˆ๋‹ค.

@Model ๋งคํฌ๋กœ๋Š” ์ €์žฅ๋œ ํ”„๋กœํผํ‹ฐ๋ฅผ ์ˆ˜์ •ํ•ด ModelContext๊ฐ€ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ์ž๋™ ์ถ”์ ํ•˜๊ณ  ๋‹ค์Œ ์ €์žฅ Operation์— ํฌํ•จ์‹œํ‚ค๋Š” ๊ฒƒ์„ ๋•์Šต๋‹ˆ๋‹ค.

SwiftData ์ปจํ…Œ์ด๋„ˆ์™€ ์ปจํ…์ŠคํŠธ, ์ž‘์—…์— ๋Œ€ํ•ด์„œ๋Š” ‘Dive Deeper into SwiftData’์„ธ์…˜ ํ™•์ธ !

 

3. Use SwiftData with SwiftUI

  • Seamless integration with SwiftUI
  • Easy Configuration
  • Automatically fetch data and update views

SwiftData๋Š” SwiftUI๋ฅผ ๊ณ ๋ คํ•˜์—ฌ ๋งŒ๋“ค์–ด์กŒ๊ธฐ์— ๋‘˜์ด ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ ์•„์ฃผ ์‰ฝ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ SwiftUI๋Š” SwiftData๋ฅผ ์‚ฌ์šฉํ•ด๋ณผ ์ˆ˜ ์žˆ๋Š” ๊ฐ€์žฅ ์‰ฌ์šด ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.

SwiftData ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์ด๋“  ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๊ฑฐ๋‚˜ ๋ทฐ ์—…๋ฐ์ดํŠธ๋ฅผ ํ•˜๋Š” ๊ฒƒ์ด๋“  ๊ด€๋ จ๋œ API๊ฐ€ ๊ตฌ์ถ•๋˜์–ด์žˆ๊ธฐ ๋•Œ๋ฌธ์—, ์ƒˆ SwiftUI scene, view modifiers๋Š” SwiftData ์•ฑ ๊ตฌ์ถ•์„ ์‹œ์ž‘ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ€์žฅ ์‰ฌ์šด ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.

 

View modifiers

  • Leverage scene and view modifiers
  • Configure data store with .modelContainer
  • Propagated throughout SwiftUI environment
  • SwiftUI will propagate your model context in its environment.

SwiftUI๋ฅผ ํ†ตํ•ด ๋ฐ์ดํ„ฐ ์Šคํ† ์–ด ๊ตฌ์„ฑ ์˜ต์…˜ ๋ณ€๊ฒฝ, ์‹คํ–‰ ์ทจ์†Œ ์ž๋™์ €์žฅ ํ† ๊ธ€์ด ๊ฐ€๋Šฅํ•˜๋ฉฐ, SwiftUI๋Š” ํ•ด๋‹น ํ™˜๊ฒฝ์—์„œ ๋ชจ๋ธ ์ปจํ…์ŠคํŠธ๋ฅผ ์ „ํŒŒํ•ฉ๋‹ˆ๋‹ค.

 

SwiftUI ์ฝ”๋“œ๋ฅผ ํ™•์ธํ•ด๋ณผ๊นŒ์š”?

import SwiftData
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
					// ...
				}
			}
		}
	}
}

์ผ๋‹จ ์„ค์ •ํ•˜๊ณ  ๋‚˜๋ฉด ๊ฐ€์žฅ ์‰ฌ์šด ๋ฐ์ดํ„ฐ ์‚ฌ์šฉ ๋ฐฉ์‹์€ ์ƒˆ๋กœ์šด @Query ํ”„๋กœํผํ‹ฐ ๋ž˜ํผ์ž…๋‹ˆ๋‹ค. ๋‹จ ํ•œ ์ค„์˜ ์ฝ”๋“œ๋กœ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ €์žฅ๋œ ๋ฌด์—‡์ด๋“  ์‰ฝ๊ฒŒ ๋กœ๋”ฉํ•˜๊ณ  ํ•„ํ„ฐ๋งํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

Observing changes

  • No need for @Published
  • SwiftUI automatically refreshes

SwiftData๋Š” ๋ชจ๋ธ ํ”„๋กœํผํ‹ฐ์— ๋Œ€ํ•ด ์ƒˆ๋กœ์šด observable ๊ธฐ๋Šฅ์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

SwiftUI๋Š” observed ํ”„๋กœํผํ‹ฐ์˜ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ์ž๋™์œผ๋กœ ์ƒˆ๋กœ๊ณ ์นจํ•ฉ๋‹ˆ๋‹ค.

SwiftUI์™€ SwiftData์˜ ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๋Š” ๋ฒ•์€ 'Build an app with SwiftData' ์„ธ์…˜์„ ํ™•์ธํ•ด ๋ณด์„ธ์š”.

 

4. Wrap-up

  • Define your schema using @Model
  • Configure your ModelContainer
  • Leverage SwiftUI and SwiftData
728x90