본문으로 건너뛰기

안전 영역 (Safe Area)

Thumbnail Image

🔔 최신화 일자: 2026-07-01

안전 영역 (Safe Area) 이해하기

안전 영역 (Safe Area)은 디바이스의 노치, 홈 인디케이터, 시스템 바 등 시스템 UI로 가려지지 않는 안전한 화면 영역을 의미합니다.

최근 출시되는 스마트폰은 노치, 펀치홀, 다이나믹 아일랜드 등 다양한 형태의 디스플레이를 채택하고 있으며, 화면 상단과 하단에 시스템 UI 요소가 배치됩니다. 이러한 요소들로 인해 앱의 중요한 콘텐츠나 UI가 가려질 수 있어, 안전 영역을 고려한 레이아웃 설계가 필수적입니다.

예시

예를 들어, iPhone X 이상 기기에서는 상단의 노치와 하단의 홈 인디케이터가 존재합니다.
앱을 풀스크린으로 사용할 경우 안전 영역을 고려하지 않으면 중요한 버튼이나 텍스트가 노치나 홈 인디케이터에 가려져 사용자 경험이 저해될 수 있습니다.

안전 영역을 올바르게 처리하면 모든 디바이스에서 일관되고 최적화된 사용자 경험을 제공할 수 있으며, 앱의 UI가 시스템 요소에 의해 가려지지 않도록 보장할 수 있습니다.


플랫폼별 안전 영역 (Safe Area) 개념

iOS의 Safe Area Insets

iOS에서 Safe Area는 UIView의 safeAreaInsets 프로퍼티를 통해 제공됩니다.

Safe Area가 필요한 주요 iOS 디바이스 요소

  • 노치 (Notch) : iPhone X 이상 기기의 상단 카메라 및 센서 영역
  • 다이나믹 아일랜드 (Dynamic Island) : iPhone 14 Pro 이상 기기의 상단 인터랙티브 영역
  • 홈 인디케이터 (Home Indicator) : iPhone X 이상 기기의 하단 제스처 바

Apple은 개발자가 안전 영역을 벗어나지 않도록 레이아웃을 구성할 것을 강력히 권장합니다.


Android의 Window Insets

Android에서는 WindowInsets를 통해 시스템 바와 디스플레이 컷아웃(노치, 펀치홀) 정보를 제공합니다.

Safe Area가 필요한 주요 Android 디바이스 요소

  • 상태 바 (Status Bar) : 화면 상단의 시간, 배터리, 네트워크 정보 표시 영역
  • 네비게이션 바 (Navigation Bar) : 화면 하단의 뒤로 가기, 홈, 최근 앱 버튼 영역
  • 디스플레이 컷아웃 (Display Cutout) : 노치, 펀치홀 등 카메라 및 센서 영역

Android는 Edge-to-Edge 디스플레이를 지원하며, 개발자는 WindowInsets를 활용하여 시스템 UI와 겹치지 않도록 레이아웃을 조정해야 합니다.

Android Window Insets 공식 문서

nachocode 앱의 시스템 바와 Safe Area

nachocode로 생성한 앱은 기본적으로 시스템 바 (상단 네비게이션 바)를 제공합니다. 이 시스템 바는 자동으로 안전 영역을 고려하여 배치되므로, 기본 설정에서는 별도의 Safe Area 처리가 필요하지 않습니다.

시스템 바 설정

nachocode 시스템 바에 대한 자세한 내용은 다음 링크에서 확인하세요.
➡️ 나쵸코드 사용자 가이드 - 시스템 바

하지만 풀스크린 앱을 만들고자 할 때는 시스템 바를 비활성화할 수 있습니다.

시스템 바 비활성화 방법

  1. 나쵸코드 대시보드 접속
  2. 앱 디자인 > 시스템 바 메뉴로 이동
  3. 시스템 바를 "미사용"으로 체크
  4. 앱 빌드 및 배포
풀스크린 모드 사용 시 주의사항

