[SwiftUI] Observation 알아보기

2026. 4. 15. 17:33·Apple/SwiftUI
728x90
반응형

Observation이 뭘까?

Observation은 프로퍼티의 변화를 추적하는 Swift의 새로운 기능입니다.

 

보통 데이터 모델 타입을 작성할 때는 여러가지 프로퍼티가 들어갑니다.

class FoodTruckModel {    
    var orders: [Order] = []
    var donuts = Donut.all
}

 

여기에 @Observable을 추가하기만 해도 UI가 데이터 모델의 변화에 대응할 수 있게 됩니다.

@Observable class FoodTruckModel {    
    var orders: [Order] = []
    var donuts = Donut.all
}

 

@Observable은 Swift 컴파일러에게 명령을 내려서 우리가 작성한 코드를 확장형 observable 타입으로 바꿉니다.

Observable 타입으로 SwiftUI 뷰를 작동시킬 수 있는 거죠.

(다른 프로퍼티 래퍼가 없어도 작동합니다)

@Observable class FoodTruckModel {    
  var orders: [Order] = []
  var donuts = Donut.all
}

struct DonutMenu: View {
  let model: FoodTruckModel
    
  var body: some View {
    List {
      Section("Donuts") {
        ForEach(model.donuts) { donut in
          Text(donut.name)
        }
        Button("Add new donut") {
          model.addDonut()
        }
      }
    }
  }
}

도넛을 보여주는 간단한 뷰를 보면서 설명을 해보겠습니다.

 

SwiftUI는 이 모델이 본문 요청을 실행할 때 특정 프로퍼티에 접근한다는 걸 알고 있습니다.

이 코드에서는 도넛 메뉴 뷰 본문을 실행할 때 'Donut'프로퍼티에 접근이 발생한다는 것을 감지합니다.

 

본문이 실행될 때 SwiftUI는 Observable 타입에서 사용된 프로퍼티의 모든 타입을 접근합니다.

그리고 이 추적 정보를 이용해서 특정 인스턴스에서 프로퍼티에 다음 변화가 언제 일어날지를 예측합니다.

 

@Observable class FoodTruckModel {    
  var orders: [Order] = []
  var donuts = Donut.all
  var orderCount: Int { orders.count }
}

struct DonutMenu: View {
  let model: FoodTruckModel
    
  var body: some View {
    List {
      Section("Donuts") {
        ForEach(model.donuts) { donut in
          Text(donut.name)
        }
        Button("Add new donut") {
          model.addDonut()
        }
      }
      Section("Orders") {
        LabeledContent("Count", value: "\(model.orderCount)")
      }
    }
  }
}

 

이렇게 코드에 연산 프로퍼티를 사용해도 마찬가지로 프로퍼티에 변화가 생기면 UI는 업데이트됩니다.

새로 추가된 콘텐츠에서는 모델의 orderCount를 호출해서 orders 프로퍼티에 접근합니다. 

 

즉, orders가 변경되면 orderCount가 orders 프로퍼티에 접근했기 때문에 Text가 업데이트된다는 것입니다.

 

@Observable 매크로를 쓰면 타입이 확장되어서 Observation을 지원할 수 있게 됩니다.

그렇게 되면 이제 SwiftUI는 프로퍼티 접근을 추적할 수 있고 Observation에서 다음 프로퍼티가 언제 변할지 관찰할 수 있습니다. 그런 추적이 가능해지면 프로퍼티에 변화가 생겼을 때 UI는 뷰 본문을 재계산만 하면 됩니다.

(Apple에 따르면 이 부분에서 성능이 엄청나게 향상되었다고 합니다.)

 

SwiftUi property wrappers

SwftUI 작업의 핵심 프로퍼티 래퍼 3가지는 State, Environment, Bindable이 있습니다.

 

모델 안에 뷰 전용 상태를 저장해야 할 때 @State 프로퍼티를 사용합니다. 

코드로도 살펴보겠습니다.

struct DonutListView: View {
    var donutList: DonutList
    @State private var donutToAdd: Donut?

    var body: some View {
        List(donutList.donuts) { DonutView(donut: $0) }
        Button("Add Donut") { donutToAdd = Donut() }
            .sheet(item: $donutToAdd) {
                TextField("Name", text: $donutToAdd.name)
                Button("Save") {
                    donutList.donuts.append(donutToAdd)
                    donutToAdd = nil
                }
                Button("Cancel") { donutToAdd = nil }
            }
    }
}

Observable 모델 객체인 도넛을 시트로 표현한 모습입니다.

 

