애플은 WWDC 2023에서 새로운 프레임워크인 Observation을 발표했습니다. 이 글에서는 Observation이 무엇인지, 어떻게 사용하는지, 그리고 기존 코드와 비교하여 어떤 장점이 있는지 알아보겠습니다.
Observation이란?
Observation은 애플이 WWDC 2023에서 소개한 새로운 프레임워크로, 데이터가 변화될 때 프레젠테이션을 업데이트할 수 있도록 하는 반응형 앱을 만들 수 있게 해줍니다. 공식 문서에 따르면, Observation 프레임워크는 다음과 같은 기능을 제공합니다:
- 타입을 관찰 가능하도록 표시합니다.
- 관찰 가능한 타입 인스턴스 내에서의 변경 사항을 추적합니다.
- 앱의 사용자 인터페이스와 같이, 다른 곳에서 이러한 변경 사항을 관찰하고 활용할 수 있습니다.
이 기능들은 기존 SwiftUI에서 사용하는 ObservableObject와 매우 유사합니다. 이제 실제 사용법을 살펴보고, 어떻게 다른지 비교해보겠습니다.
Observable 사용해보기
먼저, 간단한 ViewModel을 만들어보겠습니다.
@Observable class User {
var name: String = "Kim"
var age: Int = 26
var followers = 100
var email = "apple@apple.com"
}
struct ContentView: View {
var user = User()
var body: some View {
VStack(alignment: .leading) {
Text("name : \(user.name)")
.font(.title)
Text("age: \(String(user.age))")
Text("email: \(user.email)")
Text("followers: \(user.followers)")
Button(action: {
user.followers += 1
}, label: {
Text("Add Follower")
})
.buttonStyle(.borderedProminent)
}
.padding()
}
}
class User2: ObservableObject {
@Published var name: String = "Kim"
@Published var age: Int = 26
@Published var followers = 100
@Published var email = "apple@apple.com"
}
위의 코드에서 ObservableObject로 구현한 부분은 아래와 같습니다.
이처럼 ObservableObject로 할 수 있던 기능을 @Observable을 통해 좀 더 간결하게 구현할 수 있습니다. 컴파일 타임에 observation 코드가 자동으로 생성되기 때문입니다. 하지만 여기까지 봤을 때는 새로운 Observable 매크로를 사용해야 하는 이유가 명확하지 않을 수 있습니다.
Observable의 장점
뷰 랜더링의 효율성
다음은 Observable 매크로와 ObservableObject를 사용한 예제입니다.
struct ContentView: View {
var user = User()
@StateObject var user2 = User2()
var body: some View {
VStack(alignment: .leading) {
Text("name : \(user.name)")
.font(.title)
.background(.random)
Text("age: \(String(user.age))")
.background(.random)
Text("email: \(user.email)")
.background(.random)
Text("followers")
.background(.random)
Button(action: {
user.followers += 1
}, label: {
Text("Add Follower")
})
.buttonStyle(.borderedProminent)
}
.padding()
VStack(alignment: .leading) {
Text("name : \(user2.name)")
.font(.title)
.background(.random)
Text("age: \(String(user2.age))")
.background(.random)
Text("email: \(user2.email)")
.background(.random)
Text("followers")
.background(.random)
Button(action: {
user2.followers += 1
}, label: {
Text("Add Follower")
})
.buttonStyle(.borderedProminent)
}
.padding()
}
}
위의 예제에서, 각각의 프로퍼티는 백그라운드를 랜덤으로 설정했습니다. 만약 다시 랜더링이 된다면 백그라운드 색상이 바뀔 것입니다. Add Follower
버튼은 followers
값을 +1 하지만 그 값은 UI에 사용되지 않습니다. 여기서 각각의 버튼을 누르면 어떻게 반응할까요?
Observable 매크로로 만든 윗 부분의 버튼을 누르면 배경 색이 바뀌지 않지만, ObservableObject로 만든 아랫 부분의 버튼을 누르면 배경 색이 계속 바뀌는 것을 알 수 있습니다.
이는 Observable 매크로가 변경된 값을 View에서 관찰하지 않기 때문에 뷰가 상태 변경에 대해 알림을 받지 않기 때문입니다. 따라서 Observable을 사용하면 불필요한 뷰의 랜더링을 방지하고 앱의 성능을 향상시킬 수 있습니다.