시스템 바를 비활성화하고 풀스크린 모드로 앱을 사용할 경우, 반드시 Safe Area Insets를 확인하여 UI 레이아웃을 조정해야 합니다.
그렇지 않으면 중요한 콘텐츠가 노치, 홈 인디케이터, 시스템 바 등에 가려질 수 있습니다.


nachocode에서 Safe Area 처리하기

nachocode는 iOS와 Android 모두에서 안전 영역을 쉽게 처리할 수 있도록 두 가지 방식을 제공합니다.

1. SDK 메서드를 통한 동적 할당

nachocode SDK의 Nachocode.device.getSafeAreaInsets() 메서드를 호출하여 JavaScript로 Safe Area Insets 값을 동적으로 조회하고 활용할 수 있습니다.

지원 플랫폼

플랫폼지원 여부
Android✅ 정상 동작
iOS✅ 정상 동작
Web❌ 지원하지 않음

사용 방법

// Safe Area Insets 조회
const safeAreaInsets = await Nachocode.device.getSafeAreaInsets();

if (!safeAreaInsets.isError) {
console.log(`Top: ${safeAreaInsets.top}px`);
console.log(`Bottom: ${safeAreaInsets.bottom}px`);
console.log(`Left: ${safeAreaInsets.left}px`);
console.log(`Right: ${safeAreaInsets.right}px`);
} else {
console.error(`Safe Area Insets 조회 실패: ${safeAreaInsets.errorMessage}`);
}

CSS 변수로 설정하여 활용

// Safe Area Insets 정보를 CSS 변수로 설정하여 레이아웃에 활용
async function applySafeAreaInsets() {
const safeAreaInsets = await Nachocode.device.getSafeAreaInsets();

if (!safeAreaInsets.isError) {
const root = document.documentElement;
root.style.setProperty('--safe-area-inset-top', `${safeAreaInsets.top}px`);
root.style.setProperty(
'--safe-area-inset-bottom',
`${safeAreaInsets.bottom}px`
);
root.style.setProperty(
'--safe-area-inset-left',
`${safeAreaInsets.left}px`
);
root.style.setProperty(
'--safe-area-inset-right',
`${safeAreaInsets.right}px`
);
}
}

// 앱 시작 시 호출
applySafeAreaInsets();
/* CSS에서 사용 */
.header {
padding-top: var(--safe-area-top, env(safe-area-inset-top, 0px));
}

.footer {
padding-bottom: var(--safe-area-bottom, env(safe-area-inset-bottom, 0px));
}

.content {
padding-left: var(--safe-area-left, env(safe-area-inset-left, 0px));
padding-right: var(--safe-area-right, env(safe-area-inset-right, 0px));
}
SDK 메서드 상세 정보

getSafeAreaInsets() 메서드에 대한 자세한 API 문서는 다음 링크에서 확인하세요.
➡️ SDK 문서 - getSafeAreaInsets()


2. Native Layer에서 자동 주입되는 CSS 변수

nachocode 앱은 Native Layer에서 Safe Area Insets 값을 자동으로 CSS 변수로 주입합니다.
별도의 SDK 호출 없이 CSS에서 바로 활용할 수 있어 간편하게 활용할 수 있습니다.

제공되는 CSS 변수

nachocode 앱은 네이티브 레이어에서 다음 CSS 변수를 자동으로 주입합니다.

  • --safe-area-top : 상단 Safe Area (px)
  • --safe-area-right : 우측 Safe Area (px)
  • --safe-area-bottom : 하단 Safe Area (px)
  • --safe-area-left : 좌측 Safe Area (px)

지원 플랫폼

플랫폼지원 여부
Android✅ 정상 동작
iOS✅ 정상 동작
Web❌ 지원하지 않음

사용 방법

CSS에서 바로 변수를 활용할 수 있습니다.

/* 헤더에 상단 Safe Area 적용 */
.header {
padding-top: var(--safe-area-top, env(safe-area-inset-top, 0px));
background-color: #fff;
}

