본문으로 건너뛰기

UIKit에서 layoutMarginsGuide로 시스템 여백에 맞추기

How to use layoutMarginsGuide in UIKit

sarunw.com

핵심 요약

  1. 고정된 16포인트 여백은 기기와 방향에 따라 내비게이션 바의 제목과 어긋날 수 있으므로, layoutMarginsGuide에 제약을 연결하면 시스템이 정한 여백을 따를 수 있다.
  2. layoutMarginsGuide는 기본적으로 safe area 안쪽에서 추가 여백을 적용하며, layoutMargins 값은 safe area까지 포함한 뷰 가장자리로부터의 전체 거리를 나타낸다.
  3. 시스템 여백은 뷰 컨트롤러의 기본 뷰에 적용되고 하위 뷰는 기본적으로 각 측면 8포인트를 사용하므로, 여백을 전달하려면 preservesSuperviewLayoutMargins를 설정해야 한다.

도입

UIKit에서 콘텐츠를 시스템 제목이나 툴바 항목과 정렬하려고 고정된 16포인트 여백을 주면 기기별 차이를 놓칠 수 있다. 원문은 iPhone 17과 iPhone 18 Pro Max에서 같은 값이 서로 다르게 정렬되는 사례를 보여준다. 해결책은 뷰의 가장자리에 임의의 상수를 더하는 대신 layoutMarginsGuide에 제약을 연결하는 것이다.

상세 요약

고정 여백 대신 시스템 가이드 사용

뷰 가장자리에 16포인트를 더하는 방식은 일부 기기에서는 내비게이션 바의 큰 제목과 맞지만, 모든 기기에서 같은 결과를 내지는 않는다. 원문은 iPhone 17에서는 맞던 레이블이 iPhone 18 Pro Max에서는 제목보다 4포인트 앞에 놓이는 사례를 제시한다. 기기를 회전하면 시스템 여백도 달라질 수 있다.

UIView에는 각 가장자리에서 적절한 여백만큼 안쪽에 놓이는 layoutMarginsGuide가 있다. 레이블의 좌우 제약을 뷰의 leadingAnchor, trailingAnchor가 아니라 가이드의 해당 앵커에 연결하면 시스템 여백을 사용한다. 뷰 컨트롤러의 기본 뷰에서는 이 여백이 내비게이션 바의 제목과 버튼 위치에 맞춰진다.

let margins = view.layoutMarginsGuide
NSLayoutConstraint.activate([
    label.leadingAnchor.constraint(equalTo: margins.leadingAnchor),
    label.trailingAnchor.constraint(equalTo: margins.trailingAnchor),
    label.topAnchor.constraint(equalTo: margins.topAnchor)
])

safe area와 여백의 관계

기본적으로 layoutMarginsGuide는 safe area 안에 머문다. 먼저 safe area 경계에서 시작한 뒤 여백만큼 더 안쪽에 놓인다. 따라서 layoutMargins를 코드에서 읽으면 safe area와 추가 여백이 합쳐진, 뷰 가장자리로부터의 거리를 얻는다.

insetsLayoutMarginsFromSafeArea의 기본값은 true다. 이를 false로 바꾸면 가이드가 safe area를 무시한다. 원문 예시에서는 iPhone 18 Pro Max의 Dynamic Island 쪽에서 가이드가 화면 가장자리로부터 16포인트에 놓이고, 상단 가이드는 내비게이션 바 뒤로 들어간다. 특별한 이유가 없다면 기본 설정을 유지한다.

기기별 여백과 사용자 지정

원문이 iOS 27 시뮬레이터에서 측정한 좌우 여백은 기기와 방향에 따라 다르다.

  • iPhone 18 Pro: 세로 16/16, 가로 16/16
  • iPhone 18 Pro Max: 세로 20/20, 가로 16/16
  • iPad Pro 13인치: 세로와 가로 모두 20/20
  • 접힌 iPhone Duo: 세로 20/0, 가로 0/20

접힌 iPhone Duo에서는 세로 바 옆 추가 여백이 0이지만, 해당 바는 safe area에 포함되어 가이드가 바와 겹치지 않는다. 시스템이 기기별 값을 반영하므로 직접 여백 수치를 정해 둘 필요가 없다.

직접 값을 지정하려면 layoutMargins를 설정한다. 다만 뷰 컨트롤러의 기본 뷰는 systemMinimumLayoutMargins보다 작은 값을 허용하지 않는다. 원문 사례에서는 좌우를 4로 지정해도 20이 적용됐다. 최소값 아래로 내리려면 먼저 viewRespectsSystemMinimumLayoutMargins = false를 설정해야 한다.

하위 뷰와 SwiftUI

뷰 컨트롤러의 시스템 여백은 기본 뷰에만 적용된다. 다른 뷰는 좌우 8포인트에서 시작하므로, 하위 뷰의 layoutMarginsGuide에 콘텐츠를 연결하면 내비게이션 바와 정렬되지 않을 수 있다. 상위 뷰의 여백을 전달하려면 다음과 같이 설정한다.

banner.preservesSuperviewLayoutMargins = true

원문에서는 이 설정으로 전체 너비 배너가 기본 뷰와 같은 좌우 20포인트 여백을 사용했다. SwiftUI에는 iOS 27.1부터 UIKit 가이드와 같은 위치에 콘텐츠를 두는 contentMargins(for: .container)가 추가됐다. 관련 내용은 SwiftUI에서 시스템 콘텐츠 여백 사용하기에서 확인할 수 있다.

결론

layoutMarginsGuide를 사용하면 기기와 방향에 따라 달라지는 시스템 여백을 직접 계산하지 않고 콘텐츠에 적용할 수 있다. 기본 설정에서는 가이드가 safe area 안쪽에 놓이며, layoutMargins에는 safe area를 포함한 전체 거리가 담긴다. 하위 뷰에 같은 여백을 적용할 때는 preservesSuperviewLayoutMargins를 설정하고, 시스템 최소 여백보다 작은 값을 지정할 때는 뷰 컨트롤러의 제한 설정도 함께 확인해야 한다.