@State — SwiftUI에서의 목적과 사용법

저자: IT Sectr 게시일: 2026-06-19 읽는 시간: 7 분

@State는 단일 뷰 내에서 로컬 상태를 관리하기 위한 SwiftUI의 Property Wrapper입니다. @State 프로퍼티가 변경될 때마다 SwiftUI가 자동으로 뷰를 다시 그려 수동 업데이트 호출 없이 인터페이스를 반응형으로 만듭니다. Apple Developer Documentation (2025)에 따르면, @State는 단일 뷰에 속하는 간단한 타입과 구조체에 권장됩니다. @State는 SwiftUI 인터페이스에 상호작용을 추가하는 가장 간단한 방법입니다.

핵심 포인트

  • @State — 단일 뷰에 속하는 로컬 상태용 Property Wrapper
  • 자동 업데이트 — @State 프로퍼티 변경 시 SwiftUI가 body 재호출
  • 간단한 타입 — @State는 String, Int, Bool, enum, struct에서 작동
  • 자식 뷰에 전달하지 않음 — 자식 컴포넌트의 변경에는 @Binding 사용
  • private — @State 프로퍼티는 항상 private 수식어로 선언

SwiftUI에서 @State란?

@State는 SwiftUI에 내장된 Property Wrapper로, 뷰가 자신의 상태를 저장하고 추적할 수 있게 합니다. @State 값이 변경되면 SwiftUI가 body 프로퍼티를 다시 호출하여 뷰를 자동으로 다시 그립니다. 이것이 SwiftUI에서 반응형 프로그래밍의 기초입니다: 개발자가 상태를 선언하면 프레임워크가 인터페이스 동기화를 처리합니다.

@State는 SwiftUI가 관리하는 힙에 저장 영역을 만듭니다. 이 영역은 영구적입니다 — 매 렌더링 시 발생하는 뷰 구조체의 반복적인 초기화에서도 살아남습니다. SwiftUI는 뷰의 식별자(계층 구조 내 위치에서 생성)를 사용하여 @State 프로퍼티를 특정 뷰에 바인딩합니다. 덕분에 상위 뷰가 업데이트되어도 상태가 재설정되지 않습니다.

중요한 제한 사항: @State는 값 타입(struct, enum, 프리미티브)만을 대상으로 합니다. 참조 타입(클래스)의 경우 @StateObject 또는 @ObservedObject를 사용하세요. @State 프로퍼티에 클래스를 할당하면 SwiftUI는 객체 내부의 변경을 감지할 수 없습니다 — 참조의 완전한 교체만 감지합니다.

@State의 내부 작동 방식

SwiftUI는 내부 Storage 메커니즘을 통해 @State를 구현합니다. 각 @State 프로퍼티는 뷰의 특수 저장 컨테이너에 저장된 전용 메모리 셀을 얻습니다. wrappedValue에 쓰기가 발생하면 SwiftUI는 didSet을 통해 의존성 그래프에 다시 그려야 함을 알립니다.

swift
struct ContentView: View {
    @State private var name: String = "User"
    @State private var isLoggedIn: Bool = false

    var body: some View {
        VStack {
            Text("안녕하세요, \(name)")
            Button(isLoggedIn ? "로그아웃" : "로그인") {
                isLoggedIn.toggle()
            }
        }
    }
}

예제에는 두 개의 @State 프로퍼티가 있습니다: name(String)과 isLoggedIn(Bool). isLoggedIn.toggle()이 호출되면 SwiftUI는 ContentView를 업데이트 필요로 표시하고 다음 렌더링 사이클에서 body를 재호출합니다. 핵심 포인트: @State 프로퍼티는 항상 private 수식어로 선언됩니다 — 이는 상태가 현재 뷰에 독점적으로 속하며 외부에서 직접 변경되어서는 안 된다는 신호입니다.

변경 사항을 관찰하기 위해 SwiftUI는 Combine의 CurrentValueSubject를 사용합니다. 각 @State 프로퍼티는 변경 시마다 시스템에 알리는 숨겨진 퍼블리셔를 생성합니다. 이를 통해 SwiftUI는 최소한의 필요한 뷰 세트만 다시 그리고 전체 계층 구조 업데이트를 피할 수 있습니다.

