@Binding — 개념, 작동 방식 및 SwiftUI 예제

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

@Binding은 다른 컴포넌트가 소유한 데이터에 대한 참조를 생성하는 SwiftUI의 Property Wrapper입니다. Binding은 값 자체를 저장하지 않으며 $ 프로젝션을 통해 기존 데이터 소스에 대한 액세스만 제공합니다. Apple Developer Documentation (2025)에 따르면, Binding은 데이터를 직접 소유하지 않고 부모 뷰와 자식 뷰 간의 반응형 양방향 통신을 제공합니다. @Binding은 계층 구조에서 가변 상태를 아래로 전달하는 핵심 메커니즘입니다.

핵심 사항

  • @Binding — 부모 뷰 상태에 대한 참조를 생성하는 Property Wrapper
  • 소유권 없음 — Binding은 데이터를 저장하지 않고 데이터 소스에 대한 액세스만 제공
  • $ 프로젝션 — $stateValue가 @State 또는 @StateObject에서 Binding 생성
  • 양방향 바인딩 — 자식 뷰의 변경 사항이 즉시 부모에 반영됨
  • Binding.constant — 피드백 없는 프로토타이핑용 고정 값

SwiftUI에서 @Binding이란?

@Binding은 부모 뷰에 저장된 속성과 자식 컴포넌트 간의 양방향 연결을 생성하는 Property Wrapper입니다. Binding과 @State의 주요 차이점: Binding은 데이터를 소유하지 않습니다. 실제 데이터 소스(@State, @StateObject 또는 부모의 다른 Binding)를 통해서만 값을 읽고 씁니다. Binding이 없으면 자식 뷰는 콜백이나 델리게이트 없이 조상의 상태를 수정할 수 없습니다.

Binding은 두 개의 속성을 가진 구조체로 구현됩니다: wrappedValue(현재 값)와 projectedValue($를 통해 접근 가능한 Binding 자체). 자식 뷰가 Binding을 통해 wrappedValue를 변경하면 SwiftUI가 데이터 소스에 변경 사항을 전달하고 모든 종속 뷰를 다시 그립니다. 이는 현재 업데이트 주기 내에서 동기적으로 발생합니다.

중요한 특징: @Binding은 단일 수준 전달에 국한되지 않습니다. Binding은 여러 계층 수준을 통해 전달될 수 있으며, 각 자식 컴포넌트는 동일한 데이터 소스에 대한 참조를 받습니다. 모든 수준의 변경은 바인딩된 모든 뷰의 단일 업데이트를 트리거합니다.

Binding의 양방향 바인딩 작동 방식

@Binding을 통한 양방향 바인딩 메커니즘은 Property Wrapper 프로젝션을 기반으로 합니다. 부모가 @State var value: T를 선언하면 SwiftUI가 자동으로 Binding<T> 타입의 $value 프로젝션을 생성합니다. $value를 @Binding var value: T가 있는 자식 컴포넌트에 전달하면 두 뷰를 동일한 메모리 셀에 연결합니다. 자식 뷰에서 Binding을 통한 모든 쓰기는 두 컴포넌트의 다시 그리기를 트리거합니다.

swift
struct SliderContainer: View {
    @State private var value: Double = 0.5

    var body: some View {
        VStack {
            Text("Value: \(value)")
            SliderView(value: $value)
        }
    }
}

struct SliderView: View {
    @Binding var value: Double

    var body: some View {
        Slider(value: $value, in: 0...1)
    }
}

예제에서 SliderContainer는 @State value를 소유하고 SliderView는 $value를 통해 Binding을 받습니다. SliderView 내부의 Slider는 이 Binding에 바인딩됩니다. 슬라이더를 드래그하면 Slider가 Binding을 통해 값을 변경하고 SliderContainer의 @State를 자동으로 업데이트하여 두 뷰가 현재 숫자를 표시합니다. 전체 체인이 단일 콜백이나 알림 없이 작동합니다.