시트 표현에서 donutToAdd 상태 변수는 편집 필드의 값을 바인딩 하는데 쓰입니다.

 

'donutToAdd' 프로퍼티는 소속된 뷰의 수명 동안만 관리할 수 있습니다.

 

다음은 @Envrionment입니다.

Envrionment는 각 값을 어디서든 접근할 수 있게 합니다. 즉, 여러 곳에서 공유가 가능해지죠.

 

접근을 기반으로 업데이트가 생성되기 때문에 Observable과 잘 어울립니다.

푸드 트럭 메뉴 뷰의 본문을 불러올 때는 Account 객체의 userName 프로퍼티에 접근이 이루어집니다. 

userName이 바뀌면 메뉴 뷰도 업데이트됩니다.

 

다음은 @Bindable입니다.

애플은 @Bindable은 해당 타입으로부터 바인딩이 생성되게 하는 기능만 있기 때문에 굉장히 가볍다고 말합니다.

 

래핑된 Bindable 프로퍼티에서 바인딩을 만드는 건 간단합니다. $ 구문을 사용해서 프로퍼티에 바인딩을 만들기만 하면 됩니다.

지금 DonutView에서 name이 Text로 되어 있는데 실제로 사용하려면 이름을 수정해야 합니다. Text 대신에 TextField를 사용하면 됩니다.

이렇게 하면 이 TextField에서 바인딩이 일어납니다. 그 바인딩을 읽어서 TextField 값을 채우는 거지만 사용자가 값을 변경하면 바인딩에 회신하기도 합니다.

 

Donut에 바인딩을 만드려면 @Bindable 프로퍼티 래퍼를 붙여주면 됩니다.

 

이 모델이 뷰 상태로 있어야 하는가? -> 그렇다면 @State 사용

 

이 모델이 응용 프로그램의 전역 환경의 일부여야 하나? -> 그렇다면 @Environment 사용

 

이 모델에는 바인딩만 필요한가? -> 그렇다면 @Bindable 사용

 


감사합니다.

 

잘못된 내용이 있거나 더 좋은 내용 피드백은 언제나 환영합니다!

궁금하신 부분은 댓글로 질문 부탁드립니다! 

 

728x90
반응형

'Apple > SwiftUI' 카테고리의 다른 글

[SwiftUI] ViewBuilder 알아보기  (1) 2026.03.31
[SwiftUI] NavigationLink & NavigationStack  (0) 2025.10.22
[SwiftUI] 앱에 Face ID 잠금 기능 적용하기  (8) 2025.07.08
[SwiftUI] SwiftUI 상태 동기화 트러블슈팅  (1) 2025.06.25
[SwiftUI] CADisplayLink를 활용한 부드러운 ProgressView 애니메이션 구현 트러블슈팅  (6) 2025.06.06
'Apple/SwiftUI' 카테고리의 다른 글
  • [SwiftUI] ViewBuilder 알아보기
  • [SwiftUI] NavigationLink & NavigationStack
  • [SwiftUI] 앱에 Face ID 잠금 기능 적용하기
  • [SwiftUI] SwiftUI 상태 동기화 트러블슈팅
P_Piano
P_Piano
Apple 생태계 개발자가 되기 위해 학습과 경험을 기록하고 있습니다.
    반응형
    250x250
  • P_Piano
    피피아노의 개발 일지
    P_Piano
  • 전체
    오늘
    어제
    • 분류 전체보기 (231) N
      • Apple (149) N
        • iOS (25)
        • visionOS (5)
        • Swift (78) N
        • UIKit (2)
        • SwiftUI (27)
        • RxSwift (2)
        • Xcode (6)
        • Metal (2)
      • C언어 (5)
      • C++ (8)
      • Dart (1)
      • Python (3)
      • JavaScript (17)
      • Git (1)
      • CS (1)
        • 디자인 패턴 (6)
        • 네트워크 (20)
        • 운영체제 (8)
        • Database (5)
        • 자료구조 (0)
      • IT 지식 (2)
      • IT 뉴스 (4)
      • 경험 (1)
      • 출처 표기 (0)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    프로세스
    swiftUI
    오블완
    SWIFT
    연산자
    스위프트
    Initializers
    클래스
    ios
    visionOS
    네트워크
    프로퍼티 래퍼
    상속
    변수
    Xcode
    코딩테스트
    디자인패턴
    제어문
    UIKit
    wwdc25
    티스토리챌린지
    Vision Pro
    데이터베이스
    Apple
    이니셜라이저
    운영체제
    비동기
    자바스크립트
    함수
    배열
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.1
P_Piano
[SwiftUI] Observation 알아보기
상단으로

티스토리툴바