프로젝트에서 @State 사용 시기

@State는 간단한 로컬 상태에 최적입니다: 검색의 텍스트 필드, 모달 창의 불리언 플래그, 설정 토글, 카운터, 선택된 목록 항목. 값이 하나의 뷰와 그 자식 컴포넌트(@Binding 통해)에서만 사용되는 경우 @State가 올바른 선택입니다. 뷰가 닫혀도 유지되어야 하는 상태(예: 폼 데이터)의 경우, 뷰가 계층 구조에 남아 있는 한 @State도 작동합니다.

  • 텍스트 필드 — TextField에 입력된 텍스트 저장용 @State
  • 불리언 플래그 — 모달 창 및 시트 표시/숨기기용 @State
  • 요소 선택 — 선택된 탭 또는 행 추적용 @State
  • 카운터 — 증가/감소가 있는 숫자 값용 @State
  • 중간 계산 — 뷰 내에서 결과 캐싱용 @State

@State를 전역 애플리케이션 상태, 네트워크 데이터 캐싱, 또는 여러 화면에서 사용되는 객체에 사용하지 마세요. @StateObject와 @EnvironmentObject가 이러한 목적으로 설계되었습니다. 또한 @State는 대량의 데이터 저장에 적합하지 않습니다 — 변경 시마다 전체 뷰가 다시 그려집니다.

@State와 @Binding의 협력

@Binding은 상위 뷰의 @State와 해당 상태를 변경해야 하는 자식 뷰 사이의 다리입니다. 상위가 @State를 선언하고, 자식 컴포넌트는 $ 프로젝션을 통해 Binding을 받습니다. 자식 뷰에서 Binding을 변경하면 상위의 @State가 자동으로 업데이트되고 그 반대도 마찬가지입니다. 이는 피드백 기능이 있는 단방향 데이터 흐름을 보장합니다.

swift
struct ParentView: View {
    @State private var text: String = ""

    var body: some View {
        ChildView(text: $text)
    }
}

struct ChildView: View {
    @Binding var text: String

    var body: some View {
        TextField("Enter text", text: $text)
    }
}

목록에서 ParentView가 @State text를 소유하고, ChildView는 $text를 Binding으로 받습니다. ChildView 내의 TextField는 text: $text를 통해 이 Binding에 바인딩됩니다. 사용자가 TextField에 입력하면 Binding을 통해 ChildView에서 값이 변경되어 ParentView의 @State 업데이트가 발생합니다. 두 뷰 모두 새 값으로 다시 그려집니다.

@State 사용 시 일반적인 실수

가장 흔한 실수는 @State 프로퍼티에 클래스를 할당하는 것입니다. @State var model = MyClass()라고 작성하면 SwiftUI는 클래스 내부의 프로퍼티 변경을 추적할 수 없습니다 — 객체 교체만 감지합니다. 클래스의 경우 항상 @StateObject를 사용하세요. 두 번째 일반적인 문제는 private 수식어 없이 @State를 선언하는 것으로, 상태 캡슐화 원칙을 위반합니다.

$ 없이 @State를 직접 자식 뷰에 전달하는 것도 또 다른 일반적인 실수입니다. TextField(text: $text) 대신 TextField(text: text)를 전달하면 자식 컴포넌트는 Binding이 아닌 단순한 문자열을 받습니다. TextField의 텍스트 변경이 상위의 @State와 동기화되지 않습니다. Binding을 전달하려면 항상 $ 프로젝션을 사용하세요.

세 번째 실수는 관련 데이터에 대한 여러 @State 프로퍼티입니다. 여러 값이 논리적으로 하나의 전체를 형성하는 경우(예: 폼 필드), 하나의 @State를 가진 하나의 구조체로 결합하세요. 이렇게 하면 자식 뷰에 상태를 전달하기 쉬워지고 개별 업데이트 트리거 수가 줄어듭니다.