/* 하단 네비게이션에 하단 Safe Area 적용 */
.bottom-nav {
padding-bottom: var(--safe-area-bottom, env(safe-area-inset-bottom, 0px));
background-color: #f0f0f0;
}

/* 전체 컨테이너에 좌우 Safe Area 적용 */
.container {
padding-left: var(--safe-area-left, env(safe-area-inset-left, 0px));
padding-right: var(--safe-area-right, env(safe-area-inset-right, 0px));
}

/* 모든 안전 영역을 한번에 적용 */
.fullscreen-content {
padding-top: var(--safe-area-top, env(safe-area-inset-top, 0px));
padding-right: var(--safe-area-right, env(safe-area-inset-right, 0px));
padding-bottom: var(--safe-area-bottom, env(safe-area-inset-bottom, 0px));
padding-left: var(--safe-area-left, env(safe-area-inset-left, 0px));
}
권장 사항

CSS 변수 방식은 별도의 JavaScript 코드 없이 CSS만으로 안전 영역을 처리할 수 있어 가장 간편합니다.
풀스크린 앱을 개발할 때는 이 방식을 우선적으로 사용하는 것을 권장합니다.


실전 활용 예제

예제 1: 풀스크린 비디오 플레이어

풀스크린 비디오 플레이어를 구현할 때 컨트롤 버튼이 노치나 홈 인디케이터에 가려지지 않도록 처리

.video-container {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: black;
}

.video-controls {
position: absolute;
bottom: 0;
left: 0;
right: 0;
/* 하단 Safe Area만큼 여백 추가 */
padding-bottom: var(--safe-area-bottom, env(safe-area-inset-bottom, 0px));
background: rgba(0, 0, 0, 0.5);
}

예제 2: 하단 고정 버튼

화면 하단에 고정된 액션 버튼이 홈 인디케이터에 가려지지 않도록 처리

.fixed-button {
position: fixed;
bottom: 0;
left: 0;
right: 0;
/* 기본 여백 + Safe Area 여백 */
padding: 16px;
padding-bottom: calc(
16px + var(--safe-area-bottom, env(safe-area-inset-bottom, 0px))
);
background: #007aff;
color: white;
}

예제 3: React에서 동적으로 Safe Area 적용

React 환경에서 SDK를 활용하여 안전 영역을 동적으로 적용

import { useEffect, useState } from 'react';

function App() {
const [safeArea, setSafeArea] = useState({
top: 0,
bottom: 0,
left: 0,
right: 0,
});

useEffect(() => {
async function loadSafeArea() {
if (window.Nachocode && window.Nachocode.env.isApp()) {
const result = await window.Nachocode.device.getSafeAreaInsets();
if (!result.isError) {
setSafeArea(result);
}
}
}
loadSafeArea();
}, []);

return (
<div
style={{
paddingTop: `${safeArea.top}px`,
paddingBottom: `${safeArea.bottom}px`,
paddingLeft: `${safeArea.left}px`,
paddingRight: `${safeArea.right}px`,
}}
>
<h1>풀스크린 앱</h1>
<p>Safe Area가 적용된 콘텐츠입니다.</p>
</div>
);
}

예제 4: CSS 변수를 활용한 전체 레이아웃

네이티브에서 자동 주입되는 CSS 변수를 활용한 전체 레이아웃 구성

<!DOCTYPE html>
<html>
<head>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}

body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
}

.app-container {
display: flex;
flex-direction: column;
min-height: 100vh;
}

/* 헤더 - 상단 Safe Area 적용 */
.header {
padding-top: var(--safe-area-top, env(safe-area-inset-top, 0px));
padding-left: var(--safe-area-left, env(safe-area-inset-left, 0px));
padding-right: var(--safe-area-right, env(safe-area-inset-right, 0px));
background: #007aff;
color: white;
padding-bottom: 16px;
}

.header h1 {
padding: 16px;
padding-top: 8px;
}

