@ViewBuilder

BS_Lee·2025년 7월 20일

swift

목록 보기
20/21

@ViewBuilder 완전 정리 — 왜 필요한가?

SwiftUI로 UI를 작성하다 보면 여러 개의 뷰를 나열하는 상황이 많다.
하지만 SwiftUI의 함수나 body단 하나의 View만 반환해야 한다.
그럼에도 여러 개의 뷰를 쌓을 수 있는 이유가 뭘까? 바로 @ViewBuilder 덕분이다.


1. @ViewBuilder란?

@ViewBuilder여러 개의 뷰를 하나의 View로 조합해주는 Function Builder이다.

쉽게 말해, 여러 View를 선언적으로 나열하면 Swift가 알아서 하나의 View 트리로 합쳐준다.
이 덕분에 body나 커스텀 컴포넌트에서 뷰를 자연스럽게 쌓을 수 있다.


2. 왜 필요한가?

SwiftUI에서 함수나 프로퍼티는 some View → 단일 View만 반환 가능하다.

func myView() -> some View {
    Text("Hello")
    Text("World")   // 오류 발생
}

그럼 이렇게 여러 View를 어떻게 쌓을 수 있을까?
@ViewBuilder가 이 문제를 해결해준다.

@ViewBuilder
func myView() -> some View {
    Text("Hello")
    Text("World")   // 자동으로 TupleView로 묶임
}

Swift는 내부적으로 이 코드를 TupleView<(Text, Text)> 형태로 변환해준다.

@ViewBuilder를 쓰다보면 계속해서 아래와 같은 식으로 꼬리에 꼬리를 물면서 하나로 생성이 된다.

ModifiedContent<ModifiedContent<ModifiedContent<ModifiedContent<ModifiedContent<Text, _FrameLayout>, _BackgroundStyleModifier<AnyGradient>>, _EnvironmentKeyWritingModifier<Optional<Color>>>, _EnvironmentKeyWritingModifier<Optional<Font>>>, _ClipEffect<RoundedRectangle>>

3. 내부 원리

@ViewBuilder는 Swift의 Function Builder 기능을 사용한다.
컴파일러가 빌더 안의 여러 반환값을 하나로 합쳐주는 문법적 도우미다.

덕분에 다음과 같은 일이 가능해진다.

  • if/else, switch, ForEach 같은 제어문 사용
  • 여러 View를 선언적으로 조합

즉, SwiftUI의 선언적 UI 패러다임을 가능하게 하는 핵심 문법이다.


4. 활용 예시

4-1. 기본적인 사용

@ViewBuilder
func myView() -> some View {
    Text("Hello")
    Text("World")
}

자동으로 하나의 View로 합쳐지기 때문에 별도의 컨테이너를 명시하지 않아도 된다.


4-2. if/else 활용

@ViewBuilder
func greetingView(isMorning: Bool) -> some View {
    if isMorning {
        Text("Good Morning")
    } else {
        Text("Good Evening")
    }
}

빌더 내부에서 조건문을 자유롭게 쓸 수 있다.


4-3. ForEach 활용

@ViewBuilder
func listView(items: [String]) -> some View {
    ForEach(items, id: \.self) { item in
        Text(item)
    }
}

여러 개의 뷰를 동적으로 생성할 때도 유용하다.


4-4. 커스텀 뷰에서의 사용

@ViewBuilder클로저 형태로 View를 받아야 하는 커스텀 컴포넌트에서 특히 중요하다.

struct MyCard<Content: View>: View {
    let title: String
    let content: Content

    init(title: String, @ViewBuilder content: () -> Content) {
        self.title = title
        self.content = content()
    }

    var body: some View {
        VStack {
            Text(title)
                .font(.headline)
            content
        }
    }
}

struct ContentView: View {
    var body: some View {
        MyCard(title: "SwiftUI") {
            Text("ViewBuilder Example")
            Text("Hello World")
        }
    }
}

5. body는 왜 여러 View를 쌓을 수 있을까?

하나 의문이 생긴다. body에는 @ViewBuilder를 명시하지 않았는데 왜 여러 View를 쌓을 수 있을까?
정답은, SwiftUI가 body 프로퍼티에 암묵적으로 @ViewBuilder를 적용하기 때문이다.

즉, 다음 두 코드는 동일하게 작동한다.

// SwiftUI 내부에서 암묵적으로 이렇게 처리됨
@ViewBuilder
var body: some View {
    Text("Hello")
    Text("World")
}

7. 정리 — 한 줄 요약

개념설명
@ViewBuilder여러 View를 하나의 View 트리로 조합하는 SwiftUI 전용 Function Builder
필요성some View가 단일 View만 반환할 수 있기 때문
특징if/else, ForEach 등 제어문도 사용 가능
body암묵적으로 @ViewBuilder 적용

0개의 댓글