SwiftUI에서 @StateObject와 @ObservedObject는 상태를 관리하고 뷰를 다시 렌더링하기 위해 사용됩니다. 둘은 비슷한 기능을 제공하지만, 용도와 동작 방식에 중요한 차이가 있습니다. 이 차이점을 이해하면 효율적인 상태 관리와 뷰 재렌더링 문제 해결에 큰 도움이 됩니다.
@StateObject와 @ObservedObject의 기본 개념
1. @StateObject: 내부에서 직접 관리하는 객체
@StateObject는 뷰 내부에서 직접 생성하고 관리하는 객체에 사용됩니다. 이 객체는 뷰가 처음 생성될 때 한 번만 초기화되며, 이후 뷰가 다시 렌더링되더라도 동일한 인스턴스가 유지됩니다.
@StateObject 사용 예시
import SwiftUI
class MyViewModel: ObservableObject {
@Published var data: String = "Initial data"
init() {
print("MyViewModel initialized")
}
func fetchData() {
data = "New data fetched"
}
}
struct ContentView: View {
@StateObject var viewModel = MyViewModel()
var body: some View {
VStack {
Text(viewModel.data)
Button("Fetch Data") {
viewModel.fetchData()
}
}
}
}
출력 결과:
MyViewModel initialized
• @StateObject를 사용하면 뷰가 다시 렌더링되더라도 init()이 한 번만 호출됩니다.
• 뷰 내부에서 객체를 처음 생성하고 관리할 때 사용합니다.
2. @ObservedObject: 외부에서 주입받는 객체
@ObservedObject는 외부에서 생성된 객체를 주입받아 관찰하는 데 사용됩니다. 이 객체는 외부에서 생성 및 소유된 인스턴스를 뷰에서 재사용하도록 도와줍니다.
@ObservedObject 사용 예시
import SwiftUI
class MyViewModel: ObservableObject {
@Published var data: String = "Initial data"
init() {
print("MyViewModel initialized")
}
func fetchData() {
data = "New data fetched"
}
}
struct ContentView: View {
@ObservedObject var viewModel: MyViewModel
var body: some View {
VStack {
Text(viewModel.data)
Button("Fetch Data") {
viewModel.fetchData()
}
}
}
}
struct ParentView: View {
@StateObject var viewModel = MyViewModel()
var body: some View {
ContentView(viewModel: viewModel)
}
}
출력 결과:
MyViewModel initialized
• @ObservedObject는 외부에서 생성된 ViewModel을 주입받아 재사용할 때 사용합니다.
• 부모 뷰에서 생성된 ViewModel을 자식 뷰에 전달하여 상태를 공유할 때 적합합니다.
@StateObject vs @ObservedObject 비교
| 특성 | @StateObject | @ObservedObject |
| 객체 소유권 | 현재 뷰가 소유 | 외부에서 주입된 객체를 관찰 |
| 초기화 시점 | 뷰가 처음 생성될 때 한 번만 초기화 | 부모 뷰에서 생성된 인스턴스를 관찰 |
| 뷰 재렌더링 시 인스턴스 유지 | 유지 | 주입된 인스턴스를 유지 |
| 사용 시기 | 뷰 내부에서 ViewModel을 생성하고 관리할 때 | 외부에서 ViewModel을 주입받을 때 |
| 뷰가 다시 렌더링될 때 동작 | 인스턴스 재생성 없음 | 외부에서 주입된 인스턴스를 재사용 |
언제 @StateObject를 사용해야 할까?
• 뷰 내부에서 ViewModel을 직접 생성하고 관리해야 하는 경우.
• 뷰가 다시 렌더링되더라도 동일한 인스턴스를 유지하고 싶을 때.
• init() 메서드가 여러 번 호출되는 것을 방지하려는 경우.
언제 @ObservedObject를 사용해야 할까?
• 외부에서 생성된 ViewModel을 주입받아 재사용할 때.
• 부모 뷰에서 생성된 상태를 자식 뷰에 전달하고, 상태 변경을 관찰하고 싶을 때.
• @StateObject로 관리되지 않는 객체를 다른 뷰에서 관찰만 하고 싶을 때.
실전 예제: @StateObject와 @ObservedObject 혼합 사용
예제 시나리오
• 부모 뷰에서 HomeViewModel을 생성하고, 이를 자식 뷰에 주입합니다.
• 자식 뷰에서는 @ObservedObject로 주입받아 사용하지만, 부모 뷰에서는 @StateObject로 관리합니다.
예제 코드
class HomeViewModel: ObservableObject {
@Published var data: String = "Welcome"
init() {
print("HomeViewModel initialized")
}
func updateData() {
data = "Data updated"
}
}
struct HomeView: View {
@ObservedObject var viewModel: HomeViewModel
var body: some View {
VStack {
Text(viewModel.data)
Button("Update Data") {
viewModel.updateData()
}
}
}
}
struct ContentView: View {
@StateObject var viewModel = HomeViewModel()
var body: some View {
HomeView(viewModel: viewModel)
}
}
출력 결과:
HomeViewModel initialized
• ContentView에서 @StateObject로 HomeViewModel을 관리하고, HomeView에서는 @ObservedObject로 주입받아 사용합니다.
• 이 방식으로 객체의 재사용과 상태 관리를 효율적으로 할 수 있습니다.
정리
SwiftUI에서 @StateObject와 @ObservedObject를 적절하게 사용하면 효율적인 상태 관리와 뷰 재렌더링 문제를 해결할 수 있습니다.
• 뷰 내부에서 직접 관리해야 할 객체는 @StateObject를 사용합니다.
• 외부에서 주입받아 재사용해야 할 객체는 @ObservedObject를 사용합니다.
이 두 속성의 차이점을 이해하고 상황에 맞게 사용하면, SwiftUI 프로젝트에서 더 나은 성능과 코드 품질을 유지할 수 있습니다.
SwiftUI 상태 관리에 대해 더 궁금한 점이 있으신가요? 아래 댓글로 남겨주세요! 😊
#SwiftUI #StateObject #ObservedObject #Swift #iOSDevelopment #iOS튜토리얼 #Swift튜토리얼
'iOS > SwiftUI' 카테고리의 다른 글
| SwiftUI에서의 제스처 우선순위 이해하기: highPriorityGesture와 simultaneousGesture (2) | 2024.10.17 |
|---|---|
| SwiftUI에서 @Environment(.scenePhase) 이해하기 (0) | 2024.09.26 |
| Cancellables in Combine (0) | 2023.10.23 |
| API Calls with Combine (0) | 2023.10.20 |
| TabView and NavigationLink (0) | 2023.10.19 |