Notice
Recent Posts
Recent Comments
Link
«   2025/07   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
Archives
Today
Total
관리 메뉴

Jupyo's Daily Story

@ViewBuilder 본문

SwiftUI

@ViewBuilder

JangJupyo 2025. 6. 4. 10:27
728x90
반응형

@ViewBuilder는 SwiftUI에서 여러 개의 View들을 마치 하나의 View처럼 조합하여 반환할 수 있도록 도와주는 강력한 결과 빌딩(result building) 속성입니다. 특히 클로저 내부에서 여러 개의 View를 선언했을 때, SwiftUI가 이를 자동으로 묶어 하나의 View 계층 구조로 만들어주는 역할을 합니다.

 

@ViewBuilder가 필요한가?

SwiftUI에서는 View는 some View 타입을 반환하는 경우가 많습니다. 이는 Swift의 Opaque Type이라는 개념을 활용하여, 실제 View의 구체적인 타입을 숨기고 프로토콜만으로 인터페이스를 정의하는 방식입니다.

 

문제는 클로저 내에서 여러 개의 View를 나열할 경우입니다. 예를 들어:

var body: some View {
    Text("Hello")
    Image(systemName: "star")
}

 

위 코드는 에러를 발생시킵니다. 왜냐하면 클로저의 마지막 표현식이 여러 개이므로, 어떤 것을 some View 로 반환해야 할지 Swift 컴파일러가 알 수 없기 때문입니다.

 

이때 @ViewBuilder가 등장합니다. @ViewBuilder는 여러 개의 View를 자동으로 묶어 하나의 TupleView_ConditionalContent(if 문 등) 또는 _ForEachView(ForEach 문 등) 와 같은 내부적인 View 타입으로 변환해줍니다. 개발자는 이 복잡한 내부 타입에 대해 신경 쓸 필요 없이, 마치 여러 개의 View를 자연스럽게 나열하듯이 코드를 작성할 수 있게 됩니다.

 

@ViewBuilder의 작동 방식 (Result Builder의 일종)

@ViewBuilder는 Swift 5.4에 도입된 Result Builders라는 언어 기능을 활용합니다. Result Builder는 특정 클로저 내부에서 작성된 코드 블록을 컴파일러가 자동으로 변환(transform)하는 메커니즘을 제공합니다.

 

@ViewBuilder는 다음 규칙에 따라 View들을 변환합니다:

  1. 단일 View : 클로저 내에 하나의 View만 있으면, 그 View를 그대로 반환합니다.
  2. 여러 개의 View : 클로저 내에 여러 개의 View가 나열되면, 이 View들을 TupleView로 묶어서 반환합니다. TupleView는 최대 10개까지의 View를 담을 수 있습니다.
  3. if / else if / else : 조건문 내의 View들은 _ConditionalContent라는 View로 묶어서 반환합니다. 이는 조건에 따라 다른 View가 표시될 수 있도록 해줍니다.
  4. ForEach : ForEach 내의 View들은 _ForEachView로 묶어서 반환합니다.
  5. Optional View : if let 바인딩이나 Optional View를 반환하는 경우에도 @ViewBuilder는 이를 처리할 수 있습니다.
  6. buildBlock 메서드 : @ViewBuilder는 내부적으로 buildBlock과 같은 메서드를 사용하여 여러 View를 조합합니다. 예를 들어, 두 개의 View가 나열되면 buildBlock(view1, view2)와 같이 호출되어 TupleView<(View1, View2)>를 생성합니다.

 

@ViewBuilder의 활용 예시

@ViewBuilder는 SwiftUI의 다양한 곳에서 사용됩니다.

  • body 프로퍼티 : View 프로토콜의 body 프로퍼티는 암시적으로 @ViewBuilder가 적용됩니다.
struct MyView: View {
    var body: some View { // 여기도 사실상 @ViewBuilder가 적용되어 있음
    	Text("First")
        Text("Second")
    }
}

 

  • 커스텀 컨테이너 View : 자신만의 커스텀 컨테이너 View를 만들 때, 내부 컨텐츠를 받기 위해 @ViewBuilder를 사용할 수 있습니다.
struct CustomContainer<Content: View>: View {
    let content: Content
    
    init(@ViewBuilder content: () -> Content) {
    	self.content = content()
    }
    
    var body: some View {
    	VStack {
            Text("Header")
            content // @ViewBuilder로 전달받은 View들이 여기에 들어감
            Text("Footer")
        }
    }
}

struct ContentView: View {
    var body: some View {
    	CustomContainer { // 이 클로저에 @ViewBuilder가 적용됨
            Text("Hello, world!")
            Image(systemName: "globe")
        }
    }
}

 

  • Group : Group@ViewBuilder를 인자로 받습니다. 이는 10개 이상의 View를 body에 넣고 싶을 때 유용합니다.(TupleView는 최대 10개까지)
struct TooManyViews: View {
    var body: some View {
    	Group { // Group은 @ViewBuilder를 사용하여 여러 View를 묶을 수 있음
            Text("1")
            Text("2")
            Text("3")
            Text("4")
            Text("5")
            Text("6")
            Text("7")
            Text("8")
            Text("9")
            Text("10")
            Text("11") // Group이 없으면 에러 (TupleView limit)
        }
    }
}

 

  • View Modifier의 content 클로저 : 일부 View Modifier는 @ViewBuilder를 사용하여 컨텐츠를 받습니다.
// 예를 들어, .overlay modifier의 content 클로저도 @ViewBuilder가 적용되어 있습니다.
Text("Original")
    .overlay {
    	Rectangle().fill(.red)
        Text("Overlay")
    }

 

@ViewBuilder의 장점

  • 가독성 및 생산성 향상 : 여러 View를 자연스럽게 나열하듯이 코드를 작성할 수 있어 코드의 가독성이 높아지고 생산성이 향상됩니다.
  • 유연성 : 조건문(if), 반복문(ForEach) 등을 사용하여 동적으로 View를 구성할 수 있습니다.
  • 재사용성 : @ViewBuilder를 사용하여 자신만의 재사용 가능한 View 컨테이너를 쉽게 만들 수 있습니다.
  • SwiftUI 생태계와의 통합 :  SwiftUI의 핵심적인 작동 방식 중 하나로, SwiftUI의 모든 기본 컨테이너 View(VStack, HStack, ZStack 등)와 Modifier들이 @ViewBuilder를 활용하고 있습니다.

 

결론

@ViewBuilder는 SwiftUI에서 View를 구성하는 방식의 핵심입니다. 개발자가 복잡한 View 계층 구조를 명시적으로 작성하지 않고도, 직관적으로 여러 View를 조합할 수 있도록 도와주는 강력한 도구입니다. Swift의 Result Builders 기능 덕분에 가능하며, SwiftUI 코드의 간결함과 가독성을 크게 향상시킵니다.

반응형

'SwiftUI' 카테고리의 다른 글

@FocusState  (2) 2025.06.04
GeometryReader  (2) 2024.09.27
@Environment  (0) 2024.09.27
@Published  (0) 2024.09.22
@ObservedObject  (0) 2024.09.21