SwiftUI에서 @State 사용 예제

@State는 대부분의 SwiftUI 프로젝트에서 기본적인 상호작용에 사용됩니다. @State가 텍스트 필드와 로딩 상태를 관리하는 로그인 폼 예제를 살펴보겠습니다. 이 패턴은 모든 애플리케이션에서 나타납니다 — 간단한 메모부터 복잡한 엔터프라이즈 솔루션까지.

swift
struct LoginView: View {
    @State private var email: String = ""
    @State private var password: String = ""
    @State private var isLoading: Bool = false
    @State private var errorMessage: String?

    var body: some View {
        Form {
            TextField("Email", text: $email)
            SecureField("Password", text: $password)
            Button("로그인") {
                login()
            }.disabled(isLoading)
        }
    }

    private func login() {
        isLoading = true
        // 네트워크 요청 수행
    }
}

예제에는 네 개의 @State 프로퍼티가 있습니다: email과 password(폼 필드용), isLoading(로딩 표시용), errorMessage(오류 표시용). 각 프로퍼티는 독립적으로 인터페이스의 일부를 관리합니다. isLoading이 변경되면 버튼이 disabled(isLoading)을 통해 자동으로 비활성화됩니다 — 수동 UI 업데이트 없이.

자주 묻는 질문

왜 @State를 private으로 선언하나요?

@State는 특정 뷰의 로컬 상태를 위해 설계되었습니다. private 수식어는 다른 컴포넌트가 직접 변경하여 캡슐화를 깨뜨리는 것을 방지합니다. 외부 접근에는 $ 프로젝션을 사용하세요.

@State에 배열이나 딕셔너리를 저장할 수 있나요?

네, @State는 배열과 딕셔너리를 지원합니다. 값 타입이기 때문입니다. 그러나 배열의 요소가 변경되면 SwiftUI는 전체 뷰를 다시 그립니다. 큰 목록의 경우 @Published와 함께 @StateObject를 사용하는 것이 더 효율적입니다.

Optional 타입의 @State 프로퍼티에 nil을 할당하면 어떻게 되나요?

@State는 Optional 타입에서 올바르게 작동합니다. nil이 할당되면 SwiftUI가 변경을 감지하고 뷰를 다시 그립니다. 이는 errorMessage: String?와 같은 상태에 편리하며, 여기서 nil은 오류가 없음을 의미합니다.

뷰가 다시 나타날 때 @State는 어떻게 동작하나요?

@State는 뷰가 계층 구조에 남아 있는 한 값을 유지합니다. 뷰가 계층 구조에서 제거되었다가 다시 추가되면 @State는 기본값으로 다시 초기화됩니다. 지속성이 필요한 경우 @AppStorage를 사용하세요.

@State 변경을 애니메이션화할 수 있나요?

네, 변경을 withAnimation으로 감싸세요: withAnimation(.easeInOut) { isExpanded.toggle() }. SwiftUI는 지정된 애니메이션 타입으로 이전 인터페이스 상태와 새 상태 간의 전환을 애니메이션화합니다.

요약

  • @State — 단일 뷰의 로컬 상태용 Property Wrapper, 자동으로 인터페이스 업데이트
  • 작동 간단한 타입: String, Int, Bool, struct 및 enum
  • 비작동 참조 타입(클래스) — @StateObject 사용
  • 항상 private — 상태는 외부에서 직접 변경되지 않아야 함
  • $ 프로젝션 — 자식 뷰에 변경 권한을 전달하는 Binding 생성
  • 여러 @State 하나의 뷰에서 — 독립적인 상태에 대한 일반적인 방식
  • withAnimation — @State 프로퍼티 변경 애니메이션화 가능

턴키 방식의 모바일 애플리케이션을 개발해 드립니다

IT Sectr는 2017년부터 스타트업과 기업을 위한 iOS 및 Android 애플리케이션을 만듭니다. 저희가 상담해 드리고 최적의 솔루션을 제안하겠습니다.

프로젝트 논의

더 읽어보기