SwiftUI를 통해 개발하다보면 Grid를 사용할 일이 매우 많은데요. 사용하다보면 VStack + HStack 조합과 차이점이 무엇인가 궁금증이 있었습니다. 해당 글은 이에 대한 궁금증을 풀고자 작성한 글입니다.
글을 들어가기에 앞서 Grid가 무엇인지 공식문서를 보며 간단한 정의에 대해 알아보도록 하겠습니다.
해석해 보면, “2차원 레이아웃으로 다른 뷰를 배열하는 컨테이너 뷰”라고 합니다.
좀 더 자세히 알아볼까요?
OverView를 살펴보면, 그리드는 GridRow 구조의 컬렉션으로 Grid를 초기화하여 2차원 레이아웃을 만든다고 합니다. 또한 각 그리드 행의 첫 번째 보기는 그리드의 첫 번째 열에 표시되고, 두 번째 보기는 두 번째 열에 표시된다고 하네요.
그리드에 대해서는 이 정도 알아보기로 하고, 이제 본론으로 들어가 볼까요?
공식문서에서 예제 아래 문구를 보면
라고 되어 있습니다.
이게 무슨 소리인가 싶은가 싶은데요, 한줄씩 해석하며 정리해 보겠습니다.
A grid and its rows behave something like a collection of
HStack
instances wrapped in aVStack
첫번째 문장을 해석하면 “그리드는 겉보기에 VStack 안에 여러 개의 HStack이 들어 있는 구조처럼 보입니다.” 라는 뜻입니다.
말 그대로, 각 HStack은 한 줄(행)을 나타내고, VStack은 그 행들을 위에서 아래로 쌓는 것처럼 작동한다는 것입니다. 중요한건 이 다음인데요.
However, the grid handles row and column creation as a single operation, which applies alignment and spacing to cells, rather than first to rows and then to a column of unrelated rows
Grid는 행(row)과 열(column)을 별도로 따로 처리하지 않고, 전체 셀을 기준으로 한 번에 정렬과 간격을 처리합니다. 즉, VStack + HStack처럼 “먼저 행 정렬 → 그 다음 열 모양이 우연히 생기는 구조”가 아니라,
처음부터 2D 그리드로서 정렬/간격을 계산합니다.
한마디로 정리하면, 전체 셀에 대해 그리드 전체의 맥락에서 간격과 정렬을 적용한다는 것입니다.
정리하면 다음과 같습니다.
VStack 안에 HStack | Grid |
---|---|
하나의 행(HStack)마다 간격, 정렬이 따로 적용됨 | 전체 셀들에 대해 열(row)과 행(column)을 동시에 고려하여 정렬/간격 처리 |
행을 먼저 만들고, 그걸 세로로 쌓음 | 그리드는 처음부터 전체 그리드 레이아웃을 2D 구조로 처리 |
각 HStack은 서로 독립적인 | Grid는 전체가 하나의 레이아웃 시스템으로 작동함 |
이번에는 공식 문서에 있는 예제를 활용하여 어떤 차이가 생기는지 확인해 보겠습니다.
VStack(alignment: .leading) {
HStack {
Text("Hello")
Image(systemName: "globe")
}
HStack {
Image(systemName: "hand.wave")
Text("World")
}
}
Grid(alignment: .leading) {
GridRow {
Text("Hello")
Image(systemName: "globe")
}
GridRow {
Image(systemName: "hand.wave")
Text("World")
}
}
struct ContentView: View {
var body: some View {
Group {
vstackExample
Spacer()
gridExample
}
.frame(height: 40)
}
private var vstackExample: some View {
VStack(alignment: .leading) {
HStack {
Text("Hello")
Image(systemName: "globe")
}
HStack {
Image(systemName: "hand.wave")
Text("World")
}
}
}
private var gridExample: some View {
Grid(alignment: .leading) {
GridRow {
Text("Hello")
Image(systemName: "globe")
}
GridRow {
Image(systemName: "hand.wave")
Text("World")
}
}
}
}
차이가 보이시나요?
VStack의 경우 각 행(HStack)의 내부 정렬만 고려돼요. 왼쪽 정렬을 하더라도, 열 단위의 정렬이 일관되지 않을 수 있어요.
반면에, Grid의 경우에는 열(column) 기준으로도 정렬을 고려해서, 각 열의 너비, 정렬, 간격 등을 전부 계산해서 일관되게 맞춰줍니다.
정리하자면, SwiftUI의 Grid는 단순히 HStack을 VStack에 쌓은 구조처럼 보일 수 있지만, 실제로는 열과 행을 동시에 고려하는 2차원 레이아웃 시스템입니다.
모든 셀에 대해 정렬, 간격, 크기를 일관되게 계산하며 배치하기 때문에, VStack + HStack 조합보다 더 정밀하고 예측 가능한 레이아웃 구성이 가능합니다.
특히 복잡한 UI를 구현할 때, 각 열의 너비와 정렬을 정확하게 맞춰야 하는 상황에서는 Grid를 사용하는 것이 훨씬 효율적이며, 깔끔한 UI를 구성할 수 있습니다.