SwiftUI 기초: VStack, HStack, ZStack

SwiftUI에서 UI 요소들을 정렬하고 배치하는 방법을 알아보는 것은 앱 개발의 가장 기본적인 단계다.

오늘은 SwiftUI에서 제공하는 세 가지 기본 스택 뷰 – VStack, HStack, ZStack의 사용법에 대해 알아보겠다.

스택이란?

스택(Stack)은 SwiftUI에서 여러 뷰를 그룹화하고 정렬하는 데 사용되는 컨테이너 뷰다. 각 스택은 방향에 따라 뷰를 정렬하는 방식이 다르다.

VStack, HStack, ZStack
VStack, HStack, ZStack
  • VStack: 뷰를 수직(Vertical)으로 정렬
  • HStack: 뷰를 수평(Horizontal)으로 정렬
  • ZStack: 뷰를 깊이(Z축)로 쌓아 올림

VStack, HStack, ZStack 사용하는 방법


VStack 사용하기

VStack은 여러 뷰를 위에서 아래로 수직으로 배열한다. 텍스트, 이미지, 버튼 등 다양한 UI 요소를 포함할 수 있다.

기본 시그니처

VStack의 기본 구조는 다음과 같다:

Swift
swift// 기본 VStack
VStack {
    // 내부 뷰들
}

// 속성을 가진 VStack
VStack(alignment: .leading, spacing: 10) {
    // 내부 뷰들
}
  • alignment: 수평 정렬 방식 (.leading, .center, .trailing)
  • spacing: 각 뷰 사이의 간격

예제 코드

Swift
swiftstruct VStackExample: View {
    var body: some View {
        VStack(alignment: .leading, spacing: 15) {
            Text("제목")
                .font(.title)
                .fontWeight(.bold)
            
            Text("부제목")
                .font(.headline)
                .foregroundColor(.gray)
            
            Button("버튼 클릭") {
                // 액션 코드
            }
            .padding()
            .background(Color.blue)
            .foregroundColor(.white)
            .cornerRadius(8)
        }
        .padding()
        .background(Color.yellow.opacity(0.2))
        .cornerRadius(12)
    }
}

HStack 사용하기

HStack은 뷰를 왼쪽에서 오른쪽으로 수평으로 배열한다. 여러 항목을 나란히 표시할 때 유용하다.

기본 시그니처

Swift
swift// 기본 HStack
HStack {
    // 내부 뷰들
}

// 속성을 가진 HStack
HStack(alignment: .top, spacing: 8) {
    // 내부 뷰들
}
  • alignment: 수직 정렬 방식 (.top, .center, .bottom, .firstTextBaseline, .lastTextBaseline)
  • spacing: 각 뷰 사이의 간격

예제 코드

Swift
swiftstruct HStackExample: View {
    var body: some View {
        HStack(alignment: .center, spacing: 12) {
            Image(systemName: "star.fill")
                .foregroundColor(.yellow)
            
            Text("중요 항목")
                .fontWeight(.semibold)
            
            Spacer()
            
            Text("상세 보기")
                .foregroundColor(.blue)
        }
        .padding()
        .background(Color.gray.opacity(0.1))
        .cornerRadius(8)
    }
}

ZStack 사용하기

ZStack은 뷰를 앞뒤로(z축 방향으로) 중첩시킨다. 배경 위에 텍스트를 올리거나, 여러 레이어를 겹치게 할 때 사용한다.

기본 시그니처

Swift
swift// 기본 ZStack
ZStack {
    // 내부 뷰들 (첫 번째 뷰가 맨 뒤, 마지막 뷰가 맨 앞)
}

// 속성을 가진 ZStack
ZStack(alignment: .topLeading) {
    // 내부 뷰들
}
  • alignment: 뷰의 정렬 방식 (.center, .topLeading, .top, .topTrailing 등)

예제 코드

