티스토리 뷰

WWDC23에서 SwiftUI에 Observation 프레임워크가 새로 추가되었습니다. 이번 글에서는 @Observable 매크로 사용법과 추가적인@ObservationTracked, @ObservationIgnored 매크로의 사용법을 알아보겠습니다.

 

 

Discover Observation in SwiftUI - WWDC23 - Videos - Apple Developer

Simplify your SwiftUI data models with Observation. We'll share how the Observable macro can help you simplify models and improve your...

developer.apple.com

 

 

공식문서 훑어보기

https://developer.apple.com/documentation/observation

 

공식문서의 정의를 직역하면 "기본 데이터가 변경될 때 화면을 업데이트하는 응답형 앱을 만듭니다." 입니다. 더 쉽게 풀어쓰면 "데이터 변경시 화면 업데이트"로 이해할 수 있습니다.

 

사실 데이터가 변화함에 따라 View 업데이트를 해주는 건 기존에도 있었습니다. ObservableObject, @Published, @ObservedObject를 사용해 model이 바뀌면 View를 자동으로 변경해주었습니다.

 

간단한 코드를 통해 확인해보겠습니다.

 

import SwiftUI

class ObservationViewModel: ObservableObject {
    @Published var count: Int = 0
    
    func countUp() {
        count += 1
    }
}

struct ObservationView: View {
    
    @ObservedObject var viewModel = ObservationViewModel()
    
    var body: some View {
        Text("\(viewModel.count)")
        
        Button(
            action: { viewModel.countUp() },
            label: { Text("카운트 업") }
        )
        .buttonStyle(.borderedProminent)
    }
}

 

SwiftUI를 사용했으면 많이 봤을 코드입니다. 버튼을 클릭하면 ViewModel에 있는 count가 증가하고, ViewModel을 @ObservedObject로 명시해주었기 때문에 View가 업데이트 됩니다.

 

 

간단한 코드의 경우는 괜찮지만 실제 프로젝트를 진행하다 보면 count 하나가 아니라 ViewModel에 더 많은 프로퍼티가 있을 겁니다.

 

class ObservationViewModel: ObservableObject {
    @Published var count: Int = 0
    @Published var modelList1: [Model] = []
    @Published var modelList2: [Model] = []
    @Published var modalPresented: Bool = false
    @Published var alertPresented: Bool  = false
    // ...
}

 

 

프로퍼티가 증가할 때마다 @Published를 작성하는 건 비효율적이고 귀찮습니다. @Observable를 사용하면 이를 더 쉽게 해결할 수 있습니다.

 

 

@Observable 사용하기

@Observable를 사용하기 위해서는 Observation을 import해줘야 합니다. Observation이 SwiftData내부에 있어 SwiftData를 import해줘도 됩니다. (더 명시적인 걸 위해 import Observation를 추천하고 있습니다)

 

import Observation
// import SwiftData

 

위에서 작성했던 코드를 아래처럼 작성할 수 있습니다.

 

@Observable
class ObservationViewModel {

    var count: Int = 0
    
    func countUp() {
        count += 1
    }
}

struct ObservationView: View {
    
    var viewModel = ObservationViewModel()
    // ...
}

 

 

훨씬 깔끔해지지 않았나요?? @Published와 @ObservedObject 프로퍼티 래퍼가 없으니까 가독성이 더 증가했습니다! 프로퍼티가 늘어나고 반복되는 @Published를 작성할 필요도 없습니다.

 

 

 

@ObservationIgnored

ViewModel에 있는 모든 프로퍼티를 View에서 보여주지 않는 경우가 있습니다. 기존에는 @Published 래퍼를 안 사용하면 됐지만  @Observable 매크로를 사용할 때는 @ObservationIgnored 래퍼를 사용해주면 됩니다.

 

@Observable
class ObservationViewModel {

    @ObservationIgnored var count: Int = 0
    
    func countUp() {
        count += 1
        print(count)
    }
}

 

@ObservationIgnored를 사용해 count를 정의했습니다.

 

버튼 클릭

 

count가 Up 되서 출력되는데 View는 업데이트 되지않는 걸 볼 수 있습니다!

 

 

@ObservationTracked

Observation에 @ObservationIgnored와 더불어 @ObservationTracked 메크로가 있습니다.

 

https://developer.apple.com/documentation/observation/observationtracked()

 

공식문서에 있는데 따로 정의나 사용법은 나와있지가 않습니다. 그래서 일단 써봤습니다.

 

@Observable
class ObservationViewModel {

    @ObservationTracked var count: Int = 0
    
    func countUp() {
        count += 1
    }
}

 

위와 같이 코드를 수정했더니 에러가 발생했습니다.

 

_count를 찾을 수 없다고 하네요. _ 를 보니 프로퍼티 래퍼가 생각났습니다.

 

struct SmallRectangle {
    private var _height = TwelveOrLess()
    private var _width = TwelveOrLess()
    var height: Int {
        get { return _height.wrappedValue }
        set { _height.wrappedValue = newValue }
    }
    var width: Int {
        get { return _width.wrappedValue }
        set { _width.wrappedValue = newValue }
    }
}

 

Swift 공식문서 코드입니다. private 키워드를 사용해 _height와 _width를 외부로부터 숨기고 height, width를 통해서만 접근합니다.

 

매크로를 확대해보면 구현을 확인할 수 있습니다.

 

@ ObservationTracked

역시 접근을 숨겨주도록 구현했네요. View에서는 말 그대로 보여주기만 하고, 프로퍼티를 set하는 로직은 viewModel에서만 함으로 코드를 캡슐화 해주었습니다. @ObservationTracked를 사용해서 다시 코드를 작성했습니다.

 

@Observable
class ObservationViewModel {

    @ObservationTracked var count: Int
    @ObservationIgnored private var _count: Int = 0
    
    func countUp() {
        count += 1
        print(_count)
    }
}

struct ObservationView: View {
    
    var viewModel = ObservationViewModel()
    
    var body: some View {
        Text("\(viewModel.count)")
    //...
    }
}

 

 

private으로 선언해 _count를 숨기고 view에서는 count로만 접근합니다. count를 증가시켜도 set으로 인해 _count가 증가합니다. 

 

print(_count)

 

 

@Observable를 통해 반복되는 코드를 줄일 수 있어 매우 편하네요!

 

 

 

이상 @Observable 끝~~~~~~~~~~~~끝

 

참고

 

 

Observation | Apple Developer Documentation

Make responsive apps that update the presentation when underlying data changes.

developer.apple.com

 

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/05   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
글 보관함