SwiftUI에서 많이 하는 실수 - @ObservedObject와 @StateObject를 잘못 사용해 ViewModel이 계속 초기화되는 실수
Dev Study/SwiftUI 2025. 12. 5. 11:13반응형
SwiftUI에서 많이 하는 실수 - @ObservedObject와 @StateObject를 잘못 사용해 ViewModel이 계속 초기화되는 실수
ObservableObject를 사용할 때 이 객체의 라이프사이클을 누가 책임지느냐에 따라
@ObservedObject와 @StateObject 선택이 달라져야 합니다.
- @StateObject : 이 View가 생성과 소멸까지 책임지는 소유자
- @ObservedObject: 다른 곳에서 생성·소유한 객체를 그저 관찰만
이 둘을 반대로 사용하면 View가 다시 그려질 때마다 ViewModel이 계속 새로 만들어져,
네트워크 요청이 반복되거나 상태가 초기화되는 문제가 생깁니다.
1. 문제 원인
- “ObservableObject니까 그냥 @ObservedObject”라는 식의 습관적 사용
- 화면 루트/탭 루트 View에서도 @ObservedObject를 사용
- 부모/자식 관계 고려 없이 아무 View에서나 @StateObject 선언
2. 나타나는 증상
- 탭을 바꿨다 돌아오면, 리스트가 매번 새로 로드됨
- 입력하던 폼 값이 화면 전환 후 다시 돌아오면 모두 초기화
- init() 에 print를 넣어보면 생각보다 자주 호출되는 것을 발견
3. 잘못된 코드 예시
final class CardsViewModel: ObservableObject {
@Published var cards: [String] = []
init() {
print("🔥 CardsViewModel init")
// 네트워크/디스크 로딩
}
}
struct CardsView: View {
// ❌ 진입점 View인데 @ObservedObject 사용
@ObservedObject var viewModel = CardsViewModel()
var body: some View {
List(viewModel.cards, id: \.self) { card in
Text(card)
}
}
}
- 탭 전환/화면 재표시 때마다 init()이 여러 번 찍히게 됩니다.
4. 올바른 코드 예시
4-1. 루트 View에서의 사용
struct CardsView: View {
// ✅ 이 View가 라이프사이클 소유 → @StateObject
@StateObject private var viewModel = CardsViewModel()
var body: some View {
List(viewModel.cards, id: \.self) { card in
Text(card)
}
}
}
4-2. 부모에서 생성해 자식으로 넘길 때
struct ParentView: View {
@StateObject private var viewModel = CardsViewModel() // ✅ 소유자
var body: some View {
ChildView(viewModel: viewModel) // ✅ 주입
}
}
struct ChildView: View {
@ObservedObject var viewModel: CardsViewModel // ✅ 관찰만
var body: some View {
List(viewModel.cards, id: \.self) { card in
Text(card)
}
}
}
5. 정리 및 팁
- 원칙: “처음 만들어지는 곳 = @StateObject, 그걸 넘겨받는 곳 = @ObservedObject”
- init에 print를 넣고 언제 호출되는지 확인해보면 구조 설계의 문제가 금방 드러납니다.
init() {
print("init:", Self.self)
}
이 패턴만 잘 지켜도, “왜 ViewModel이 자꾸 초기화되지?” 문제를 대부분 막을 수 있습니다.
반응형
'Dev Study > SwiftUI' 카테고리의 다른 글
| SwiftUI에서 많이 하는 실수 - ForEach에서 id를 잘못 선택해 셀이 깜빡이거나 재배치되는 실수 (0) | 2025.12.05 |
|---|---|
| SwiftUI에서 많이 하는 실수 - View struct 내부에 일반 프로퍼티로 상태를 저장하려는 실수 (0) | 2025.12.05 |
| SwiftUI에서 많이 하는 실수 - View의 body 안에서 무거운 연산을 실행하는 실수 (0) | 2025.12.05 |
| SwiftUI에서 많이 하는 실수 - @EnvironmentObject를 남용하거나 주입을 잊어서 크래시가 나는 실수 (0) | 2025.12.05 |
| SwiftUI에서 많이 하는 실수 - @State와 @Binding을 혼동해서 잘못 사용하는 실수 (0) | 2025.12.05 |
| SwiftUI 전용 개발을 위한 최적의 iOS Deploy Target 가이드(25년 기준) (0) | 2025.11.10 |
| SwiftUI + UIKit 혼합 아키텍처 실전 가이드 (0) | 2025.11.10 |
| foregroundColor vs tint (0) | 2023.10.28 |