Swift
swiftstruct ZStackExample: View {
    var body: some View {
        ZStack(alignment: .bottomTrailing) {
            // 배경 이미지
            Color.blue.opacity(0.3)
                .frame(width: 300, height: 200)
                .cornerRadius(15)
            
            // 중간 레이어
            VStack(alignment: .leading) {
                Text("카드 제목")
                    .font(.title3)
                    .fontWeight(.bold)
                
                Text("카드 설명")
                    .font(.body)
            }
            .padding()
            .background(Color.white.opacity(0.8))
            .cornerRadius(10)
            .padding(20)
            
            // 전면 레이어
            Text("NEW")
                .font(.caption)
                .fontWeight(.bold)
                .foregroundColor(.white)
                .padding(8)
                .background(Color.red)
                .cornerRadius(8)
                .padding(12)
        }
    }
}

스택 조합하기

Stack의 조합
Stack의 조합

실제 앱 개발에서는 이러한 스택들을 조합해서 복잡한 레이아웃을 구성한다. 스택 안에 다른 스택을 넣는 것도 가능하다.

Swift
swiftstruct CombinedStacksExample: View {
    var body: some View {
        VStack(spacing: 20) {
            // 제목 영역
            Text("스택 조합 예시")
                .font(.title)
                .fontWeight(.bold)
            
            // 카드 목록
            VStack(spacing: 12) {
                // 첫 번째 카드
                HStack {
                    Image(systemName: "swift")
                        .font(.largeTitle)
                        .foregroundColor(.orange)
                    
                    VStack(alignment: .leading) {
                        Text("Swift")
                            .font(.headline)
                        Text("프로그래밍 언어")
                            .font(.subheadline)
                            .foregroundColor(.gray)
                    }
                    
                    Spacer()
                    
                    ZStack {
                        Circle()
                            .fill(Color.green)
                            .frame(width: 30, height: 30)
                        
                        Text("A")
                            .foregroundColor(.white)
                            .fontWeight(.bold)
                    }
                }
                .padding()
                .background(Color.gray.opacity(0.1))
                .cornerRadius(12)
                
                // 두 번째 카드 (비슷한 구조)
                HStack {
                    Image(systemName: "hammer.fill")
                        .font(.largeTitle)
                        .foregroundColor(.purple)
                    
                    VStack(alignment: .leading) {
                        Text("SwiftUI")
                            .font(.headline)
                        Text("UI 프레임워크")
                            .font(.subheadline)
                            .foregroundColor(.gray)
                    }
                    
                    Spacer()
                    
                    ZStack {
                        Circle()
                            .fill(Color.blue)
                            .frame(width: 30, height: 30)
                        
                        Text("B")
                            .foregroundColor(.white)
                            .fontWeight(.bold)
                    }
                }
                .padding()
                .background(Color.gray.opacity(0.1))
                .cornerRadius(12)
            }
            .padding(.horizontal)
        }
        .padding()
    }
}

스택의 성능 고려사항

많은 뷰를 포함하는 스택은 성능에 영향을 줄 수 있다. 특히 깊게 중첩된 스택은 성능 문제를 일으킬 수 있으므로 적절히 사용해야 한다.

  • 불필요한 중첩을 피한다
  • LazyVStack과 LazyHStack을 사용하여 필요할 때만 뷰를 로드한다.(스크롤 됐을 때 불러오는 뷰다.)
  • Group을 사용하여 뷰를 그룹화하면서 불필요한 스택을 줄일 수 있다.

VStack, HStack, ZStack 사용법을 마치며


SwiftUI의 VStack, HStack, ZStack은 앱 UI를 구성하는 가장 기본적인 빌딩 블록이다. 이 세 가지 스택을 적절히 조합하면 거의 모든 UI 레이아웃을 만들 수 있다.

화면 크기에 따라 자동으로 조정되는 반응형 레이아웃을 구현하기 위해서는 이러한 스택들의 특성을 잘 이해하고 활용하는 것이 중요하다.

특히 iOS와 iPadOS, macOS에서 모두 잘 작동하는 앱을 만들고 싶다면 스택을 적절하게 사용하여 다양한 화면 크기에 대응할 수 있다.

더 자세한 정보는 Apple 공식 문서에서 확인할 수 있다.