Swift - Safe Area

Marble·2026년 4월 14일

iOS 개발을 하다보면 화면 상단이나 하단에 영역이 있잖아요? 그 부분을 Safe Area라고 하는데 이번에는 Safe Area에 대해 간단하게 알아볼게요

Safe Area

iOS에서 화면을 만들 때 가장 자주 겪는 문제 중 하나는 “내 UI가 왜 위아래에 가려지지?”입니다. 이걸 해결하기 위해 Apple이 도입한 개념이 Safe Area에요. Safe Area는 노치, 상태바, 홈 인디케이터, 탭바/네비게이션바 같은 시스템 UI를 피해서 콘텐츠가 안전하게 보일 수 있는 영역을 의미해요

필요해진 이유

iOS 10 이하에서는 topLayoutGuide, bottomLayoutGuide 같은 방식으로 직접 대응해야 했습니다. 하지만 기기 화면 형태가 다양해지고(특히 iPhone X 이후), 노치/라운드 코너/홈 인디케이터가 등장하면서 기기마다 다르게 잘리는 문제가 커졌습니다

그래서 iOS 11부터 Safe Area가 공식 표준이 되었어요

UIKit에서 사용법

import UIKit

final class SafeAreaViewController: UIViewController {
    // 화면 상단에 보여줄 제목 라벨
    private let titleLabel = UILabel()

    // 화면 하단에 고정할 버튼
    private let bottomButton = UIButton(type: .system)

    override func viewDidLoad() {
        super.viewDidLoad()

        // 기본 배경색
        view.backgroundColor = .systemBackground

        // 라벨 텍스트/스타일 설정
        titleLabel.text = "Safe Area"
        titleLabel.font = .boldSystemFont(ofSize: 24)

        // Auto Layout을 쓰기 위해 autoresizing mask 변환 비활성화
        titleLabel.translatesAutoresizingMaskIntoConstraints = false

        // 버튼 텍스트 설정
        bottomButton.setTitle("계속", for: .normal)
        bottomButton.translatesAutoresizingMaskIntoConstraints = false

        // 뷰 계층에 추가
        view.addSubview(titleLabel)
        view.addSubview(bottomButton)

        // 제약 설정 시작
        NSLayoutConstraint.activate([
            // titleLabel의 top을 Safe Area top에 붙임
            // -> 노치/상태바 영역과 겹치지 않게 안전하게 배치
            titleLabel.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 16),

            // 왼쪽 여백 20
            titleLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20),

            // 버튼 좌우 여백 20
            bottomButton.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20),
            bottomButton.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20),

            // 버튼 bottom을 Safe Area bottom에 붙임
            // -> 홈 인디케이터(하단 바)와 겹치지 않게 배치
            bottomButton.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -16),

            // 버튼 높이 고정
            bottomButton.heightAnchor.constraint(equalToConstant: 48)
        ])
    }

    // Safe Area가 바뀔 때마다 호출됨
    // (예: 회전, 통화/핫스팟 상태바 변화 등)
    override func viewSafeAreaInsetsDidChange() {
        super.viewSafeAreaInsetsDidChange()

        // 현재 Safe Area 여백(top/left/bottom/right) 확인 가능
        // 디버깅할 때 유용
        print("SafeArea Insets:", view.safeAreaInsets)
    }
}

핵심만 말하면

  • 위/아래 핵심 UI는 view.safeAreaLayoutGuide에 붙여요
  • 배경만 필요하면 화면 끝까지(view.topAnchor, view.bottomAnchor) 깔 수 있어요

SwiftUI에서 사용법

4-1. 배경만 Safe Area 무시

struct SafeAreaExampleView: View {
    var body: some View {
        ZStack {
            LinearGradient(
                colors: [.blue, .mint],
                startPoint: .topLeading,
                endPoint: .bottomTrailing
            )
            .ignoresSafeArea() // 배경만 무시

            VStack(spacing: 16) {
                Text("콘텐츠는 Safe Area를 지킵니다")
                    .font(.title2.bold())

                Button("확인") {}
                    .buttonStyle(.borderedProminent)
            }
            .padding()
        }
    }
}

4-2. 하단 고정 버튼을 안전하게 배치

struct SafeAreaInsetView: View {
    var body: some View {
        ScrollView {
            Text("긴 본문...")
                .frame(maxWidth: .infinity, alignment: .leading)
                .padding()
        }
        .safeAreaInset(edge: .bottom) {
            Button("다음") {}
                .frame(maxWidth: .infinity)
                .padding()
                .background(.ultraThinMaterial)
        }
    }
}

핵심 원칙은 ignoresSafeArea()는 화면 전체에 무조건 적용하지 말고, 배경 레이어처럼 필요한 뷰에만 국소적으로 적용하는 거에요

profile
개발자가 되고 싶은 공돌이

0개의 댓글