@StateObject 또는 @ObservedObject에서 Binding을 생성하려면 동일한 프로젝션을 사용합니다: $object.property는 Binding<PropertyType>을 제공합니다. 이를 통해 전체 객체를 전달하지 않고 ObservableObject의 개별 속성을 자식 뷰에 전달할 수 있습니다. 이 접근 방식은 더 좁은 결합을 제공하고 불필요한 다시 그리기를 방지합니다.

@Binding vs 콜백: 무엇을 선택할까

SwiftUI 이전에는 계층 구조에서 위로 변경 사항을 전달하는 표준 방법이 콜백과 델리게이트였습니다: 부모가 클로저를 전달하고 자식 컴포넌트가 변경 시 이를 호출했습니다. @Binding은 더 적은 코드와 더 선언적인 구문으로 대안을 제공합니다. 완료 클로저를 전달하는 대신 $stateValue를 전달하기만 하면 됩니다.

기준@Binding콜백
코드하나의 어노테이션 + $클로저 + 호출
다중 수준자동클로저 체인
테스트Binding(value:constant)모의 클로저
가독성높음중간
유연성데이터만모든 로직

자식 뷰가 값을 읽고 수정만 하면 되는 경우 @Binding을 사용하세요. 변경 시 부작용(유효성 검사, 로깅, 네트워크 요청)이 필요한 경우 Binding을 콜백과 결합하세요: 데이터에는 Binding을, 이벤트에는 클로저를 전달합니다. 예를 들어 TextField는 Binding에 바인딩되고 onChange는 유효성 검사를 트리거합니다.

프로젝트에서 @Binding 사용 패턴

@Binding은 여러 일반적인 시나리오에서 사용됩니다. 첫 번째 — 커스텀 컨트롤: 스위치, 슬라이더, 컬러 피커 및 기타 인터랙티브 요소가 양방향 동기화를 위해 Binding을 수락합니다. 두 번째 — 모달 창: 시트 표시 플래그가 Binding으로 전달되어 자식 뷰가 presentationMode 또는 직접 설정을 통해 자체적으로 닫힐 수 있습니다.

세 번째 패턴 — 분리된 폼. 폼이 많은 필드로 구성된 경우 각 필드를 별도의 컴포넌트로 추출하여 해당 값에 대한 Binding을 수락할 수 있습니다. 이는 여러 폼 간의 필드 테스트 및 재사용을 간소화합니다. 부모 컴포넌트는 전체 폼 모델의 유일한 소유자로 유지됩니다.

swift
struct FormField: View {
    let title: String
    @Binding var text: String

    var body: some View {
        VStack(alignment: .leading) {
            Text(title).font(.caption)
            TextField("Enter \(title.lowercased())", text: $text)
                .textFieldStyle(.roundedBorder)
        }
    }
}

FormField 컴포넌트는 제목과 문자열에 대한 Binding을 수락합니다. 레이블과 전달된 Binding에 바인딩된 TextField를 표시합니다. 모든 폼은 각 필드에 $property를 전달하여 FormField를 여러 번 사용할 수 있습니다. 이는 마크업 중복을 줄이고 텍스트 필드 스타일링을 중앙 집중화합니다.

커스텀 Binding 만들기

SwiftUI는 Binding(get:set:) 초기화자를 통해 수동으로 Binding을 생성할 수 있습니다. 이는 값을 읽거나 쓸 때 로직을 추가해야 할 때 유용합니다. 예를 들어 저장 전에 숫자의 형식을 지정하는 Binding이나 변경 시마다 값을 원격 서버와 동기화하는 Binding을 만들 수 있습니다.

swift
struct ValidatedField: View {
    @State private var email: String = ""

    var emailBinding: Binding<String> {
        .init(
            get: { email },
            set: { email = $0.lowercased().trimmingCharacters(in: .whitespaces) }
        )
    }

    var body: some View {
        TextField("Email", text: emailBinding)
    }
}

