| name | swiftui-patterns |
| description | iOS 17+ SwiftUI patterns를 구현할 때 사용합니다: @Observable/@Bindable, MVVM architecture, NavigationStack, lazy loading, UIKit interop, accessibility (VoiceOver), 비동기 작업(.task/.refreshable), 또는 ObservableObject/@StateObject에서 마이그레이션하는 경우. |
SwiftUI Patterns (iOS 17+)
SwiftUI 17+는 @Observable로 ObservableObject 보일러플레이트 코드를 제거하고, @Environment로 environment 주입을 단순화하며, task 기반 async patterns를 도입합니다. 핵심 원칙은 리액티브 라이브러리 대신 Apple의 최신 API를 사용하는 것입니다.
개요
빠른 참조
| 필요 | 사용 (iOS 17+) | 사용 금지 |
|---|
| Observable 모델 | @Observable | ObservableObject |
| Published 속성 | 일반 속성 | @Published |
| 자체 상태 | @State | @StateObject |
| 전달된 모델 (바인딩) | @Bindable | @ObservedObject |
| Environment 주입 | environment(_:) | environmentObject(_:) |
| Environment 접근 | @Environment(Type.self) | @EnvironmentObject |
| 화면 표시 시 비동기 실행 | .task { } | .onAppear { Task {} } |
| 값 변경 | onChange(of:initial:_:) | onChange(of:perform:) |
핵심 워크플로우
- 모델 클래스에는
@Observable을 사용합니다 (@Published 불필요)
- View가 소유하는 모델에는
@State를, 전달되는 모델에는 @Bindable을 사용합니다
- 비동기 작업에는
.task { }를 사용합니다 (사라질 때 자동으로 취소됨)
- 프로그래밍 방식 내비게이션에는
NavigationPath와 함께 NavigationStack을 사용합니다
- 상호작용 요소에
.accessibilityLabel()과 .accessibilityHint()를 적용합니다
참조 로딩 가이드
콘텐츠가 필요할 가능성이 조금이라도 있다면 항상 참조 파일을 로드하세요. pattern을 놓치거나 실수를 하는 것보다 context를 확보하는 것이 더 낫습니다.
흔히 하는 실수
-
전달된 모델에 @Bindable을 과도하게 사용 — 모든 속성마다 @Bindable을 생성하면 불필요하게 View가 다시 로드됩니다. @Bindable은 양방향 바인딩이 필요한 변경 가능한 모델 속성에만 사용하세요. 읽기 전용 계산 속성은 일반 속성을 사용해야 합니다.
-
상태 배치 오류 — 전용 @Observable 모델 대신 View에 모델 상태를 두면 View 로직이 뒤엉키게 됩니다. 항상 모델과 View의 관심사를 분리하세요.
-
NavigationPath 상태 손상 — NavigationPath를 잘못 변경하면 일관되지 않은 상태로 남을 수 있습니다. 경로 손상을 피하려면 적절한 상태 관리와 함께 navigationDestination(for:destination:)을 사용하세요.
-
.task 취소 누락 — .task는 사라질 때 자동으로 취소를 처리하지만, 중첩된 Task는 그렇지 않습니다. 복잡한 async 흐름에서는 zombie task를 피하기 위해 명시적인 취소 추적이 필요합니다.
-
environment invalidation 무시 — 부모에서 environment 값을 변경해도 자식 View가 자동으로 무효화되지는 않습니다. @Environment를 일관되게 사용하고, observation을 기반으로 리렌더링이 언제 발생하는지 이해하세요.
-
UIKit interop 메모리 누수 — delegate cycle이 끊어지지 않으면 UIViewRepresentable과 UIViewControllerRepresentable이 누수될 수 있습니다. weak reference와 명시적인 정리가 필요합니다.