SwiftUI #25: 상태 (@State)
I’m happy to translate the article for you, but I’ll need the full text you’d like translated. Could you please paste the content (or the portion you want translated) here? I’ll keep the source line, formatting, markdown, and any code blocks exactly as they are.
@State
@State은 property‑wrapper 로, SomeType 타입의 값을 State 구조체로 감싸고 해당 값이 변경될 때 시스템에 알림을 보내어 뷰가 자동으로 업데이트되도록 합니다.
참고:
@State로 표시된 프로퍼티는 뷰의 내부 상태를 나타내므로private로 선언해야 하며, 외부에서 수정해서는 안 됩니다.
struct ContentView: View {
@State private var title: String = "Título inicial"
var body: some View {
VStack {
Text(title)
Button {
title = "Otro título"
} label: {
Text("Modificar")
}
}
}
}
위 예시에서 title이 변경되면 @State가 시스템에 변화를 알리고 body의 내용이 다시 렌더링됩니다.
Binding
Binding 은 @State에 저장된 값에 대한 참조입니다.
뷰가 @State에 저장된 값을 내부적으로 수정하려면 변수 이름 앞에 $ 접두사를 붙여 projected value를 통해 State에 대한 참조를 전달합니다.
struct ContentView: View {
@State private var tituloFinal: String = "Título inicial"
@State private var title: String = ""
var body: some View {
VStack {
Text(tituloFinal)
.padding(10)
TextField("Ingrese título", text: $title)
Button {
tituloFinal = title
} label: {
Text("Actualizar título")
}
}
}
}

Binding을 받는 서브뷰
뷰가 외부 @State로 감싼 값을 수정해야 할 때는 property‑wrapper @Binding을 사용해 Binding 타입의 인스턴스 변수를 선언합니다.
struct ContentSubview: View {
var title: String
@Binding var titleInput: String
var body: some View {
VStack {
Text(title)
.padding(10)
TextField("Ingrese título", text: $titleInput)
}
}
}
메인 뷰에서 서브뷰 사용
struct ContentView: View {
@State private var tituloFinal: String = "Título inicial"
@State private var title: String = ""
var body: some View {
VStack {
ContentSubview(title: tituloFinal, titleInput: $title)
Button {
tituloFinal = title
} label: {
Text("Actualizar título")
}
}
}
}
중요:
@Binding속성은 항상@State속성으로부터 값을 받으므로 기본값을 지정할 필요가 없습니다.
State와 Binding을 구조체로
Swift는 언더스코어(_)를 변수명 앞에 붙여 프로퍼티‑래퍼의 기본 구조체에 접근할 수 있게 합니다.
프로퍼티 표
| 프로퍼티 | 설명 |
|---|---|
wrappedValue | @State가 관리하는 값. 변수명(언더스코어 없이)으로 직접 접근합니다. |
projectedValue | State에 대한 참조 역할을 하는 Binding. $를 사용해 접근합니다( _name.projectedValue와 동일). |
struct ContentSubview: View {
var title: String
@Binding var titleInput: String
var body: some View {
VStack {
Text(title)
.padding(10)
TextField("Ingrese título", text: _titleInput.projectedValue)
.textFieldStyle(.roundedBorder)
}
}
}
struct ContentView: View {
@State private var tituloFinal: String = "Título inicial"
@State private var title: String = ""
var body: some View {
VStack {
// Acceso a la estructura subyacente
ContentSubview(
title: _tituloFinal.wrappedValue,
titleInput: _title.projectedValue
)
Button {
_tituloFinal.wrappedValue = _title.wrappedValue
} label: {
Text("Actualizar título")
}
}
}
}
Binding 매뉴얼
보통 Binding은 @State와 함께 사용되지만, init(get:set:) 이니셜라이저를 사용해 두 개의 클로저—값을 가져오는 클로저와 값을 설정하는 클로저—를 전달하여 수동으로 Binding을 만들 수도 있습니다. 이는 예를 들어 Binding을 받는 컴포넌트를 미리보기할 때 유용합니다.
struct ContentSubview: View {
var title: String
@Binding var titleInput: String
var body: some View {
VStack {
Text(title)
.padding(10)
TextField("Ingrese título", text: _titleInput.projectedValue)
.textFieldStyle(.roundedBorder)
}
}
}
수동 Binding 미리보기
#Preview("Manual binding") {
var someTitle = ""
// Binding manual que opera sobre `someTitle`
let titleBinding = Binding(
get: { someTitle },
set: { newValue in
someTitle = newValue
}
)
ContentSubview(title: "Vista previa", titleInput: titleBinding)
}
뷰에서 Binding 사용
struct ContentSubview: View {
let title: String
@Binding var titleInput: String
var body: some View {
VStack {
Text(title)
TextField("Título", text: $titleInput)
}
}
}
Binding을 수동으로 만들기
struct ContentView: View {
@State private var title = ""
var body: some View {
ContentSubview(title: "Título inicial", titleInput: $title)
}
}
#Preview("Manual binding") {
@State var title = ""
ContentSubview(title: "Título inicial", titleInput: $title)
}
참고: 미리 보기(
#Preview)에서는 전체 화면 버튼이 표시되지 않으므로 Enter fullscreen mode와 Exit fullscreen mode 컨트롤이 생략됩니다.
상수 Binding 사용
때때로 Binding에 변경 불가능한 값을 전달하는 것이 편리합니다. 이 경우 정적 메서드 .constant(_:) 를 사용합니다:
#Preview("Binding constante") {
ContentSubview(title: "Título inicial", titleInput: .constant("Algún título"))
}
#Preview에서 State 만들기
iOS 17/macOS 14부터 매크로 @Previewable 을 사용하면 #Preview 블록 안에서 바로 @State 를 선언할 수 있어 테스트용 뷰 작성을 간소화합니다.
#Preview("@Previewable") {
@Previewable @State var title = ""
ContentSubview(title: "Título inicial", titleInput: $title)
}
팁:
@Previewable은 테스트 뷰에서 상태 관리를 단순화합니다. 코드를 편집하는 동안 상태가 실시간으로 업데이트되기 때문입니다.