목록에서 커스텀 emailBinding은 변경 시마다 자동으로 텍스트를 소문자로 변환하고 공백을 제거합니다. TextField는 $email에 직접 바인딩하는 대신 이 Binding을 사용합니다. 이 접근 방식은 onChange 핸들러로 코드를 복잡하게 만들지 않고 Binding 내에서 유효성 검사 및 데이터 변환을 중앙 집중화합니다.

@Binding 오류 및 안티패턴

첫 번째이자 가장 흔한 오류는 Binding 대신 값 전달입니다. 자식 컴포넌트가 @Binding var text: String을 선언하고 부모가 text($ 없이)를 전달하면 컴파일러가 오류를 표시합니다: Cannot convert value of type 'String' to expected argument type 'Binding<String>'. 해결책 — 전달 시 항상 $ 접두사를 사용하세요: $text.

두 번째 오류 — 읽기 전용 데이터에 Binding. 자식 뷰가 값을 읽기만 하면 되는 경우 @Binding을 사용하지 마세요 — 부모의 단순한 let 또는 @State로 충분합니다. Binding은 쓰기 가능성을 의미하며 과도한 수정 권한은 디버깅을 복잡하게 하고 최소 권한 원칙을 위반합니다.

세 번째 문제 — 프로덕션에서 Binding.constant. Binding.constant(value)는 피드백 없는 더미 바인딩을 생성하며 변경 사항이 무시됩니다. constant는 프로토타이핑 및 미리보기(Xcode Previews)에만 사용하고 실제 코드에서는 절대 사용하지 마세요. 테스트에는 제어된 동작으로 Binding(get:set:)을 사용하세요.

자주 묻는 질문

@Binding과 @State의 차이점은 무엇인가요?

@State는 데이터를 소유하고 힙에서 저장을 관리합니다. @Binding은 소유권 없이 기존 상태만 참조합니다. @State는 항상 비공개이며 @Binding은 자식 뷰의 입력 매개변수입니다.

@State 없이 Binding을 만들 수 있나요?

네, Binding(get:set:) 초기화자 또는 Binding.constant(value)를 통해 가능합니다. Binding은 @StateObject에서 $object.$property 프로젝션을 통해, 그리고 Publisher에서 Subscribe 내부의 Binding(get:set:)을 통해 얻을 수도 있습니다.

여러 중첩 수준을 통해 Binding을 어떻게 전달하나요?

@Binding은 체인을 통해 전달됩니다: 각 중간 컴포넌트가 @Binding을 선언하고 $를 통해 더 전달합니다. 모든 수준은 루트 뷰의 동일한 데이터 소스를 참조합니다.

Binding.constant가 인터페이스를 업데이트하지 않는 이유는 무엇인가요?

Binding.constant는 뮤트 래퍼를 생성하며 세터가 새 값을 무시합니다. 자식 컴포넌트의 피드백이 필요하지 않은 프로토타이핑 및 SwiftUI Previews 전용입니다.

@Binding을 옵셔널로 만들 수 있나요?

네, Binding<T?>이 지원됩니다. Binding<String?>을 전달하면 자식 뷰가 nil을 설정할 수 있습니다. 이는 옵셔널 폼 필드 또는 재설정 옵션이 있는 상태에 편리합니다.

요약

  • @Binding — 부모 뷰 데이터와의 양방향 바인딩용 Property Wrapper
  • 소유하지 않음 데이터 — 데이터 소스에 대한 액세스만 제공
  • $ 프로젝션이 @State, @StateObject를 자식 뷰에 전달할 Binding으로 변환
  • 커스텀 Binding 추가 로직으로 Binding(get:set:)을 통해 생성
  • Binding.constant — 미리보기 및 프로토타입 전용
  • 다중 수준 전달 — Binding이 모든 중첩 깊이를 통과
  • 콜백의 대안 — 자식 컴포넌트에서 상태를 수정하는 선언적 방법

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

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

프로젝트 논의

더 읽어보기