IT

SwiftUI alignmentGuide와 Custom Layout 완벽 이해

초코모찌롤 2026. 4. 3. 09:45
반응형
SwiftUI alignmentGuide와 Custom Layout 완벽 이해

SwiftUI alignmentGuide와 Custom Layout 완벽 이해

SwiftUI Layout의 내부 동작(Propose → Size → Place)을 이해했다면, 다음 단계는 정렬(alignment)을 직접 제어하는 방법입니다.

기본 Stack만으로 해결되지 않는 레이아웃은 alignmentGuideCustom Layout으로 해결할 수 있습니다.


1. alignment란 무엇인가?

SwiftUI에서 alignment는 부모가 자식 뷰를 어디 기준으로 정렬할지를 의미합니다.


HStack(alignment: .top) {
    Text("A")
    Text("B")
}

위 코드에서 HStack은 자식 뷰들을 top 기준으로 정렬합니다.


2. alignmentGuide란?

alignmentGuide는 뷰가 자신의 정렬 기준을 직접 정의할 수 있게 해주는 기능입니다.


Text("Hello")
    .alignmentGuide(.leading) { d in
        d[.trailing]
    }

이 코드는 "leading 정렬 기준을 trailing 기준으로 사용"하겠다는 의미입니다.

즉, alignmentGuide는 다음과 같이 동작합니다.

  • 부모가 alignment 기준 요청
  • 자식이 alignmentGuide로 응답

3. alignmentGuide 내부 동작

alignmentGuide는 결국 좌표 값을 재정의하는 것입니다.

  • d[.leading] → 기본 leading 위치
  • d[.trailing] → 기본 trailing 위치

이 값을 변경하면 부모의 배치 기준이 달라집니다.


4. 실전 예제

텍스트 기준선 맞추기


HStack(alignment: .firstTextBaseline) {
    Text("Hello")
        .font(.largeTitle)
    Text("World")
}

폰트 크기가 달라도 baseline 기준으로 정렬됩니다.


커스텀 정렬 만들기


extension VerticalAlignment {
    private enum CustomAlignment: AlignmentID {
        static func defaultValue(in d: ViewDimensions) -> CGFloat {
            d[.center]
        }
    }

    static let custom = VerticalAlignment(CustomAlignment.self)
}

HStack(alignment: .custom) {
    Text("A")
        .alignmentGuide(.custom) { d in d[.bottom] }

    Text("B")
        .alignmentGuide(.custom) { d in d[.top] }
}

각 뷰가 서로 다른 기준으로 정렬됩니다.


5. Custom Layout이 필요한 이유

alignmentGuide로도 해결이 안 되는 경우가 있습니다.

  • Grid처럼 복잡한 배치
  • Flow Layout (줄바꿈)
  • 동적 위치 계산

이럴 때 사용하는 것이 Layout protocol입니다.


6. Layout 프로토콜 기본 구조


struct CustomLayout: Layout {

    func sizeThatFits(
        proposal: ProposedViewSize,
        subviews: Subviews,
        cache: inout ()
    ) -> CGSize {
        return CGSize(width: 100, height: 100)
    }

    func placeSubviews(
        in bounds: CGRect,
        proposal: ProposedViewSize,
        subviews: Subviews,
        cache: inout ()
    ) {
        for subview in subviews {
            subview.place(at: bounds.origin, proposal: proposal)
        }
    }
}

여기서 중요한 역할은 다음과 같습니다.

  • sizeThatFits → 전체 크기 계산
  • placeSubviews → 자식 위치 배치

7. Flow Layout 예제

줄바꿈되는 레이아웃을 직접 구현할 수 있습니다.


struct FlowLayout: Layout {

    func sizeThatFits(proposal: ProposedViewSize,
                      subviews: Subviews,
                      cache: inout ()) -> CGSize {

        var width: CGFloat = 0
        var height: CGFloat = 0

        for subview in subviews {
            let size = subview.sizeThatFits(proposal)
            width = max(width, size.width)
            height += size.height
        }

        return CGSize(width: width, height: height)
    }

    func placeSubviews(in bounds: CGRect,
                       proposal: ProposedViewSize,
                       subviews: Subviews,
                       cache: inout ()) {

        var y: CGFloat = bounds.minY

        for subview in subviews {
            let size = subview.sizeThatFits(proposal)

            subview.place(
                at: CGPoint(x: bounds.minX, y: y),
                proposal: proposal
            )

            y += size.height
        }
    }
}

8. 언제 어떤 것을 써야 할까?

상황 사용 방법
단순 정렬 alignment
정렬 기준 변경 alignmentGuide
완전히 새로운 레이아웃 Layout protocol

9. 결론

SwiftUI Layout을 깊이 있게 사용하려면 다음 단계로 확장해야 합니다.

  • alignment → 기본 정렬
  • alignmentGuide → 기준 재정의
  • Layout → 완전 커스터마이징

이 세 가지를 이해하면 복잡한 UI도 제약 없이 구현할 수 있습니다.


다음 단계에서는 SwiftUI Layout 성능 최적화를 다루면 실무 활용도가 더욱 높아집니다.

반응형