/* 메인 콘텐츠 - 좌우 Safe Area 적용 */
.main-content {
flex: 1;
padding-left: calc(
16px + var(--safe-area-left, env(safe-area-inset-left, 0px))
);
padding-right: calc(
16px + var(--safe-area-right, env(safe-area-inset-right, 0px))
);
padding-top: 16px;
padding-bottom: 16px;
}

/* 하단 네비게이션 - 하단 Safe Area 적용 */
.bottom-nav {
display: flex;
justify-content: space-around;
padding: 12px;
padding-bottom: calc(
12px + var(--safe-area-bottom, env(safe-area-inset-bottom, 0px))
);
padding-left: calc(
12px + var(--safe-area-left, env(safe-area-inset-left, 0px))
);
padding-right: calc(
12px + var(--safe-area-right, env(safe-area-inset-right, 0px))
);
background: #f0f0f0;
border-top: 1px solid #ddd;
}

.nav-item {
padding: 8px 16px;
cursor: pointer;
}
</style>
</head>
<body>
<div class="app-container">
<header class="header">
<h1>nachocode 앱</h1>
</header>

<main class="main-content">
<h2>Safe Area가 적용된 풀스크린 앱</h2>
<p>모든 디바이스에서 최적화된 레이아웃을 제공합니다.</p>
</main>

<nav class="bottom-nav">
<div class="nav-item"></div>
<div class="nav-item">검색</div>
<div class="nav-item">설정</div>
</nav>
</div>
</body>
</html>

주의사항

1. 웹 환경에서는 지원되지 않음

Safe Area 기능은 네이티브 앱 환경 (Android, iOS)에서만 동작합니다.
웹 브라우저에서는 Safe Area 값을 조회할 수 없으므로, 환경 체크를 통해 네이티브 앱에서만 적용하도록 구현하세요.

// 네이티브 앱 환경에서만 Safe Area 적용
if (Nachocode.env.isApp()) {
const safeArea = await Nachocode.device.getSafeAreaInsets();
// Safe Area 처리
}

2. 단위는 픽셀(px)

Safe Area Insets 값은 픽셀(px) 단위로 제공됩니다. iOS의 포인트(pt) 값을 그대로 픽셀로 적용해도 올바르게 동작하므로, CSS에 적용 시 별도의 변환 없이 px 단위로 사용하면 됩니다.

/* 올바른 사용법 */
.header {
padding-top: var(--safe-area-top); /* px 단위로 적용 */
}
주의

전달받은 pt 값을 px로 그대로 쓰기 위해서는 반드시 올바른 Viewport 메타 태그가 설정되어 있어야 합니다.

<meta name="viewport" content="width=width-device, initial-scale=1.0" />

이 태그가 누락되면 크기가 축소되거나 왜곡될 수 있습니다.


3. 시스템 바 사용 시에는 불필요

nachocode 시스템 바를 사용하는 경우, 이미 Safe Area가 자동으로 처리되므로 별도의 Safe Area 처리가 필요하지 않습니다.
시스템 바를 비활성화하고 풀스크린 모드로 앱을 사용할 때만 Safe Area 처리가 필요합니다.

시스템 바 설정

nachocode 시스템 바에 대한 자세한 내용은 다음 링크에서 확인하세요.
➡️ 나쵸코드 사용자 가이드 - 시스템 바


4. 디바이스별 테스트 필수

Safe Area는 디바이스마다 다를 수 있으므로, 다양한 디바이스에서 테스트하는 것이 중요합니다.

테스트 권장 디바이스

  • iOS: iPhone X 이상 (노치 있는 기기), iPhone 14 Pro 이상 (다이나믹 아일랜드)
  • Android: 노치/펀치홀이 있는 기기, 네비게이션 바가 있는 기기

릴리즈 정보

Safe Area 기능은 다음 버전부터 지원됩니다.

SDK

App Source


기술 지원

nachocode 팀은 여러분의 성공적인 프로젝트 구현을 위해 항상 도움을 준비하고 있습니다.
Safe Area 처리와 관련된 기술적인 질문이나 피드백이 있다면 언제든지 support@nachocode.io이메일을 보내주세요.