본문 바로가기

iOS/SwiftUI

SwiftUI의 @StateObject vs @ObservedObject: 정확한 사용법과 차이점 정리

반응형

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에서 @StateObjectHomeViewModel을 관리하고, HomeView에서는 @ObservedObject로 주입받아 사용합니다.

이 방식으로 객체의 재사용과 상태 관리를 효율적으로 할 수 있습니다.

 

정리

 

SwiftUI에서 @StateObject@ObservedObject를 적절하게 사용하면 효율적인 상태 관리뷰 재렌더링 문제를 해결할 수 있습니다.

뷰 내부에서 직접 관리해야 할 객체는 @StateObject를 사용합니다.

외부에서 주입받아 재사용해야 할 객체는 @ObservedObject를 사용합니다.

 

이 두 속성의 차이점을 이해하고 상황에 맞게 사용하면, SwiftUI 프로젝트에서 더 나은 성능과 코드 품질을 유지할 수 있습니다.

 

SwiftUI 상태 관리에 대해 더 궁금한 점이 있으신가요? 아래 댓글로 남겨주세요! 😊

 

#SwiftUI #StateObject #ObservedObject #Swift #iOSDevelopment #iOS튜토리얼 #Swift튜토리얼

반응형