반응형
SwiftUI에서 많이 하는 실수 - View struct 내부에 일반 프로퍼티로 상태를 저장하려는 실수
SwiftUI의 View는 struct(값 타입) 입니다.
그래서 일반 저장 프로퍼티는 렌더링 사이에 쉽게 초기화되며,
“상태 유지” 목적에 사용할 수 없습니다.
상태를 유지하고 싶다면 @State, @StateObject, @ObservedObject 등을 사용해야 합니다.
1. 문제 원인
- UIKit의 UIViewController처럼 “인스턴스 하나가 계속 살아있다”고 착각
- var count = 0와 같은 저장 프로퍼티에 상태를 넣어도 될 거라고 생각
- 값 타입의 재생성/복사 개념을 잘 모름
2. 나타나는 증상
- 버튼을 눌러도 카운터가 1만 늘고, 이후 다시 0으로 돌아간 것처럼 보임
- NavigationStack/TabView 안에서 화면 전환 후 돌아오면 값이 초기화
- init이 자주 호출되며, 내부 값이 매번 새로 설정됨
3. 잘못된 코드 예시
struct CounterView: View {
// ❌ 상태를 일반 저장 프로퍼티로 선언
var count = 0
var body: some View {
VStack {
Text("Count: \(count)")
Button("증가") {
// 컴파일은 되지만, 다음 렌더링 때 count는 다시 0
count += 1
}
}
}
}
이 코드는 버튼을 눌러도 화면상의 숫자가 변하지 않거나,
한 번만 변하고 다시 원래대로 돌아가는 것처럼 보일 수 있습니다.
4. 올바른 코드 예시
struct CounterView: View {
// ✅ View가 소유하는 상태는 @State
@State private var count = 0
var body: some View {
VStack {
Text("Count: \(count)")
Button("증가") {
count += 1 // ✅ 상태 변경 → View 리렌더링
}
}
}
}
또는, ViewModel로 분리하는 경우:
final class CounterViewModel: ObservableObject {
@Published var count: Int = 0
}
struct CounterView2: View {
@StateObject private var viewModel = CounterViewModel()
var body: some View {
VStack {
Text("Count: \(viewModel.count)")
Button("증가") {
viewModel.count += 1
}
}
}
}
5. 정리 및 팁
- “렌더링 사이에 유지되어야 하는 값인가?” → 그렇다면 State 계열을 사용해야 합니다.
- 일반 저장 프로퍼티는
- 상수 레이아웃 값
- Color, Font, spacing, 상수 텍스트 등
- DI로 주입받은 UseCase/Service 같은 상태가 아닌 값에 사용하는 것이 안전합니다.
반응형

