@State

@State는 SwiftUI에서 뷰의 상태를 관리하기 위한 속성 래퍼이다. @State는 뷰의 상태 변화를 감지하고, 상태가 변경되면 자동으로 뷰를 다시 렌더링하게 한다.
간단한 예제코드로 알아보자.
import SwiftUI
struct StarButtonView: View {
private var isTapped: Bool = false
var body: some View {
Button(action: {
self.isTapped.toggle()
}, label: {
Image(systemName: "star.fill")
.foregroundStyle(isTapped ? .yellow : .gray)
})
}
}
버튼 클릭 시 별 모양 버튼의 색상이 바뀌는 간단한 액션을 가진 버튼이다. 과연 정상적으로 작동 할까?
Nope! isTapped의 값을 변경하는 과정에서 에러가 발생할 것이다.

에러 로그를 직역해보자. "immutable 값에 대해 mutating 멤버를 사용할 수 없다. self(isTapped)가 immutable이기 때문이다."
✅ 구조체 vs 클래스
구조체 : 기본적으로 imutable하며, 내부 값을 변경하려면 mutating 키워드가 필요하다.
클래스 : 기본적으로 mutable하며, 내부 값을 자유롭게 변경할 수 있다.
즉, SwiftUI의 View 프로토콜은 body가 { get }으로만 정의되어 있어 내부 값을 직접 수정할 수 없기 때문에 에러가 발생한다. 따라서 isTapped를 @State로 선언하지 않으면, 구조체인 View의 특성상 값을 변경할 수 없어 에러가 발생한다.

isTapped를 @State로 선언하면 정상적으로 작동한다.
❗️ @State는 항상 private로 선언하고 가장 상위 뷰에서 @State로 관리해야 한다. 만약 상위 뷰의 @State 값을 하위 뷰에서도 접근할 수 있게 하려면 @Binding을 사용한다.
정리
View 프로토콜의 제약
protocol View {
associatedtype Body : View
@ViewBuilder var body: Body { get }
}
View 프로토콜은 단 하나의 필수 프로퍼티인 body만을 요구하며, 이는 get-only로 정의되어 있다. 따라서 읽기만 가능하고 수정은 불가능하다. 이는 SwiftUI의 선언적 UI 패러다임을 따르기 위한 설계이다. SwiftUI는 View의 body 타입을 컴파일 타임에 정적으로 결정하여 성능을 최적화한다. 만약 body가 mutating을 허용한다면, 뷰의 타입이 런타임에 변경될 수 있어 이러한 최적화가 불가능해진다.
구조체의 특성
- View를 구조체로 구현하면 기본적으로 모든 프로퍼티가 immutable하다.
- 값을 변경하려면 명시적으로 mutating 키워드가 필요하다.
- 하지만 View 프로토콜이 get-only로 정의되어 있어 mutating을 사용할 수 없다.
결론
1. View가 구조체이기 때문에 기본적으로 immutable하다.
2. View 프로토콜이 get-only로 제한되어 있어 mutating도 사용할 수 없다.
➡️ 이러한 두 가지 제약으로 인해 @State 같은 특별한 속성 래퍼가 필요하다.
✅ UIKit에서는 @State를 사용해도 에러가 발생하지 않는데요?
➡️ SwiftUI와 UIKit의 구조적 차이 때문이다. UIKit의 View는 클래스로 구현되어 있고, 클래스는 mutable하기 때문에 @State를 사용하지 않아도 된다.
'Swift > SwiftUI' 카테고리의 다른 글
[SwiftUI] @Binding을 알아보자. (2) | 2025.01.03 |
---|---|
[SwiftUI] Stack에 대해 알아보자. (0) | 2024.07.07 |
[SwiftUI] Modifier에 대해 알아보자. (0) | 2024.07.05 |
[SwiftUI] SwiftUI 시작하기. (0) | 2024.07.05 |
@State

@State는 SwiftUI에서 뷰의 상태를 관리하기 위한 속성 래퍼이다. @State는 뷰의 상태 변화를 감지하고, 상태가 변경되면 자동으로 뷰를 다시 렌더링하게 한다.
간단한 예제코드로 알아보자.
import SwiftUI
struct StarButtonView: View {
private var isTapped: Bool = false
var body: some View {
Button(action: {
self.isTapped.toggle()
}, label: {
Image(systemName: "star.fill")
.foregroundStyle(isTapped ? .yellow : .gray)
})
}
}
버튼 클릭 시 별 모양 버튼의 색상이 바뀌는 간단한 액션을 가진 버튼이다. 과연 정상적으로 작동 할까?
Nope! isTapped의 값을 변경하는 과정에서 에러가 발생할 것이다.

에러 로그를 직역해보자. "immutable 값에 대해 mutating 멤버를 사용할 수 없다. self(isTapped)가 immutable이기 때문이다."
✅ 구조체 vs 클래스
구조체 : 기본적으로 imutable하며, 내부 값을 변경하려면 mutating 키워드가 필요하다.
클래스 : 기본적으로 mutable하며, 내부 값을 자유롭게 변경할 수 있다.
즉, SwiftUI의 View 프로토콜은 body가 { get }으로만 정의되어 있어 내부 값을 직접 수정할 수 없기 때문에 에러가 발생한다. 따라서 isTapped를 @State로 선언하지 않으면, 구조체인 View의 특성상 값을 변경할 수 없어 에러가 발생한다.

isTapped를 @State로 선언하면 정상적으로 작동한다.
❗️ @State는 항상 private로 선언하고 가장 상위 뷰에서 @State로 관리해야 한다. 만약 상위 뷰의 @State 값을 하위 뷰에서도 접근할 수 있게 하려면 @Binding을 사용한다.
정리
View 프로토콜의 제약
protocol View {
associatedtype Body : View
@ViewBuilder var body: Body { get }
}
View 프로토콜은 단 하나의 필수 프로퍼티인 body만을 요구하며, 이는 get-only로 정의되어 있다. 따라서 읽기만 가능하고 수정은 불가능하다. 이는 SwiftUI의 선언적 UI 패러다임을 따르기 위한 설계이다. SwiftUI는 View의 body 타입을 컴파일 타임에 정적으로 결정하여 성능을 최적화한다. 만약 body가 mutating을 허용한다면, 뷰의 타입이 런타임에 변경될 수 있어 이러한 최적화가 불가능해진다.
구조체의 특성
- View를 구조체로 구현하면 기본적으로 모든 프로퍼티가 immutable하다.
- 값을 변경하려면 명시적으로 mutating 키워드가 필요하다.
- 하지만 View 프로토콜이 get-only로 정의되어 있어 mutating을 사용할 수 없다.
결론
1. View가 구조체이기 때문에 기본적으로 immutable하다.
2. View 프로토콜이 get-only로 제한되어 있어 mutating도 사용할 수 없다.
➡️ 이러한 두 가지 제약으로 인해 @State 같은 특별한 속성 래퍼가 필요하다.
✅ UIKit에서는 @State를 사용해도 에러가 발생하지 않는데요?
➡️ SwiftUI와 UIKit의 구조적 차이 때문이다. UIKit의 View는 클래스로 구현되어 있고, 클래스는 mutable하기 때문에 @State를 사용하지 않아도 된다.
'Swift > SwiftUI' 카테고리의 다른 글
[SwiftUI] @Binding을 알아보자. (2) | 2025.01.03 |
---|---|
[SwiftUI] Stack에 대해 알아보자. (0) | 2024.07.07 |
[SwiftUI] Modifier에 대해 알아보자. (0) | 2024.07.05 |
[SwiftUI] SwiftUI 시작하기. (0) | 2024.07.05 |