● 목차 68개 항목 전체 주석 + 디자인 원칙 7

Toolbar · Text · Tab Bar · Sheets · Safe Area Bar · System Materials · Menu 목차별 설명 — 언제 · 기준 · 설계 의도

원래 목차 구조를 그대로 유지하고, 각 항목마다 다섯 가지를 달았습니다: 어느 상황에서 사용하는가 / 이렇게 해야하는 이유 / TIP 실무 참고 / 적절한 예 실제 앱 기준 좋은 사례 2개 / 잘못된 예 흔한 오용 사례 2개 / 참고 자료 해당 항목의 근거 출처. 각 항목 오른쪽의 미니 프리뷰는 해당 요소가 화면 어디에 놓이는지(파란 하이라이트)를 보여줍니다.
본문은 iOS 26(WWDC25) 기준이며, 그 이후 바뀐 내용은 iOS 27 업데이트 행으로 구분해 반영했습니다 (WWDC26 발표 + iOS 27 베타·보도 기준, 최종 업데이트 2026-07-17). 전체 출처는 참고자료 페이지에 있습니다. 왼쪽 목차를 누르면 해당 항목 페이지로 바로 이동합니다.

1

Toolbar — Items · Title Display Modes · Scroll Edge Effects · Search

1.1

Items

아홉 개 케이스는 결국 세 변수의 조합입니다 — 위치(top leading/trailing · principal · bottom), 개수(단일 vs 클러스터), 공간 부족 시 처리(overflow). 순서대로 단순→복잡으로 진행됩니다.

1.1.1

Single Trailing Item

오른쪽 상단에 버튼 하나만 있는 최소 구성. 유리 캡슐 하나가 떠 있는 형태.

어느 상황에서 사용하는가
화면에 의미 있는 액션이 딱 하나일 때 — 편집, 완료, 추가(+), 공유 등. 액션이 하나뿐이라면 늘리지 말고 이 형태를 유지하는 게 정답.
이렇게 해야하는 이유
trailing은 iOS에서 primary action의 관례적 위치. 오른손 엄지 대각선상에 있고, leading은 뒤로가기가 선점하므로 충돌이 없음. 버튼이 하나면 유리 캡슐도 하나 — 시각적 무게 최소화(content-first).
Tip
액션 하나짜리 화면에서 굳이 bottom bar를 만들면 과합니다. 하단 바는 "자주·반복해서 누르는" 액션용.
적절한 예
① 메모 상세 화면 오른쪽 상단의 완료 버튼 하나 ② 목록 화면의 +(새 항목) 하나 — 액션이 하나뿐이니 형태도 하나
잘못된 예
① 액션이 하나뿐인데 공유·별표 같은 장식용 버튼을 억지로 추가해 캡슐을 채움 ② 유일한 액션을 시스템 자리 대신 커스텀 플로팅 버튼으로 화면 위에 띄움
오른쪽 상단(trailing)에 단일 액션 캡슐 하나
1.1.2

Leading Cluster and Trailing Item

왼쪽에 여러 버튼이 한 유리 그룹(cluster)으로 묶이고, 오른쪽엔 단일 버튼.

어느 상황에서 사용하는가
왼쪽엔 서로 관련된 보조 도구들(보기 전환, 정렬, 필터 묶음), 오른쪽엔 확정성 액션 하나(완료·저장)를 둘 때. "도구 vs 결정"이 나뉘는 화면.
이렇게 해야하는 이유
Liquid Glass에서 묶음 = 의미. 같은 캡슐 안에 있으면 사용자는 "이것들은 한 세트"로 읽습니다. 왼쪽 묶음(도구 세트)과 오른쪽 단일(결정)이 분리돼 있어야 역할이 오독되지 않음.
Tip
leading에 클러스터를 두면 뒤로가기 버튼 자리와 경쟁합니다. 루트 화면이거나 모달처럼 back이 없는 화면에서 주로 쓰는 패턴.
적절한 예
① 파일 앱 — 왼쪽에 보기 전환·정렬 묶음, 오른쪽에 선택 ② 문서 편집기 — 왼쪽에 실행취소/재실행 묶음, 오른쪽에 완료
잘못된 예
① 성격이 다른 삭제 + 정렬을 한 캡슐에 묶어 한 세트처럼 보이게 함 ② push된 상세 화면의 leading에 클러스터를 둬 뒤로가기 버튼과 충돌
왼쪽 도구 클러스터 + 오른쪽 단일 결정 액션
1.1.3

Leading and Trailing Clusters

양쪽 모두 여러 아이템 — 왼쪽 캡슐 하나, 오른쪽 캡슐 하나로 두 개의 독립 그룹.

어느 상황에서 사용하는가
액션이 많고 성격이 두 갈래로 나뉠 때. 예: 왼쪽=탐색/보기 관련, 오른쪽=콘텐츠 조작 관련. 도구가 많은 생산성 앱(문서·사진 편집)의 상단부.
이렇게 해야하는 이유
두 캡슐 사이의 빈 공간 자체가 정보입니다 — "이 두 묶음은 서로 다른 일"이라는 신호. 전부 한 캡슐에 붙이면 관계없는 기능이 한 덩어리로 보여 인지 부담이 커짐.
Tip
그룹당 2~3개가 적정. 그 이상이면 다음 항목(overflow)이나 bottom bar로 분산을 고려하세요.
적절한 예
① 사진 편집 — 왼쪽은 보기/비교 도구, 오른쪽은 자르기·필터 도구 ② 브라우저 상단 — 왼쪽은 뒤로/앞으로(탐색), 오른쪽은 공유·탭 전환
잘못된 예
① 관련 없는 액션 6개를 좌우 3개씩 기계적으로 배분(묶음=의미 위반) ② 같은 기능(공유)이 양쪽 캡슐에 중복 배치
양쪽에 독립된 두 클러스터 — 사이 여백이 “서로 다른 일” 신호
1.1.4

Single Bottom Item

화면 하단 툴바(.bottomBar)에 아이템 하나. 떠 있는 유리로 표시.

어느 상황에서 사용하는가
그 화면에서 가장 자주, 반복적으로 누르는 핵심 액션 하나 — 메일의 "새 메일 작성", 메모의 "새 메모". 빈도가 높을수록 아래로.
이렇게 해야하는 이유
Reachability(엄지 도달성)가 이유의 전부. 큰 화면에서 상단은 한 손으로 닿기 어렵고, 하단은 엄지의 홈 그라운드. iOS 26이 검색까지 하단으로 내린 것과 같은 논리이며, 이것이 "하단 배치가 기본 지향"이 된 배경.
Tip
탭바가 있는 화면이라면 하단 공간을 공유하므로 신중히 — 탭바(이동)와 툴바(액션)의 역할 구분을 흐리면 안 됩니다.
적절한 예
① 메일의 새 메일 작성 ② 메모의 새 메모 — 그 화면에서 가장 반복되는 액션
잘못된 예
① 한 달에 한 번 쓸 설정을 하단에 배치(빈도 기준 위반) ② 삭제 같은 파괴적 액션을 가장 누르기 쉬운 하단에 단독 배치
제목
하단(.bottomBar) — 엄지가 닿는 자리에 고빈도 액션
1.1.5

Single Principal Item

제목이 오는 정중앙 자리(.principal)에 커스텀 컨트롤을 배치. 제목을 대체.

어느 상황에서 사용하는가
그 컨트롤이 화면의 정체성 그 자체일 때 — "지도/목록" 세그먼트 컨트롤, 기간 선택기처럼 화면 전체 내용을 좌우하는 스위치. 단순 액션 버튼을 여기 두면 안 됨.
이렇게 해야하는 이유
중앙은 시선의 앵커이자 "이 화면이 무엇인가"를 말하는 자리. 제목 대신 컨트롤이 온다는 것은 "이 화면의 정체가 이 컨트롤 값에 따라 바뀐다"는 뜻. 위계상 가장 강한 자리라 남용하면 화면의 초점이 흐려짐.
Tip
principal을 쓰면 제목이 사라지므로, 화면 정체를 컨트롤이 충분히 설명하는지 먼저 확인.
적절한 예
① 지도 앱의 지도/위성/대중교통 세그먼트 ② 주식 앱의 기간 선택(1일/1주/1년) — 값이 바뀌면 화면 전체가 바뀜
잘못된 예
① 화면 정체성과 무관한 공유 버튼을 정중앙에 ② 화면 내용과 무관한 브랜드 로고를 principal에 넣고 제목을 없앰
정중앙(principal) — 제목 자리를 화면을 정의하는 컨트롤이 대체
1.1.6

Principal and Trailing Item

중앙에 핵심 컨트롤 + 오른쪽에 보조 액션 하나. 위 두 패턴의 조합.

어느 상황에서 사용하는가
화면 모드를 바꾸는 컨트롤(중앙)과, 그 모드와 무관하게 늘 필요한 액션(오른쪽 — 예: 더보기, 설정)이 동시에 필요할 때.
이렇게 해야하는 이유
두 요소의 위계가 다름을 위치로 표현 — 중앙=화면의 정의, trailing=부가 액션. 같은 줄에 있어도 별개의 유리 캡슐로 분리되어 혼동이 없음.
Tip
principal 컨트롤이 넓으면(긴 세그먼트) trailing과 공간 경쟁이 생기니 아이콘 버튼 1개 정도로 절제.
적절한 예
① 지도/목록 세그먼트 + 오른쪽 더보기(⋯) ② 캘린더 보기 전환(일/주/월) + 오른쪽 오늘 버튼
잘못된 예
① 넓은 세그먼트 5칸 + trailing 버튼 3개 — 공간 경쟁으로 잘림 ② 중앙에 액션 버튼, trailing에 화면 모드 컨트롤(위계가 뒤바뀜)
중앙 컨트롤 + 오른쪽 보조 액션 — 위계를 위치로 분리
1.1.7

Trailing Overflowing Cluster

trailing에 아이템이 폭보다 많을 때, 시스템이 나머지를 … (overflow) 메뉴로 자동으로 접는 동작.

어느 상황에서 사용하는가
액션이 4개 이상으로 많은 화면. 노출할 소수의 핵심접어도 되는 다수를 나눌 때. 드물게 쓰는 액션·파괴적 액션(삭제)은 의도적으로 overflow 안으로.
이렇게 해야하는 이유
두 원칙의 타협 — 기능은 다 제공하되(완전성), 화면은 어지럽히지 않는다(content-first). 또한 버튼을 무한정 줄여 넣으면 터치 타깃이 손가락 크기 이하로 작아지므로, 시스템이 자동으로 접어 최소 타깃 크기를 보장. "많으면 접는다"가 기본 동작인 이유.
Tip
overflow에 뭐가 들어갈지는 선언 순서/우선순위로 제어 가능. "자주 쓰는 걸 접어버리는" 상황이 안 되게 순서를 설계하세요.
iOS 27 업데이트
WWDC26에서 visibilityPriority(_:)가 추가되어, 공간이 좁아질 때 어떤 아이템을 화면에 남길지 우선순위를 직접 지정할 수 있습니다. overflow 메뉴 구성도 ToolbarOverflowMenu로 제어 가능 — "자주 쓰는 게 접히는" 문제를 API 차원에서 해결한 것.
적절한 예
① 문서 앱 — 핵심 2개(공유·편집)만 노출하고 내보내기·인쇄·버전 기록은 overflow로 ② 삭제를 의도적으로 overflow 안에 둠(오조작 방지)
잘못된 예
① 가장 자주 쓰는 저장이 선언 순서 탓에 overflow로 접힘 ② overflow를 피하려고 아이콘 7개를 우겨넣어 터치 타깃이 손가락보다 작아짐
넘치는 아이템은 ⋯ 메뉴로 자동으로 접힘
1.1.8

Custom Views in Bottom Toolbar

하단 툴바에 버튼이 아닌 임의의 SwiftUI 뷰(텍스트, 상태 표시, 진행바, 슬라이더 등)를 배치.

어느 상황에서 사용하는가
하단에 상태 정보 + 액션을 함께 보여줄 때 — Safari의 주소창, 메일의 "업데이트됨: 방금 전" + 작성 버튼, 음악 재생 컨트롤 등.
이렇게 해야하는 이유
하단 바는 단순 버튼 줄이 아니라 "현재 페이지의 콕핏"이라는 설계 관점. 자주 보는 정보와 자주 쓰는 조작을 엄지 근처 한 곳에 모으는 것 — reachability를 정보에까지 확장한 것.
Tip
커스텀 뷰도 유리 위에 올라가므로, 뷰 자체에 배경색을 깔면 유리 효과와 충돌합니다. 배경은 시스템에 맡기세요.
적절한 예
① Safari의 하단 주소창 ② 메일의 “업데이트됨: 방금 전” 상태 텍스트 + 작성 버튼
잘못된 예
① 커스텀 뷰에 불투명 배경색을 깔아 유리 위에 널판지처럼 얹힘 ② 하단 바에 광고 배너 삽입 — “콕핏” 자리의 문법 위반
제목
업데이트: 방금 전
하단 바에 상태 정보 + 액션 — 현재 페이지의 콕핏
1.1.9

Mixed Toolbar Items

leading · principal · trailing · bottom을 한 화면에서 동시에 쓰는 종합 구성.

어느 상황에서 사용하는가
기능이 많은 풀 기능 화면(편집기, 브라우저)에서 모든 위치의 역할 분담이 필요할 때 — 위: 네비게이션·확정, 중앙: 모드, 아래: 고빈도 액션.
이렇게 해야하는 이유
각 위치에 고유한 의미(위=이동/결정, 중앙=정체성, 아래=빈도)를 부여했기 때문에, 조합해도 일관된 문법으로 읽힘. 위치별 문법이 있어야 사용자가 새 앱에서도 버튼 위치를 예측 가능 — 이것이 시스템 차원에서 위치를 표준화한 이유.
Tip
모든 자리를 채우는 게 목표가 아닙니다. 각 자리의 문법에 맞는 것만 두고 나머지는 비우거나 overflow로.
적절한 예
① 브라우저 — 위: 탐색·공유, 하단: 주소창+탭 전환 ② 사진 편집기 — 위: 취소/저장, 중앙: 편집 모드, 하단: 세부 도구
잘못된 예
① “빈 자리 = 실패”라는 오해로 모든 위치에 버튼을 배분 ② 같은 액션(공유)이 상단과 하단에 중복 배치
위 · 중앙 · 아래 전 위치 조합 — 자리마다 다른 문법
1.2

Title Display Modes

제목은 "화면이 무엇인지"를 말하는 장치. 선택 기준은 계층 깊이(루트냐 상세냐) × 콘텐츠 밀도 × 제목이 컨트롤이 될 필요가 있는가.

1.2.1

Large

내비바 아래 34pt 대형 제목. 스크롤하면 작은 inline 제목으로 자동 축소.

어느 상황에서 사용하는가
루트/최상위 화면, 둘러보는 목록 화면(설정, 메일함, 라이브러리). 사용자가 "내가 어디에 있는지"를 크게 인지해야 하는 진입점.
이렇게 해야하는 이유
진입 시엔 방향감(orientation)이 콘텐츠보다 중요 → 크게. 읽기 시작하면 콘텐츠가 중요 → 스크롤 시 자동으로 접힘(minimization 원칙). "필요할 때 크고, 안 필요하면 물러난다"를 제목에 적용한 것이 이 기본 동작.
Tip
Large는 첫 화면 여백을 크게 차지하므로, 위쪽 콘텐츠가 즉시 보여야 하는 화면(채팅 등)엔 부적합.
적절한 예
① 설정 루트 화면의 큰 “설정” 제목 ② 뮤직 보관함처럼 “내가 어디에 있는지”가 중요한 최상위 목록
잘못된 예
① 3뎁스 상세 화면까지 전부 Large — 제목 크기가 위계를 말하지 못함 ② 채팅 화면에 Large — 첫 화면부터 대화가 아래로 밀림
내비바 아래 34pt 대형 제목 — 스크롤하면 작게 접힘
1.2.2

Inline Large

대형 제목의 크기감을 유지하되 내비바 안(inline 위치)에 고정. 스크롤로 밀려나지 않음. iOS 26 신규.

어느 상황에서 사용하는가
제목의 존재감은 원하지만 레이아웃이 스크롤에 따라 출렁이는 게 싫을 때. 상단 위치가 안정적으로 유지돼야 하는 화면.
이렇게 해야하는 이유
Large(존재감 있지만 동적)와 Inline(안정적이지만 존재감 약함)의 중간 지대가 비어 있었기 때문에 추가된 절충안. 특히 유리 툴바에서 제목·아이템의 상대 위치가 고정되는 것이 시각적으로 안정적.
Tip
iOS 26 신규 모드라 공식 가이드가 아직 얇습니다. 실기기에서 large/inline과 비교해보고 결정하는 걸 권장.
적절한 예
① 스크롤 출렁임 없이 존재감이 필요한 대시보드 홈 ② 유리 툴바에서 제목·버튼의 상대 위치가 고정되어야 하는 화면
잘못된 예
① 깊은 상세 화면에 Inline Large — 위계 과장 ② Large의 축소 애니메이션이 싫다는 이유만으로 전 화면에 일괄 적용
큰 제목이 내비바 안에 고정 — 스크롤에도 위치 유지
1.2.3

Inline

내비바 중앙의 17pt 작은 제목. 가장 간결한 형태.

어느 상황에서 사용하는가
상세(detail) 화면, 깊은 계층, 모달 시트, 콘텐츠가 빽빽한 화면. "루트=Large, 상세=Inline"이 기본 공식. 확신 없으면 Inline이 안전.
이렇게 해야하는 이유
상세 화면에선 사용자가 이미 맥락을 알고 들어왔으므로 제목의 역할이 작음 → 세로 공간을 아껴 콘텐츠를 한 줄이라도 더(content-first). 위계 표현이기도 함: 제목 크기가 계층 깊이를 암시.
Tip
Large 루트에서 push된 화면이 Inline이면, 크기 변화 자체가 "한 단계 들어왔다"는 내비게이션 신호가 됩니다.
적절한 예
① 메일 상세 화면 ② 모달 시트의 상단 제목 — 맥락을 이미 알고 들어온 화면
잘못된 예
① 루트 화면까지 Inline로 통일해 진입점의 방향감 상실 ② 제목이 길어 계속 잘리는데 짧게 다듬지 않고 방치
제목
중앙의 17pt 작은 제목 — 상세 화면·모달의 기본
1.2.4

Inline with 5 Toolbar Items

inline 제목 + 아이템 5개가 좁은 내비바를 나눠 쓰는 극한 케이스.

어느 상황에서 사용하는가
이건 "이렇게 쓰라"보다 "이만큼 넣으면 시스템이 어떻게 처리하는지"를 보여주는 케이스. 실제로 5개가 필요하면 제목·아이템의 공간 협상과 overflow 동작을 여기서 확인.
이렇게 해야하는 이유
시스템이 우선순위를 정해 제목을 줄이거나 아이템을 접는 자동 협상을 하도록 설계됨 — 개발자가 기기 폭마다 분기하지 않아도 되게. "깨지지 않고 우아하게 줄어든다(graceful degradation)"가 기본 동작인 이유.
Tip
상단에 5개가 필요하다는 건 대개 설계 신호입니다 — 일부를 bottom bar나 overflow로 내리는 걸 먼저 검토하세요.
적절한 예
① PDF 뷰어처럼 정말 5개 도구가 필요한 전문 화면에서 시스템의 공간 협상에 맡김 ② 좁은 기기에서 무엇이 먼저 접힐지 우선순위를 설계하고 확인
잘못된 예
① 5개 전부 노출을 강제하려고 커스텀 내비바를 직접 구현 ② 제목이 잘리는데 아이템 수를 줄이지 않고 글자만 억지로 축소
제목이깁니다
제목과 아이템 5개의 공간 협상 — 시스템이 자동 조정
1.2.5

Inline with Toolbar Title Menu

제목 옆에 표시(⌄)가 붙고, 제목을 탭하면 메뉴가 열림 (toolbarTitleMenu).

어느 상황에서 사용하는가
제목이 바꿀 수 있는 대상일 때 — 현재 폴더/계정/문서 이름이 제목이고, 탭해서 전환·이름변경·복제 같은 걸 할 때. 파일 앱·문서 편집기의 전형 패턴.
이렇게 해야하는 이유
"제목에 대한 액션"을 별도 버튼으로 만들면 제목과 버튼의 관계를 사용자가 유추해야 함. 대상 자체를 탭하게 하면 관계 설명이 필요 없음 — 직접 조작(direct manipulation) 원칙. 툴바 버튼 하나를 아끼는 효과도.
Tip
메뉴에는 "제목이 가리키는 대상"에 대한 액션만. 화면 전체 액션을 넣으면 문법이 깨집니다.
적절한 예
① 파일 앱 — 폴더 제목 탭 → 이름 변경·복제·태그 ② 메일 — 제목 탭 → 계정/메일함 전환
잘못된 예
① 제목과 무관한 앱 전역 설정 메뉴를 제목에 연결 ② 표시(⌄) 없이 탭 가능하게 만들어 아무도 발견 못 함
제목 ⌄
제목을 탭하면 메뉴가 열림 — 제목이 “바꿀 수 있는 대상”일 때
1.2.6

Custom Large Title

기본 텍스트 대신 커스텀 뷰를 대형 타이틀 자리에 — 로고, 아바타+이름, 특수 서식 등.

어느 상황에서 사용하는가
텍스트만으로 부족한 브랜드/맥락 표현이 필요할 때 — 앱 홈의 로고, 프로필 화면의 아바타+이름, 날짜 강조가 필요한 저널 등.
이렇게 해야하는 이유
제목 자리는 화면 정체성의 자리인데, 정체성이 항상 순수 텍스트인 건 아니므로 자리는 유지하되 내용물만 교체할 수 있게 열어둔 것. 스크롤 축소 등 시스템 동작은 그대로 물려받아 일관성 유지.
Tip
커스텀이어도 "제목처럼" 행동해야 합니다 — 여기에 버튼·입력 필드를 넣는 건 자리의 문법 위반.
적절한 예
① 프로필 화면 — 아바타+이름 조합 ② 저널 앱 — 날짜를 강조한 커스텀 서식
잘못된 예
① 커스텀 뷰가 스크롤 축소 동작을 구현하지 않아 다른 화면과 이질적 ② 타이틀 자리에 검색창+버튼까지 넣은 미니 대시보드(자리 남용)
대형 타이틀 자리에 로고·아바타 등 커스텀 뷰
1.3

Scroll Edge Effects

이 기능이 존재하는 근본 이유: 툴바가 반투명 유리로 콘텐츠 위에 떠 있기 때문에, 그 밑을 지나가는 콘텐츠와 겹치면 컨트롤이 안 보일 수 있음. 가장자리 효과는 가독성을 지키는 안전장치라서 기본으로 켜져 있습니다. 선택 기준은 하나 — "바 뒤로 지나갈 콘텐츠가 얼마나 복잡한가."

1.3.1

Soft

경계 없이 부드럽게 번지는(diffused) 페이드. 콘텐츠가 유리 아래로 은은하게 사라짐.

어느 상황에서 사용하는가
대부분의 일반 화면. 텍스트 목록, 카드 피드처럼 평범한 밝기·대비의 콘텐츠. 고민되면 soft(=automatic이 주로 택하는 값).
이렇게 해야하는 이유
경계선은 그 자체로 시각 요소라 UI의 존재감을 늘림. 콘텐츠가 "잘리는" 게 아니라 "스며드는" 표현이 유리라는 재질 은유와 맞고, 몰입을 덜 깨기 때문에 이것이 기본값.
Tip
soft에서 컨트롤 가독성이 부족하게 느껴지면 그때 hard로 올리는 순서로 결정하세요.
적절한 예
① 텍스트 목록·카드 피드 등 평범한 콘텐츠의 기본값으로 ② 이미지가 적은 설정류 화면
잘못된 예
① 표·그리드처럼 구획이 중요한 화면에 soft — 경계 위치가 흐림 ② 하단 입력창 위에 soft — 입력 영역의 시작점이 모호
제목
경계선 없이 콘텐츠가 부드럽게 스며드는 페이드 — 기본값
1.3.2

Hard

선명한 구분선으로 딱 잘리는 경계. 콘텐츠 영역과 바 영역이 명확히 분리.

어느 상황에서 사용하는가
영역 경계가 또렷해야 하는 UI — 하단 입력창/액세서리 위, 표·그리드처럼 구조적인 콘텐츠, "여기부터는 컨트롤"임을 분명히 해야 할 때.
이렇게 해야하는 이유
soft의 번짐은 우아하지만 경계의 위치 정보를 흐림. 구획이 중요한 화면에선 모호함이 오히려 인지 비용 → 명확한 선이 정답. "분위기냐 명료함이냐"에서 명료함을 택하는 옵션.
Tip
한 앱 안에서 화면 성격에 따라 soft/hard를 섞어도 되지만, 같은 종류의 화면끼리는 통일하세요.
적절한 예
① 채팅 입력창 위의 명확한 경계선 ② 스프레드시트·표 화면 — 구조가 또렷해야 하는 콘텐츠
잘못된 예
① 은은한 사진 피드에 hard — 몰입을 끊는 불필요한 선 ② 화면마다 soft/hard를 무원칙하게 섞어 일관성 상실
제목
선명한 구분선으로 바 영역과 콘텐츠를 분리
1.3.3

Hard with Thick Material Toolbar Background

hard 경계 + 툴바 배경을 불투명에 가까운 두꺼운 material로. 가독성 최대 구성.

어느 상황에서 사용하는가
바 뒤로 사진·영상·고대비 그래픽처럼 복잡한 콘텐츠가 지나가는 화면. soft/hard의 반투명으로는 컨트롤 글자가 묻힐 때의 최종 수단.
이렇게 해야하는 이유
Liquid Glass의 알려진 약점이 "복잡한 배경 위에서의 대비 부족". 투명함(미학)과 가독성(접근성)이 충돌할 땐 가독성이 이긴다 — 그래서 투명도를 포기하는 탈출구를 시스템이 공식 제공. 접근성 설정(투명도 감소)이 자동 적용되는 것과 같은 철학.
Tip
"예쁜데 안 읽힌다"는 리뷰가 나오면 주저 없이 이 조합으로. 미학보다 가독성이 우선입니다.
적절한 예
① 사진 그리드 위에 뜨는 툴바 — 가독성 확보의 최종 수단 ② 지도 위 컨트롤 바(복잡한 배경이 상시 지나감)
잘못된 예
① 단순한 흰 배경 목록에까지 thick — 과잉 방어로 답답함 ② 글자가 묻히는데도 “투명이 예뻐서” 유지(가독성>미학 역전)
제목
사진·영상 등 복잡한 배경 위 — 불투명에 가까운 배경으로 가독성 확보
1.3.4

Scroll Edge Effect Hidden

가장자리 효과를 완전히 끔. 콘텐츠가 아무 처리 없이 바 밑을 그대로 지나감.

어느 상황에서 사용하는가
배경이 확실히 단순·균일해서 겹쳐도 가독성 문제가 없거나, 콘텐츠가 아예 바 뒤까지 도달하지 않는 레이아웃일 때만. 예외적 선택.
이렇게 해야하는 이유
효과도 결국 시각 요소이므로, 불필요한 곳에선 빼는 게 content-first에 부합. 다만 시스템이 기본으로 켜두는 건 "꺼도 안전한 경우"보다 "켜야 안전한 경우"가 압도적으로 많기 때문 — 끄는 건 개발자가 안전을 직접 보증할 때만.
Tip
끈 상태로 다크모드·가로모드·큰 글씨 설정까지 확인하세요. 한 조건에서만 확인하고 끄면 다른 조건에서 깨지기 쉽습니다.
적절한 예
① 콘텐츠가 바 밑까지 도달하지 않는 고정 레이아웃 ② 배경이 확실히 균일한 단색 화면
잘못된 예
① 사진 피드에서 끔 — 스크롤하면 버튼 글자가 사진과 뒤섞임 ② “미니멀해 보인다”는 이유로 전 화면 일괄 비활성화
제목
효과 완전 꺼짐 — 콘텐츠가 그대로 바 밑을 통과 (단순 배경 전용)
1.4

Search

배치 기준은 검색의 지위: 이 화면에서 검색이 ① 주인공인가 ② 자주 쓰는 조연인가 ③ 가끔 쓰는 단역인가. iOS 26의 큰 변화 — 검색의 기본 위치가 상단에서 하단으로 이동(reachability).

1.4.1

Placement: Toolbar

검색 필드를 툴바에 배치 — iPhone은 하단 유리 캡슐, iPad는 상단 trailing.

어느 상황에서 사용하는가
검색을 자주 쓰는 화면의 표준 선택. iOS 26에서 새로 만들 화면이라면 사실상 1순위 후보.
이렇게 해야하는 이유
기존의 상단 검색은 한 손으로 가장 닿기 어려운 곳에 가장 자주 쓰는 기능을 둔 셈이었음. iOS 26은 이 모순을 해소 — iPhone은 엄지 근처 하단, iPad는 양손 파지 기준 자연스러운 상단 trailing으로 기기별 인체공학에 맞게 시스템이 알아서 배치.
Tip
placement를 명시하지 않은 .searchable()의 automatic도 iOS 26에선 대체로 이 위치로 갑니다.
적절한 예
① 연락처처럼 검색이 주 기능인 목록의 하단 검색 캡슐 ② iPad에서 상단 trailing 자동 배치를 그대로 수용
잘못된 예
① 검색을 거의 안 쓰는 화면에 검색 필드를 상시 노출 ② iPhone에서 커스텀으로 상단에 고정 — 엄지 도달성 무시
제목
iPhone은 하단 유리 캡슐 · iPad는 상단 trailing
1.4.2

Placement: Toolbar (w/ an item in the bottom toolbar)

하단 툴바에서 검색 필드와 다른 버튼이 공존하는 구성.

어느 상황에서 사용하는가
검색도 자주 쓰고 작성·필터 같은 액션도 자주 쓰는 화면 — 메일함(검색+새 메일), 메모(검색+새 메모)가 전형.
이렇게 해야하는 이유
고빈도 기능이 둘 이상이면 둘 다 하단에 있어야 reachability가 일관됨. 이때 DefaultToolbarItem(kind:.search)으로 검색의 자리를 명시하고 ToolbarSpacer로 분리 — 검색(입력)과 버튼(액션)은 성격이 다르므로 다른 캡슐로 보이게 하는 것.
Tip
하단에 검색+버튼 2개 이상이면 과밀입니다. 검색 + 핵심 액션 1개가 균형점.
적절한 예
① 메일함 — 검색 캡슐 + 작성 버튼을 별도 캡슐로 분리 ② 노트 목록 — 검색 + 새 노트 버튼 공존
잘못된 예
① 검색 필드와 액션 버튼을 같은 캡슐에 묶음(입력과 액션 혼합) ② 하단에 검색+버튼 3개 — 캡슐 과밀로 오탭 유발
제목
하단에서 검색 + 액션 공존 — ToolbarSpacer로 캡슐 분리
1.4.3

Placement: Navigation Bar Drawer

내비바 제목 아래 서랍에 검색바 — 전통적(iOS 25 이전) 위치. 기본은 스크롤하면 접힘.

어느 상황에서 사용하는가
검색이 보조 기능이고 "당겨서 찾는" 관습이 자연스러운 목록 화면. 기존 앱의 익숙한 동작을 유지해야 할 때.
이렇게 해야하는 이유
스크롤 시 접히는 게 기본인 이유 — 스크롤 중이라는 건 탐색이 아니라 읽는 중이라는 신호이므로, 안 쓰는 검색바에 세로 공간을 주지 않음(minimization). 필요하면 맨 위로 당겨서 다시 꺼내는 관습이 이미 학습돼 있음.
Tip
iOS 26 신규 화면이면 toolbar 배치를 먼저 고려하고, drawer는 "기존 관습 유지"가 목적일 때 선택하세요.
적절한 예
① 위에서 아래로 훑는 설정류 목록의 보조 검색 ② 구버전과의 일관성이 중요한 앱의 점진적 마이그레이션 단계
잘못된 예
① 검색이 핵심인 앱인데 스크롤하면 사라지는 서랍에 배치 ② 서랍 검색과 하단 검색을 동시에 제공(자리 중복)
제목
제목 아래 서랍 — 스크롤하면 접히는 전통 위치
1.4.4

Placement: Navigation Bar Drawer: Always

서랍 검색바를 스크롤해도 항상 표시 (displayMode: .always).

어느 상황에서 사용하는가
화면 사용 흐름에서 검색이 반복적으로 필요한 경우 — 연락처처럼 "찾기"가 주 사용 패턴이고, 스크롤 중에도 언제든 재검색할 수 있어야 할 때.
이렇게 해야하는 이유
기본값(접힘)은 공간 절약이 우선이지만, 검색 빈도가 높은 화면에선 "다시 꺼내는 비용"이 "공간 비용"보다 큼. 그 트레이드오프를 화면 성격에 따라 개발자가 뒤집을 수 있게 한 옵션.
Tip
always는 세로 공간을 상시 소모합니다. 검색 빈도가 정말 높은지 데이터로 확인 후 선택하는 걸 권장.
적절한 예
① 사전·주소록처럼 검색이 상시 필요한 화면 ② 목록이 길고 필터링 검색이 잦은 화면
잘못된 예
① 항목 10개 미만의 짧은 목록에 상시 노출 — 공간 낭비 ② always로 고정해놓고 하단 검색까지 추가(두 자리 차지)
제목
항상 표시
서랍 검색바를 스크롤해도 고정 (.always)
1.4.5

Placement: Toolbar Principal

검색 필드를 툴바 정중앙(principal)에 — 제목 자리를 검색이 차지.

어느 상황에서 사용하는가
검색이 화면의 존재 이유일 때 — 검색 전용 탭/화면, 브라우저의 주소·검색창처럼 "이 화면 = 검색"인 경우.
이렇게 해야하는 이유
principal 자리의 문법("화면의 정체성") 그대로 — 검색이 정체성이면 검색이 중앙에 온다. Single Principal Item(1.1.5)과 동일한 논리를 검색에 적용한 것.
Tip
일반 목록 화면의 검색을 여기 두면 "검색 전용 화면"처럼 읽혀 과합니다. 검색이 진짜 주인공일 때만.
적절한 예
① 웹 검색처럼 “이 화면 = 검색”인 화면 ② 지도 검색 — 제목보다 검색이 화면의 본질일 때
잘못된 예
① 일반 목록 화면의 제목을 없애고 중앙에 검색(방향감 상실) ② principal 검색 + 하단 검색을 동시 제공(중복)
제목 자리(중앙)를 검색이 차지 — “이 화면 = 검색”일 때
1.4.6

Integrating System Search Bar w/ Other Toolbar Items

시스템 검색바를 다른 툴바 아이템들과 한 툴바 체계 안에 통합 — 자리 확보·분리·축소를 조합.

어느 상황에서 사용하는가
검색과 여러 액션이 공존하되 검색이 항상 클 필요는 없는 화면. 도구 조합: DefaultToolbarItem(.search)(자리), ToolbarSpacer(분리), searchToolbarBehavior(.minimize)(평소엔 돋보기 버튼으로 축소, 탭하면 확장).
이렇게 해야하는 이유
"기능은 제공하되 평소엔 물러난다"는 minimization 원칙의 검색 버전. 검색이 조연인 화면에서 풀사이즈 검색바는 공간 낭비 — 버튼 크기로 접어두면 다른 액션에 공간을 양보하면서도 한 탭 거리 유지. overflow가 버튼에 하는 일을 검색바에 하는 것.
Tip
.minimize는 "검색을 숨기는" 게 아니라 "접는" 것 — 검색을 거의 안 쓰는 화면이라면 애초에 searchable을 빼는 게 맞습니다.
적절한 예
① 브라우저 — 검색은 minimize로 접고 탭·공유 버튼과 공존 ② 파일 앱 — 축소된 검색 + 정렬·보기 버튼 조합
잘못된 예
① 검색을 거의 안 쓰는데 minimize로라도 상시 배치(searchable 자체가 불필요) ② 축소된 돋보기 옆에 비슷한 아이콘(필터)을 붙여 혼동 유발
제목
.minimize
평소엔 돋보기 버튼으로 접힘 — 탭하면 검색바로 확장
2

Text — Text Behavior · Text Formatting

2.1

Text Behavior

텍스트는 콘텐츠 길이를 예측할 수 없다는 게 본질입니다. 다섯 케이스는 전부 "공간은 유한한데 텍스트는 가변"이라는 하나의 문제에 대한 서로 다른 답 — 자른다(limit·truncation), 줄인다(scale), 예약한다(range), 그리고 선택하게 한다(selection).

2.1.1

Line Limit

lineLimit(n) — 텍스트가 차지할 수 있는 최대 줄 수를 고정. 넘치는 내용은 잘림.

어느 상황에서 사용하는가
목록 셀·카드 미리보기처럼 레이아웃 높이가 일정해야 하는 곳. 메일 목록의 본문 2줄 미리보기, 뉴스 카드의 제목 2줄이 전형. "전문은 상세 화면에서"가 전제일 때.
이렇게 해야하는 이유
SwiftUI Text의 기본은 무제한 줄바꿈 — 콘텐츠를 자르지 않는 게 원칙이기 때문. 하지만 목록에서 셀마다 높이가 다르면 스캔 리듬이 깨지고 한 화면에 보이는 항목 수가 줄어듦 → 목록의 목적은 훑기(scan)이지 정독이 아니므로, 미리보기 맥락에선 개발자가 명시적으로 제한하는 설계.
Tip
Dynamic Type 큰 글씨 설정에서는 같은 문장도 더 많은 줄을 차지합니다. lineLimit을 정할 땐 접근성 글자 크기에서 핵심 정보가 살아남는지 확인하세요.
적절한 예
① 피드의 본문 미리보기를 lineLimit(3)으로 통일 ② 목록 셀 제목을 1줄로 고정해 행 높이 일정 유지
잘못된 예
① 주소·금액 같은 핵심 정보가 잘리는데 전체 보기 경로가 없음 ② 접근성 큰 글씨 설정에서 1줄 고정+축소가 겹쳐 사실상 판독 불가
.lineLimit(2)

주문하신 상품이 오늘 오후에 발송될 예정이며 배송 조회는 주문 내역 화면에서 언제든지 확인하실 수 있습니다.

↑ 3줄째부터는 렌더되지 않음
딱 2줄까지만 — 셀 높이가 일정해짐
2.1.2

Truncation

truncationMode(.head / .middle / .tail) — 잘릴 때 어느 부분을 …로 접을지 선택.

어느 상황에서 사용하는가
정보 가치가 어디에 있는가로 결정 — 문장·제목은 앞이 중요하니 .tail(기본), 파일 경로·긴 이름은 시작과 끝이 중요하니 .middle, 채팅의 "…에서 도착"처럼 끝이 결론이면 .head.
이렇게 해야하는 이유
기본값이 .tail인 이유 — 자연어 문장은 두괄식으로 앞에 정보가 몰리는 게 일반적이라, 앞을 보존하는 게 평균적으로 손실이 가장 적기 때문. 하지만 식별자(경로·URL·해시)는 앞이 공통 접두사라 앞만 보이면 구분이 불가능 — 그래서 모드를 열어둔 것.
Tip
잘림이 자주 일어나는 텍스트라면 truncation 모드를 고르기 전에 "애초에 이 폭·줄 수가 맞는가"를 먼저 의심하세요. 잘림은 최후의 안전장치지 레이아웃 설계 수단이 아닙니다.
적절한 예
① 파일 경로는 .middle — 시작(위치)과 끝(파일명)이 모두 정보 ② 이메일 제목은 .tail 기본값 유지 — 앞부분이 핵심
잘못된 예
① 끝자리가 구분자인 주문번호에 .tail — 정작 필요한 끝이 잘림 ② 사람 이름에 .middle — “김…수” 같은 어색한 절단
.truncationMode
.tail오늘 회의는 오후 세
.middleUsersreport_v2.pdf
.head강남역 3번 출구 앞
…의 위치가 옵션 — 정보 가치가 어디 있느냐로 선택
2.1.3

Scale to Fit

minimumScaleFactor(0.5) (+ lineLimit(1)) — 자르는 대신 글자 크기를 줄여서 공간에 맞춤.

어느 상황에서 사용하는가
전체가 보여야만 의미 있는 짧은 값 — 타이머 숫자, 금액, 온도, 버튼 라벨. "12:34:5…"처럼 잘리면 정보가 파괴되는 종류의 텍스트.
이렇게 해야하는 이유
truncation과 scale은 같은 문제의 반대 해법 — 잘라도 뜻이 통하면 자르고(문장), 잘리면 뜻이 죽으면 줄인다(값·수치). 시스템이 자동으로 정하지 않고 개발자에게 맡기는 이유는, 텍스트가 "문장"인지 "값"인지는 의미론이라 코드만으로 판단할 수 없기 때문.
Tip
scaleFactor가 0.5 밑으로 내려가야 들어간다면 축소가 아니라 설계 문제입니다 — 폭을 늘리거나 표기 자체를 줄이는(예: 1,234,000 → 1.2M) 쪽을 검토하세요. 같은 줄의 이웃 텍스트와 크기가 어긋나 보이는 부작용도 확인.
적절한 예
① 타이머·계기판의 큰 숫자 — 길이가 변해도 한 줄 유지 ② 로컬라이즈로 길이가 널뛰는 버튼 라벨의 안전장치
잘못된 예
① 본문 문단에 적용해 화면마다 글자 크기가 제각각 ② minimumScaleFactor(0.3) 같은 과도한 축소 허용 — 가독성 파괴
.minimumScaleFactor(0.5)
적용 전 — 잘려서 정보 파괴
12:34:5…
적용 후 — 줄여서 전부 표시
12:34:56
자르는 대신 글자 크기를 줄여 값 전체를 보존
2.1.4

Line Limit (Range · Reserve Space)

lineLimit(2...4) 범위 지정, lineLimit(3, reservesSpace: true) — 최대뿐 아니라 최소 줄 수·공간 예약까지 제어.

어느 상황에서 사용하는가
콘텐츠 길이가 들쭉날쭉해도 셀·카드 높이는 균일해야 할 때. 한 줄짜리 리뷰와 네 줄짜리 리뷰가 섞인 그리드에서, 짧은 텍스트에도 3줄 높이를 예약해 카드 크기를 통일하는 패턴.
이렇게 해야하는 이유
최대 제한(2.1.1)만으로는 "짧은 콘텐츠가 레이아웃을 무너뜨리는" 문제를 못 막음 — 그리드에서 카드 높이가 제각각이면 시각적 정렬이 깨짐. 텍스트가 아니라 텍스트가 차지하는 공간을 계약으로 만들어, 콘텐츠와 레이아웃을 분리한 것.
Tip
reservesSpace는 빈 공간을 상시 소모합니다. 균일함이 실제로 필요한 그리드·가로 스크롤 카드에만 쓰고, 세로 목록에서는 대개 최대 제한만으로 충분합니다.
적절한 예
① 카드 높이 통일을 위해 lineLimit(3, reservesSpace: true) ② 리뷰 미리보기를 2...4줄 범위로 — 짧아도 최소 형태 유지
잘못된 예
① 텍스트가 항상 1줄인데 3줄을 예약 — 빈 공간만 낭비 ② 범위만 지정하고 넘친 내용을 볼 “더보기” 경로를 안 만듦
lineLimit(3, reservesSpace: true)
이 카드는 리뷰가 길어서 세 줄 높이를 전부 채웠습니다. 기준 높이.
좋아요!
짧은 텍스트에도 같은 높이를 예약 — 카드 정렬 유지
2.1.5

Text Selection

textSelection(.enabled) — 읽기 전용 텍스트를 길게 눌러 선택·복사할 수 있게 허용.

어느 상황에서 사용하는가
사용자가 가져다 쓸 가치가 있는 텍스트 — 주소, 전화번호, 쿠폰·인증 코드, 오류 메시지, 인용문. "이걸 복사하고 싶을까?"에 예스면 켜기.
이렇게 해야하는 이유
기본이 비활성인 이유 — UI의 텍스트 대부분은 라벨(장치의 일부)이지 콘텐츠(데이터)가 아니기 때문. 버튼 이름이 선택되기 시작하면 롱프레스 제스처(컨텍스트 메뉴 등)와 충돌하고 화면 전체가 "문서"처럼 행동하게 됨. 선택 가능 여부 자체가 "이건 데이터다"라는 신호.
Tip
iOS에서는 부분 선택이 아니라 해당 텍스트 전체가 한 번에 복사됩니다. 코드·주소처럼 통째로 쓰는 값에 적합하고, 긴 본문의 부분 인용이 필요하면 다른 UX(공유 시트 등)를 고려하세요.
적절한 예
① 오류 코드·주문번호처럼 복사해 쓸 값에 허용 ② 약관·주소 등 참조용 텍스트에 허용
잘못된 예
① 버튼 라벨에 선택 허용 — 탭과 길게 누르기가 충돌 ② 운송장 번호에 미적용 — 사용자가 화면 보며 수기로 옮겨 적음
.textSelection(.enabled)

쿠폰 코드는 WELCOME-2026 입니다. 길게 눌러 복사하세요.

길게 누르면 전체가 선택·복사 — “이건 데이터” 신호
2.2

Text Formatting

핵심 원칙은 하나 — 데이터를 문자열로 직접 조립하지 말 것. 단위·이름·날짜·숫자는 문화권마다 표기 규칙이 다르므로, FormatStyle에 데이터를 주고 표기는 시스템에 맡기는 것이 이 API 군의 존재 이유.

2.2.1

Format Styles (Units)

Text(measurement, format: .measurement(width: .wide))Measurement 값(길이·무게·온도)을 로케일에 맞는 단위 표기로 자동 변환.

어느 상황에서 사용하는가
거리·무게·온도·속도 같은 단위 있는 수치를 보여주는 모든 곳 — 운동 거리 "5 km", 날씨 "23°C", 몸무게 기록. 특히 글로벌 출시 앱이라면 선택이 아니라 필수.
이렇게 해야하는 이유
"\(value) km" 식의 문자열 조립은 미국 사용자에게 마일 대신 킬로미터를 강요하는 국제화 버그. Measurement + FormatStyle은 값과 표기를 분리해, 같은 데이터가 로케일에 따라 "5 kilometers" / "3.1 miles" / "5킬로미터"로 렌더링됨. 단위 환산·복수형·기호 위치까지 시스템이 책임지므로 앱은 값만 소유하면 됨.
Tip
width로 밀도를 고르세요 — .wide("5 kilometers", 문장 속), .abbreviated("5 km", 목록·라벨), .narrow("5km", 좁은 공간). 시뮬레이터 로케일을 en_US로 바꿔 마일 변환까지 확인하는 게 검증 포인트.
적절한 예
① 러닝 앱의 거리 — 로케일 따라 km/mi 자동 전환 ② 날씨 온도 — °C/°F를 시스템 설정에 위임
잘못된 예
① “\(value) km” 문자열 하드코딩 — 마일 사용권 사용자에게도 km ② 단위 변환을 직접 구현해 반올림·표기 오류 발생
.measurement(width:)
ko_KR5킬로미터
en_US3.1 miles
.abbrev5 km
같은 값 하나 — 표기는 로케일이 결정
2.2.2

Name Formatting

PersonNameComponents + .name(style:) — 사람 이름을 성·이름 구성요소로 다루고 표기 순서는 시스템에 위임.

어느 상황에서 사용하는가
사용자·연락처·참여자 등 사람 이름이 화면에 나오는 모든 곳. 전체 이름, 목록의 축약 이름, 아바타 이니셜까지 이름 표기가 필요한 자리 전부.
이렇게 해야하는 이유
"이름 성"(John Appleseed) 순서 하드코딩은 한국·일본·중국·헝가리에서 틀린 표기(홍길동을 "길동 홍"으로) — 이름 순서는 데이터가 아니라 문화권 규칙이기 때문. components(givenName·familyName)로 저장하고 표기는 로케일이 결정하게 하면, 같은 데이터가 문화권마다 올바른 순서로 나옴.
Tip
style로 용도를 구분 — .long(경칭 포함), .medium(기본 전체 이름), .short(친근한 호칭), .abbreviated(이니셜 "JA" → 아바타에 최적). 이름을 firstName/lastName 문자열 두 개로 저장하고 있다면 PersonNameComponents로의 이관부터가 시작입니다.
적절한 예
① 연락처 표시 — 한국어는 성-이름, 영어는 이름-성 순서 자동 ② 이니셜 아바타에 .abbreviated 스타일 활용
잘못된 예
① “\(first) \(last)” 하드코딩 — 동아시아 이름이 역순으로 표기 ② 표시용 문자열을 정렬 키로 사용 — 성/이름 기준이 뒤죽박죽
.name(style:)
en_USJohn Appleseed
ko_KR홍길동
.abbrevJA 아바타 이니셜
성·이름 순서는 문화권 규칙 — 하드코딩 금지
3

Tab Bar — Tab Items · Tab Counts · Visibility · Search · Bottom Accessory

3.1

Tab Items

탭 아이템은 앱 최상위 구조의 라벨입니다. 선택 기준은 두 가지 — 아이콘만으로 의미가 통하는가(라벨 스타일), 사용자를 불러야 할 상태가 있는가(배지).

3.1.1

Label Style: Title & Icon

아이콘 + 한 단어 제목의 표준 탭 아이템. 선택된 탭은 틴트 컬러로 강조.

어느 상황에서 사용하는가
거의 모든 탭. 기본값이자 명확성·접근성 기준의 정답. 다른 스타일은 이 표준에서 벗어날 명확한 이유가 있을 때만.
이렇게 해야하는 이유
아이콘은 빠른 스캔용, 제목은 의미 확정용 — 아이콘만으로는 다의적입니다(하트가 좋아요인지 건강인지). 재인(recognition)이 회상(recall)보다 싸다는 원칙: 두 채널을 함께 주면 학습 없이 읽힘.
Tip
제목은 1단어 명사로(홈·보관함·설정). 동사나 문장형 라벨은 탭이 아니라 버튼의 문법입니다.
적절한 예
① 홈·검색·보관함·프로필 — 명사 한 단어 + 표준 SF Symbol ② 선택/비선택을 채움·윤곽 아이콘으로 구분
잘못된 예
① “내가 찜한 목록” 같은 긴 라벨 — 잘리거나 겹침 ② 의미가 모호한 추상 아이콘에 흔치 않은 신조어 라벨
제목
보관함설정
아이콘 + 한 단어 제목 — 탭 아이템의 표준형
3.1.2

Label Style: Icon Only

제목 없이 아이콘만으로 구성된 탭 아이템.

어느 상황에서 사용하는가
모든 탭이 보편적으로 합의된 아이콘(홈·검색·프로필)으로 구성되고, 미니멀함이 앱 정체성일 때. 사진·미디어 몰입형 앱에서 드물게 선택.
이렇게 해야하는 이유
라벨 제거는 시각적 소음을 줄이지만 인지 비용을 사용자에게 전가하는 트레이드. 시스템이 옵션으로 열어둔 건 앱 성격에 따라 균형점이 다르기 때문 — 기본 권장은 여전히 제목+아이콘.
Tip
화면 라벨이 없어도 accessibilityLabel은 필수입니다. VoiceOver 사용자에겐 그 라벨이 전부입니다.
적절한 예
① 재생·검색처럼 만국 공통으로 읽히는 아이콘일 때 ② 공간이 극도로 좁은 보조 바에서 제한적으로
잘못된 예
① 앱 고유 개념(예: “무드”, “피드백”)을 아이콘만으로 표현 ② 비슷하게 생긴 윤곽 아이콘 4개가 라벨 없이 나열 — 구분 불가
제목
아이콘만 — 의미가 보편적일 때만 허용되는 미니멀형
3.1.3

Label Style: Title & Icon with Badge Count

아이템 우상단에 빨간 숫자 배지 (.badge(3)) — 미처리 항목 개수.

어느 상황에서 사용하는가
“몇 개”가 행동을 결정할 때 — 안 읽은 메시지, 대기 중 알림. 숫자를 보고 들어갈지 말지 판단하는 종류의 정보.
이렇게 해야하는 이유
배지는 사용자를 부르는 인터럽트 장치. 빨강+숫자는 OS 전체에서 “처리 안 된 것”의 규약이라 앱이 따로 학습시킬 필요가 없음. 모든 탭에 배지를 달면 인터럽트 가치가 인플레이션 — 진짜 중요한 알림이 묻힘.
Tip
0이 되면 배지를 제거하세요(“0” 표시 금지). 배지를 확인해도 안 꺼지는 앱은 신뢰를 잃습니다.
적절한 예
① 메시지 탭의 안 읽은 개수 ② 할 일 탭의 오늘 마감 개수 — 처리하면 줄어드는 수
잘못된 예
① 처리해도 줄지 않는 상시 배지(마케팅용 “1”) — 신뢰 소모 ② 세 자리 숫자를 그대로 노출 — “99+”로 접지 않음
제목
3메일설정
아이템 위 숫자 배지 — 미처리 개수의 규약
3.1.4

Label Style: Title & Icon with Badge Text

숫자 대신 짧은 텍스트 배지 (.badge("NEW")) — 상태형 알림.

어느 상황에서 사용하는가
개수가 아니라 상태가 정보일 때 — “NEW”, “LIVE”, 세었을 때 의미가 없는 종류. 새 기능 탭 안내, 라이브 진행 표시 등.
이렇게 해야하는 이유
숫자 배지의 문법(주의를 끄는 빨간 점)을 빌리되 의미를 상태로 확장한 것. 긴 텍스트는 탭 레이아웃을 침범하므로 시스템도 짧은 문자열을 전제로 설계.
Tip
2~4자 이내로. 그리고 상시 붙어 있는 “NEW”는 더 이상 new가 아닙니다 — 조건이 끝나면 반드시 제거하세요.
적절한 예
① 새로 추가된 탭에 한시적 “NEW” ② 라이브 방송 중인 탭에 “LIVE”
잘못된 예
① “NEW”가 몇 달째 상시 부착 — 아무도 새롭다고 믿지 않음 ② “SALE 50%” 같은 긴 배지로 탭 라벨을 침범
제목
N이벤트설정
숫자 대신 짧은 텍스트 배지 — 상태를 알림
3.2

Tab Counts

탭 수는 앱의 정보 구조 그 자체입니다. 3~5개가 표준 범위 — 그보다 적으면 “탭이 맞는가”, 많으면 “구조가 맞는가”를 물어야 합니다.

3.2.1

2 Tabs

탭이 둘뿐인 최소 구조 — 하단 바 전체를 두 목적지가 나눠 씀.

어느 상황에서 사용하는가
앱의 세계가 정말 둘로 나뉠 때 — “지금 듣기 / 라이브러리”처럼 성격이 뚜렷이 다른 두 영역만 있는 앱.
이렇게 해야하는 이유
탭바는 항상 하단을 차지하는 비싼 부동산 — 개수가 적을수록 각 탭의 명확성은 최대. 다만 2개뿐이면 탭 대신 세그먼트 컨트롤로 충분한 구조일 수 있음. 시스템이 개수를 강제하지 않는 건 구조가 앱 도메인의 문제이기 때문.
Tip
두 탭의 사용 빈도가 9:1로 기울면 구조 재검토 신호 — 부탭이 아니라 설정 화면이나 시트여야 할 수도 있습니다.
적절한 예
① 팟캐스트류 — 듣기/보관함 두 세계 ② 도구형 앱 — 작업/기록처럼 대등한 두 축
잘못된 예
① 세그먼트 컨트롤로 충분한 한 화면을 억지로 두 탭으로 분리 ② 사용 빈도 9:1의 부기능을 탭으로 승격(설정·시트가 맞는 구조)
제목
듣기보관함
탭 2개 — 최소 구조, 명확성 최대
3.2.2

2 Tabs with Minimize Behavior

.tabBarMinimizeBehavior(.onScrollDown) — 아래로 스크롤하면 탭바가 작게 접힘, 위로 스크롤하면 복원.

어느 상황에서 사용하는가
콘텐츠 몰입이 중요한 피드·리더형 화면. “아래로 스크롤 = 읽는 중, 위로 = 탐색 복귀”가 성립하는 앱.
이렇게 해야하는 이유
Liquid Glass의 minimization 원칙을 탭바에 적용한 것 — 이동 장치는 이동할 때만 크면 됩니다. 스크롤 방향으로 사용자 의도를 추론하며, 사라지는 게 아니라 접히는 것이라 위치 단서는 유지됨.
Tip
탭 전환이 잦은 앱(메신저 등)에선 오히려 방해입니다. 콘텐츠 소비형 화면에만 켜세요.
iOS 27 업데이트
Apple이 방향을 일부 수정했습니다 — iOS 27 베타에선 뮤직·팟캐스트 등 자체 앱들의 스크롤 축소 동작을 제거하고 탭바를 항상 노출하는 쪽으로 회귀 중("복원에 탭 한 번을 더 쓰게 하는 건 우아한 애니메이션보다 나쁘다"는 피드백 반영). API 자체는 유지되지만, 새로 만드는 앱이라면 minimize 채택을 더 보수적으로 판단하세요.
적절한 예
① 읽기 몰입형 뉴스·아티클 피드 ② 세로 스크롤 영상 피드 — 소비 중 이동이 드묾
잘못된 예
① 탭 전환이 잦은 메신저에 적용 — 전환마다 복원 동작 필요 ② 스크롤이 거의 없는 짧은 화면에 적용 — 동작만 거슬림
제목
듣기보관함
스크롤 ↓ 시 접힘
스크롤 내리면 탭바가 작게 접힘 — 콘텐츠에 자리 양보
3.2.3

4 Tabs

3~5개 표준 범위의 전형적 구성 — 대부분의 앱이 도달하는 균형점.

어느 상황에서 사용하는가
최상위 영역이 3~5개로 정리되는 대부분의 앱. 고민 없이 쓸 수 있는 안전 범위.
이렇게 해야하는 이유
터치 타깃 크기와 인지 부하의 교차점 — 5개를 넘으면 각 타깃이 엄지 정확도 아래로 좁아지고, 최상위 개념이 많아지면 구조 자체가 안 읽힘. “모든 걸 탭으로”가 아니라 덜 중요한 건 탭 안의 화면으로 내리는 게 원칙.
Tip
4~5번째 탭이 “기타/더보기”가 되고 있다면 정보 구조를 다시 그려야 한다는 신호입니다.
적절한 예
① 홈·검색·라이브러리·프로필의 표준 4탭 ② 각 탭이 대등한 정보 구조의 목적지일 때
잘못된 예
① 남는 자리를 “더보기” 잡동사니 탭으로 채움 ② 목적지가 아닌 프로모션 전용 탭 — 광고를 구조로 위장
제목
탐색보관함설정
3~5개가 표준 구성 — 타깃 크기와 인지 부하의 균형점
3.2.4

6 Tabs

표준 범위를 넘는 6개 탭 — 시스템이 어디까지 수용하는지 보여주는 한계 케이스.

어느 상황에서 사용하는가
기능이 정말 많은 대형 앱의 예외적 선택. 이 데모는 “이렇게 쓰라”보다 “이만큼 넣으면 어떻게 되는가”를 보여주는 쪽.
이렇게 해야하는 이유
iPhone 폭에서 6개는 타깃·라벨이 모두 압박됩니다. 그래도 선언적으로 받아두는 이유 — 같은 선언이 iPadOS에선 사이드바로 적응되는 등, 기기별 재배치를 시스템이 처리할 수 있기 때문.
Tip
6개가 필요해 보이면 대개 둘은 같은 개념입니다 — 통합을 먼저, 추가는 마지막에.
적절한 예
① 정보 구조상 6개가 불가피할 때 시스템의 자동 축약을 수용 ② 공간 여유가 있는 iPad 레이아웃에서의 6탭
잘못된 예
① iPhone에서 6개 강행 — 라벨 잘림·터치 타깃 축소 ② 회사 조직도(부서별 탭)를 그대로 탭 구조로 이식
제목
탐색클립알림메일설정
6개 — iPhone에선 과밀, iPad에선 사이드바로 적응되는 한계 케이스
3.3

Visibility

기준은 화면의 주 작업 — 이동이 주 작업이면 탭바를 유지하고, 소비(읽기·보기)가 주 작업이면 물러나게 합니다.

3.3.1

Always Visible

어느 깊이로 들어가도 탭바가 항상 표시되는 기본 동작.

어느 상황에서 사용하는가
기본값. 탭 전환이 언제든 가능해야 하는 대부분의 앱 — 목록→상세 정도의 얕은 계층 구조.
이렇게 해야하는 이유
탭바는 “지금 어디에 있고 어디로 갈 수 있는지”를 보여주는 상시 지도 — 항상 보이는 것 자체가 방향 상실을 막는 안정 장치입니다. 깊이 들어가도 “나는 이 탭 안에 있다”는 컨텍스트가 유지됨.
Tip
항상 보이는 만큼 하단 툴바 액션과 공간을 경쟁합니다. 탭바가 있는 화면에선 하단 액션을 절제하세요.
적절한 예
① 대부분의 브라우징 앱 — 언제든 섹션 점프 가능 ② 커머스 — 탐색 중 장바구니·검색 탭 상시 접근
잘못된 예
① 전체화면 미디어 뷰어에서까지 유지 — 몰입 방해 ② 결제 진행 중 탭 이동을 열어둠 — 작성 내용 유실 위험
제목
탐색설정
상세로 들어가도 탭바가 항상 유지 — 상시 지도 역할
3.3.2

Hidden on Detail Views

push된 상세 화면에서 .toolbar(.hidden, for: .tabBar)로 탭바를 숨김.

어느 상황에서 사용하는가
상세가 몰입형일 때 — 사진 전체 화면, 영상 재생, 읽기 화면. 또는 작성 중 화면처럼 탭 전환이 흐름을 깨는 경우.
이렇게 해야하는 이유
목록에선 이동이 주 작업이지만 상세에선 소비가 주 작업 — 주 작업이 바뀌면 크롬도 바뀌는 것이 content-first. 탭바가 빠진 공간은 콘텐츠에 반환되고, 뒤로가기가 유일한 출구가 됩니다.
Tip
숨겼다 나타날 때 레이아웃 점프가 없는지 확인하세요. 탭바 높이에 의존하는 하단 UI가 있으면 깨집니다.
적절한 예
① 사진 전체보기·영상 재생 같은 몰입 상세 ② 결제·서명처럼 완결해야 하는 플로우
잘못된 예
① 얕은 2뎁스 설정 화면에서 숨김 — 이동성만 잃음 ② 숨겨놓고 하단에 유사 탭바를 커스텀으로 재구현(이중 구현)
제목
상세에서 숨김
상세 화면에서 탭바 자리가 콘텐츠에 반환
3.4

Search

질문은 하나 — 검색이 “하나의 목적지”인가, “별도의 모드”인가. iOS 26은 후자를 위해 search role(분리 캡슐)을 새로 제공했고, iOS 27(WWDC26)은 이 분리 캡슐 자리를 prominent role로 검색 외 탭에도 개방했습니다.

3.4.1

As Tab Item

검색을 일반 탭 중 하나로 배치 — 다른 탭과 동급의 섹션.

어느 상황에서 사용하는가
검색이 탐색과 대등한 주요 목적지일 때 — 앱스토어·미디어 앱처럼 검색 탭 안에 추천·트렌딩 등 자체 콘텐츠가 있는 경우.
이렇게 해야하는 이유
탭은 최상위 구조이므로, 검색을 탭으로 두는 것은 “검색은 우리 앱의 한 세계”라는 선언. 목록을 좁히는 필터형 검색이라면 과합니다 — 그건 화면 안의 .searchable이 맞음.
Tip
검색 탭에 빈 검색창만 있으면 자리 낭비 — 추천·최근 검색 같은 “검색 전 콘텐츠”를 채우세요.
적절한 예
① 앱스토어 — 검색 탭 안에 추천·차트 콘텐츠 ② 미디어 앱 — 검색 탭에 트렌딩·최근 검색
잘못된 예
① 검색 탭이 빈 검색창 하나뿐 — 최상위 자리 낭비 ② 목록을 좁히는 필터형 검색을 탭으로 승격(.searchable이 맞는 구조)
제목
탐색검색설정
검색이 일반 탭 중 하나 — 동급의 목적지
3.4.2

With Search Role

Tab(role: .search) — 시스템이 검색 탭을 인식해 다른 탭과 분리된 유리 캡슐(오른쪽)로 배치. iOS 26 신규.

어느 상황에서 사용하는가
iOS 26에서 검색 탭을 둘 때의 새 표준. 역할만 선언하면 위치·모양·전환 동작을 시스템이 알아서 처리.
이렇게 해야하는 이유
탭은 “장소 이동”이지만 검색은 “모드 진입” — 성격이 다른 것을 시각적으로도 분리(별도 캡슐)해 OS 전체에서 일관되게 표현한 것. 탭하면 캡슐이 그 자리에서 검색 필드로 변형되어, 화면 이동 없이 모드가 전환됩니다.
Tip
role만 선언하고 위치·모양 커스텀은 하지 마세요 — 시스템 규약에서 벗어나면 사용자의 기대가 깨집니다.
iOS 27 업데이트
iOS 27에선 Apple 자체 앱들(뮤직·팟캐스트·TV·뉴스 등)이 검색 탭을 다시 메인 탭 줄로 통합하는 방향 수정이 보도·베타에서 확인됩니다. 분리 캡슐이 "새 표준"에서 "선택지 중 하나"로 위상이 조정되는 중 — 검색이 정말 별도 모드인지(이 섹션 서두의 질문)를 더 엄격히 물은 뒤 채택하세요.
적절한 예
① 스트리밍 앱 — 검색을 별도 모드로 보고 분리 캡슐 채택 ② role만 선언하고 위치·모양·전환은 시스템에 위임
잘못된 예
① 분리 캡슐의 위치·모양을 커스텀 — 시스템 규약 이탈 ② 검색 캡슐 자리를 흉내내 작성 버튼을 배치(자리 오용)
제목
탐색보관함
search role — 검색이 분리된 캡슐(오른쪽)로 배치
3.4.3

Search Role with Minimize Behavior

search role + tabBarMinimizeBehavior 조합 — 스크롤 시 탭바는 접히고 검색 캡슐은 축소된 채 잔류.

어느 상황에서 사용하는가
콘텐츠 몰입(피드)과 검색 상시 접근이 둘 다 필요한 앱 — 브라우징 중에 “아까 그거 찾아야지”가 잦은 사용 패턴.
이렇게 해야하는 이유
접힘(탭바)과 잔류(검색)의 역할 분리 — 소비 중에는 이동이 덜 필요하지만 검색은 소비 중에 오히려 촉발되기 때문. 두 API가 직교로 설계되어 조합이 자연스럽게 성립합니다.
Tip
실기기에서 스크롤 방향 전환 시 접힘/펼침 애니메이션을 확인하세요. 스크롤이 짧은 화면에는 부적합합니다.
적절한 예
① 피드 몰입과 상시 검색이 둘 다 필요한 콘텐츠 앱 ② 긴 카탈로그를 브라우징하다 수시로 검색하는 커머스
잘못된 예
① 스크롤이 짧은 화면에 조합 적용 — 접힘/복원만 어수선 ② 검색 빈도가 낮은데 캡슐을 상주시킴 — 불필요한 상주 UI
제목
탐색보관함
스크롤 시 탭바만 접힘
탭바는 접혀도 검색은 한 탭 거리 유지
3.4.4

Prominent Role — iOS 27 신규 (WWDC26)

Tab(role: .prominent) — search role 전용이던 trailing 분리 캡슐 자리를 일반 탭에도 개방. 시스템이 해당 탭에 추가 시각 강조를 적용.

어느 상황에서 사용하는가
앱에서 특별히 강조하고 싶은 핵심 목적지가 하나 있을 때 — 장바구니, 티켓, 여행, 결제 내역처럼 “자주 가는 장소”. 검색이 아닌 탭도 분리 캡슐에 둘 수 있게 된 iOS 27의 확장.
이렇게 해야하는 이유
iOS 26에서 분리 캡슐이 검색 전용이자 “버튼처럼 생긴 자리”가 되자, 개발자들이 이 자리를 작성·업로드 버튼으로 오용하는 패턴이 퍼짐 → Apple이 “강조된 목적지”라는 공식 경로를 열어 수요를 흡수한 것. 단 prominent도 여전히 탭 — 탭의 의미(장소 이동)는 그대로이고 겉모습만 강조됩니다.
Tip
액션 버튼(작성·업로드·스캔·새로 만들기)을 여기 두면 안 됩니다. FAB(플로팅 액션 버튼)의 대용이 아님 — “탭하면 어딘가로 이동하는가?”에 예라고 답할 수 없으면 그건 탭이 아니라 액션이고, 액션의 자리는 툴바입니다.
적절한 예
① 커머스의 장바구니 탭 강조 — 자주 가는 장소 ② 여행 앱의 내 여행 탭 — 핵심 목적지 하나를 부각
잘못된 예
작성·업로드 버튼을 prominent 탭으로 위장 — 액션은 탭이 아님 ② 탭하면 이동 없이 시트만 띄우는 가짜 탭 — “어디로 가는가”에 답 못 함
제목
탐색보관함
목적지 ○ · 액션 ✕
분리 캡슐에 검색 아닌 탭(예: 장바구니) — 단, “장소”여야 함
3.5

Bottom Accessory

.tabViewBottomAccessory — 탭바 위 층에 상주하는 전역 상태 뷰(미니 플레이어 등). 뮤직 앱 패턴을 시스템 API로 표준화한 iOS 26 신규 기능입니다.

3.5.1

3 Tab Items

탭 3개 위에 액세서리 뷰가 상주하는 기본 구성 — 탭을 전환해도 액세서리는 유지.

어느 상황에서 사용하는가
어느 탭에 있든 유지되어야 하는 진행 중 상태 — 음악 재생, 통화 중, 업로드 진행, 타이머.
이렇게 해야하는 이유
탭을 넘나드는 상태는 특정 화면이 아니라 앱 전역의 소유 — 그래서 탭 콘텐츠가 아닌 탭바 계층에 붙입니다. 모두가 각자 구현하던 뮤직 앱 미니 플레이어 패턴을 시스템 API로 표준화한 것.
Tip
액세서리는 한 개, 한 줄 높이로. 배너·광고를 여기 두는 것은 자리의 문법 위반입니다.
적절한 예
① 뮤직의 미니 플레이어 ② 통화 중·녹음 중 상태 바 — 어느 탭에서든 유지
잘못된 예
① 광고 배너를 액세서리 자리에 — 자리의 문법 위반 ② 두 줄짜리 복잡한 컨트롤 패널 — 한 줄 높이 원칙 위반
제목
탐색보관함
탭바 위 층에 전역 상태(미니 플레이어 등)가 상주
3.5.2

3 Tab Items with Minimize Behavior

액세서리 + 탭바 최소화 — 스크롤하면 탭바가 접히고 액세서리가 그 자리로 내려앉음(inline 배치).

어느 상황에서 사용하는가
콘텐츠 몰입과 전역 상태 유지가 동시에 필요할 때 — 가사·목록을 스크롤하는 동안에도 재생 컨트롤은 남아야 하는 뮤직형 앱.
이렇게 해야하는 이유
핵심은 접힐 때 액세서리가 사라지지 않고 탭바 자리로 승격된다는 것 — “이동 < 상태”라는 우선순위 역전을 시스템이 자동 처리해, 개발자가 두 상태의 레이아웃을 따로 만들지 않아도 됩니다.
Tip
액세서리 뷰는 확장/인라인 두 크기에서 모두 읽혀야 합니다 — tabViewBottomAccessoryPlacement 환경 값으로 분기하세요.
적절한 예
① 가사를 스크롤하는 동안에도 재생 컨트롤 유지 ② 에피소드 목록 탐색 중 재생바 유지
잘못된 예
① inline 크기 대응 없이 확장 레이아웃 그대로 — 접히면 잘림 ② 액세서리에 탭 전환 버튼을 넣음 — 이동과 상태의 역할 혼동
제목
탐색보관함
접히면 탭바 자리로 ↓
탭바가 접히면 액세서리가 그 자리로 내려앉음(inline)
3.5.3

Tab Items with Search Role and Minimize Behavior

탭 + search role + 액세서리 + 최소화 — 하단 시스템의 풀 구성.

어느 상황에서 사용하는가
미디어·콘텐츠 대형 앱에서 하단에 이동(탭)·검색·전역 상태(액세서리)를 모두 담아야 할 때.
이렇게 해야하는 이유
하단이라는 한 자리를 세 시스템이 나눠 쓰려면 각자의 규약이 필요 — 탭=왼쪽 묶음, 검색=오른쪽 분리 캡슐, 액세서리=위 층. 전부 시스템 관할이라 조합해도 충돌하지 않고, 앱이 좌표를 계산할 일이 없습니다.
Tip
풀 구성은 하단이 무겁습니다. 콘텐츠가 눌리는 느낌이면 최소화 동작을 켜서 소비 중엔 물러나게 하세요.
적절한 예
① 스트리밍 풀 구성 — 탭 + 검색 캡슐 + 미니 플레이어 + minimize ② 오디오북 앱의 동일 구성 — 각 요소가 자기 역할만 수행
잘못된 예
① 요소를 다 켜고 위계 설계는 없음 — 하단 과밀 ② 작은 화면(SE급)에서 겹침·잘림 검증 없이 풀 구성 강행
제목
탐색
액세서리
탭 + 검색 + 액세서리 — 하단 시스템의 풀 구성
4

Sheets — Configurations · Full Screen Cover · Transitions

4.1

Configurations

시트의 핵심 변수는 detent(멈춤 높이)모달성 — 화면을 얼마나 차지할지, 그리고 뒤 콘텐츠와의 관계(차단 vs 병행)를 어떻게 설정할지가 다섯 케이스의 전부입니다.

4.1.1

Presentation Detent: Large

.presentationDetents([.large]) — 화면을 거의 다 덮는 기본 시트. 뒤 화면이 살짝 물러나 보임.

어느 상황에서 사용하는가
독립된 작업 흐름 — 새 항목 작성, 프로필 편집처럼 배경 컨텍스트를 참조할 필요가 없는 작업. 시트의 기본값이자 가장 흔한 형태.
이렇게 해야하는 이유
시트는 “임시 컨텍스트 전환”의 장치 — large는 사실상 새 화면이지만, 뒤가 살짝 보이는 스택 은유로 “끝나면 원래 화면으로 돌아간다”는 감각을 유지합니다. 영구 이동인 push와 구분되는 이유가 이 은유.
Tip
작성 중 데이터가 있는 시트라면 아래로 스와이프 닫기로 인한 손실 주의 — interactiveDismissDisabled + 확인 다이얼로그를 고려하세요.
적절한 예
① 새 이벤트 작성처럼 입력이 많은 폼 시트 ② 여러 섹션을 스크롤하는 편집 화면
잘못된 예
① 항목 2개짜리 선택지에 전체 높이 시트 ② 뒤 화면을 참조하며 해야 하는 작업을 전부 덮어버림
제목
화면을 거의 덮는 기본(large) 시트 — 뒤가 살짝 보임
4.1.2

Presentation Detent: Medium

.presentationDetents([.medium]) — 화면 절반 높이에서 멈추는 시트.

어느 상황에서 사용하는가
배경을 보면서 하는 보조 작업 — 지도 위 검색 결과, 필터 패널, 공유 옵션. 원본과 시트를 번갈아 봐야 하는 작업.
이렇게 해야하는 이유
절반 높이는 “원본과의 대화” 은유 — 화면을 나눠 가짐으로써 시트가 배경 콘텐츠에 대한 것임을 형태로 말합니다. 지도 앱이 만든 패턴을 시스템 detent로 표준화한 것.
Tip
medium 시트에서 키보드가 올라오면 시스템이 large로 밀어올립니다 — 입력이 중심인 시트라면 처음부터 large가 자연스럽습니다.
적절한 예
① 지도 위 장소 정보 — 뒤 지도를 보며 확인 ② 절반 높이로 충분한 옵션·공유류 시트
잘못된 예
① 긴 폼을 medium에 우겨넣어 시트 안 이중 스크롤 ② medium인데 뒤를 딤으로 가림 — 반높이를 쓴 이유가 소멸
제목
절반 높이(medium) — 배경을 참조하며 하는 보조 작업
4.1.3

Presentation Detent: Custom

.height(250) · .fraction(0.3) — 시스템 2단이 아닌 커스텀 높이의 detent.

어느 상황에서 사용하는가
콘텐츠에 고유한 높이가 있을 때 — 버튼 몇 개짜리 액션 패널, 재생 컨트롤 등 medium도 과한 작은 UI.
이렇게 해야하는 이유
시트 높이는 콘텐츠가 결정해야 합니다 — medium에 작은 콘텐츠를 넣으면 잉여 공백이 “뭔가 더 있나?”라는 오독을 만듭니다. 다만 자유 높이는 일관성을 해치므로, detent 시스템 안에서 커스텀을 허용하는 절충 설계.
Tip
고정 px보다 .fraction이나 콘텐츠 크기 기반이 안전합니다 — Dynamic Type 큰 글씨에서 내용이 잘리는지 꼭 확인하세요.
적절한 예
① 재생 대기열 패널 .height(250) ② 필터 패널 .fraction(0.3) — 내용에 맞는 최소 높이
잘못된 예
① 기기별 검증 없는 고정 px — 작은 화면에서 넘침 ② 시스템 2단으로 충분한데 픽셀 미세조정에 집착
제목
콘텐츠 고유 높이에 맞춘 커스텀 detent
4.1.4

Presentation Detent: Combo

[.medium, .large] — detent를 여러 개 선언하고 사용자가 끌어서 단계 전환.

어느 상황에서 사용하는가
훑어보기 → 집중의 두 모드가 다 필요한 콘텐츠 — 지도 검색 결과(반쯤 보다가 끌어올려 전체 목록), 상세 정보 패널.
이렇게 해야하는 이유
“지금 얼마나 보고 싶은지”는 시스템이 판단할 수 없는 사용자의 의도 — 그래서 높이 선택권 자체를 사용자에게 넘긴 것. 끌어올리는 제스처가 곧 의도 표현이고, 그랩바는 “단계가 더 있다”는 어포던스입니다.
Tip
detent가 여럿인데 그랩바가 안 보이면 발견이 불가능합니다 — presentationDragIndicator(.visible)로 명시하세요.
적절한 예
① 지도 검색 결과 — medium으로 훑고 끌어올려 large 상세 ② 미리보기 → 확장 편집의 단계 전환
잘못된 예
① 확장 가능하다는 시각 단서(grabber)를 숨김 — 발견 불가 ② 단계마다 레이아웃이 확 바뀜 — 연속성 상실
제목
↑ 끌어올리면 large
medium ↔ large 단계 전환 — 그랩바가 “더 있다”는 신호
4.1.5

Nonmodal Sheet

.presentationBackgroundInteraction(.enabled(upThrough: .medium)) — 시트가 떠 있는 동안에도 뒤 콘텐츠를 조작 가능. 딤이 없음.

어느 상황에서 사용하는가
시트가 도구 팔레트 역할일 때 — 지도를 계속 움직이면서 결과 시트 유지, 본문을 스크롤하면서 서식 패널 사용.
이렇게 해야하는 이유
모달의 본질은 “응답을 요구하고 나머지를 차단” — 하지만 도구 패널은 응답이 아니라 병행 작업입니다. 시트의 형태(하단 패널)만 빌리고 모달성은 제거한 것. 딤이 없는 것이 “뒤를 만져도 된다”는 시각 신호.
Tip
딤이 없어 사용자가 시트의 존재를 잊기 쉽습니다 — 명시적 닫기 버튼을 두고, 시트가 가리는 영역에 핵심 콘텐츠가 없는지 확인하세요.
적절한 예
① 지도를 조작하면서 장소 시트를 동시에 유지 ② 이퀄라이저를 조절하며 뒤 재생 화면 계속 조작
잘못된 예
① 확정이 필요한 결제 시트를 nonmodal로 — 뒤를 조작해 상태 불일치 ② 뒤 조작이 가능한데 딤을 깔아 모달처럼 보이게(신호 모순)
제목
뒤 화면 조작 가능
딤(어두운 배경) 없음 — 시트 뒤 콘텐츠와 병행 작업
4.2

Full Screen Cover

시트의 형제지만 성격은 반대 — 뒤를 완전히 가리고, 스와이프로 닫을 수 없는 강한 모달입니다. 선택 기준은 “실수로 이탈하면 안 되는 흐름인가”.

4.2.1

General Behavior

.fullScreenCover화면 전체를 덮으며, 아래로 스와이프해도 닫히지 않음.

어느 상황에서 사용하는가
완료 또는 명시적 취소가 필요한 흐름 — 온보딩, 로그인, 카메라·전체 화면 미디어, 운동 세션처럼 실수 이탈로 깨지면 안 되는 몰입 화면.
이렇게 해야하는 이유
시트와 달리 뒤가 전혀 안 보이고 제스처 닫기도 없음 — “이 작업을 끝내거나, 명시적으로 나가라”는 강한 모달성입니다. 가벼운 시트와 무거운 커버를 시스템이 굳이 별도 API로 분리한 건, 이 무게 차이가 사용자 기대의 문제이기 때문.
Tip
스와이프가 안 되므로 완료/취소 버튼이 유일한 출구 — 닫기 수단을 빼먹으면 사용자가 갇힙니다. 반드시 확인하세요.
적절한 예
① 온보딩·로그인처럼 완료 전 이탈이 없어야 하는 플로우 ② 영상 전체 재생 — 화면 전부가 콘텐츠
잘못된 예
① 간단한 확인 팝업을 전체 화면으로 덮음 — 과잉 ② 닫기 버튼 없는 cover — 스와이프도 안 되니 탈출구가 없음
제목
스와이프 닫기 없음
화면 전체를 덮는 강한 모달 — 출구는 명시적 버튼뿐
4.3

Transitions

전환은 “이 화면이 어디서 왔는가”에 대한 답입니다 — 출처가 의미 없으면 standard(아래에서), 탭한 요소가 곧 열리는 내용이면 zoom(그 자리에서 확대).

4.3.1

Standard

아래에서 위로 올라오는 기본 전환 — 모든 시트의 디폴트.

어느 상황에서 사용하는가
대부분의 시트. “+” 버튼으로 여는 작성 화면처럼, 시트 내용이 화면의 특정 요소와 대응하지 않을 때.
이렇게 해야하는 이유
아래에서 올라오는 모션은 “임시 레이어가 위에 쌓인다”는 공간 은유 — OS 전역에서 동일해서 사용자가 “아래로 내리면 닫힌다”를 즉시 예측합니다. 예측 가능성이 곧 이 전환의 가치.
Tip
커스텀 전환을 고민하기 전에 — 출처가 의미 없는 시트라면 standard 그대로가 정답인 경우가 대부분입니다.
iOS 27 업데이트
.navigationTransition(.crossFade) 추가 — zoom과 달리 source view 지정 없이 쓸 수 있는 교차 페이드 전환. "출처는 의미 없지만 standard의 슬라이드 모션이 과한" 화면을 위한 중간 선택지입니다.
적절한 예
① “+” 버튼으로 여는 작성 시트 ② 설정에서 여는 편집 폼 — 출처가 의미 없는 시트
잘못된 예
① 카드를 탭해 여는 상세인데 standard — 출처 정보를 버림(zoom이 정답) ② 시트마다 커스텀 슬라이드 방향을 달리함 — 예측 가능성 파괴
제목
아래에서 올라오는 표준 전환 — 어디서 열든 동일
4.3.2

Zoom – Sheet

.navigationTransition(.zoom(sourceID:in:))탭한 요소에서 시트가 확대되어 나오는 전환.

어느 상황에서 사용하는가
시트 내용이 탭한 요소의 확장일 때 — 카드를 탭해 그 카드의 상세 시트가 열리는 구조.
이렇게 해야하는 이유
눌렀던 것과 열린 것이 같은 것임을 모션으로 증명하는 장치 — 공간적 연속성이 유지되어 “어디서 왔는지”를 설명할 필요가 없습니다. standard는 출처 정보를 버리므로, 출처가 의미 있으면 zoom이 정답.
Tip
sourceID와 namespace 매칭이 어긋나면 standard로 조용히 폴백됩니다 — 실기기에서 확대 출발점이 맞는지 확인하세요. 출처 없는 시트(작성 버튼)에는 부적합.
적절한 예
① 카드 탭 → 그 카드의 상세 시트로 확대 ② 썸네일 탭 → 미리보기 시트
잘못된 예
① 출처가 무의미한 작성 버튼에 zoom ② sourceID/namespace 불일치를 방치 — 조용히 standard로 폴백된 채 배포
제목
여기서 확대 ⤢
탭한 카드가 시트로 확대(zoom) — 공간적 연속성
4.3.3

Zoom – Full Screen Cover

zoom 전환을 full screen cover에 적용 — 썸네일이 화면 전체로 확대.

어느 상황에서 사용하는가
사진·영상 썸네일 → 전체 화면 뷰어처럼, 작은 요소가 화면 전체를 차지하는 콘텐츠로 확장될 때.
이렇게 해야하는 이유
사진 앱이 표준화한 패턴 — 확대로 열리고 닫을 때 원래 자리로 축소되어 공간 모델이 왕복 내내 유지됩니다. zoom을 쓰면 풀스크린인데도 아래로 끌어내리는 닫기 제스처가 자연스럽게 연동되는 것도 이 연속성 덕분.
Tip
닫기 축소의 목적지(원래 셀)가 스크롤로 화면 밖에 있을 때의 동작을 확인하세요 — 목적지를 잃은 축소는 어색합니다.
적절한 예
① 사진 썸네일 → 전체화면 뷰어 ② 지도 카드 → 전체 지도 화면
잘못된 예
① 시각적 대응물이 없는 텍스트 행에서 전체화면 zoom ② 닫을 때 원래 위치로 돌아가지 않는 커스텀 구현 — 공간 은유 붕괴
제목
썸네일 → 전체 화면 ⤢
요소가 화면 전체로 확대 — 사진 뷰어 패턴
5

Safe Area Bar — Vertical · Horizontal

5.1

Vertical Safe Area Bars

.safeAreaBar(edge:) — 커스텀 뷰를 “바”로 승격시키는 iOS 26 API. 시스템 바처럼 콘텐츠를 자동으로 인셋시키고 스크롤 가장자리 효과에 참여합니다. overlay(가림)와 safeAreaInset(인셋만)의 상위 호환.

5.1.1

Top

.safeAreaBar(edge: .top) — 커스텀 뷰를 상단 safe area에 배치. 스크롤 콘텐츠는 자동으로 그 아래부터 시작.

어느 상황에서 사용하는가
시스템 내비바로는 안 되는 상단 상시 UI — 필터 칩 줄, 동기화 상태 배너, 커스텀 헤더처럼 콘텐츠 위에 늘 떠 있어야 하는 것.
이렇게 해야하는 이유
overlay는 콘텐츠를 가리고, safeAreaInset은 밀어내기만 하고 가장자리 효과가 없음 — safeAreaBar는 인셋 + 스크롤 가장자리 효과까지, 시스템 바의 인프라 전체를 커스텀 뷰에 개방한 것입니다. 커스텀 UI도 시스템과 같은 문법으로 행동해야 화면이 하나의 시스템으로 읽히기 때문.
Tip
첫 번째 콘텐츠가 바에 가려지지 않는지(자동 인셋), 스크롤 시 콘텐츠가 바 밑으로 지나갈 때의 가독성을 확인하세요.
적절한 예
① 필터 칩 줄을 상단 바로 — 콘텐츠가 자동으로 그 아래부터 ② 동기화 상태·오프라인 배너
잘못된 예
① safeAreaBar 대신 ZStack으로 얹어 콘텐츠 첫 줄이 가려짐 ② 상단 바가 과하게 높아 콘텐츠 영역 잠식
상단 safe area에 커스텀 바 — 콘텐츠는 자동으로 아래로 밀림
5.1.2

Top with Title

상단 safe area bar 안에 타이틀 텍스트를 넣은 커스텀 헤더 구성.

어느 상황에서 사용하는가
시스템 내비게이션 바를 쓰지 않는 화면에서 자체 헤더가 필요할 때 — 브랜드 디자인이 강한 앱, 특수 레이아웃의 홈 화면.
이렇게 해야하는 이유
시스템 내비바를 버리면 제목 배치·인셋·가장자리 효과를 전부 직접 구현해야 했습니다 — safeAreaBar는 그 인프라(인셋+효과)는 시스템이 대고, 내용만 앱이 채우는 절충안. 완전 커스텀과 시스템 동작 사이의 중간 지대.
Tip
시스템 내비바의 공짜 기능(스크롤 시 제목 축소, Dynamic Type 대응)은 따라오지 않습니다 — 큰 글씨 설정에서 헤더가 깨지는지 직접 확인하세요.
적절한 예
① 내비바를 쓸 수 없는 커스텀 레이아웃의 제목 표시 ② 브랜드 헤더가 필요한 홈 화면
잘못된 예
① 시스템 내비바와 커스텀 타이틀 바를 동시에 — 이중 헤더 ② 커스텀 헤더가 Dynamic Type을 무시 — 큰 글씨에서 깨짐
제목
상단 바 안에 타이틀 — 시스템 내비바 없는 커스텀 헤더
5.1.3

Bottom

.safeAreaBar(edge: .bottom)하단 safe area에 커스텀 바. 콘텐츠 끝이 바 위까지 자동 인셋.

어느 상황에서 사용하는가
탭바·툴바가 아닌 커스텀 하단 UI — 재생 컨트롤 바, CTA 버튼 띠, 입력 액세서리처럼 화면 고유의 하단 장치.
이렇게 해야하는 이유
하단은 홈 인디케이터와 겹치는 위험 지역 — safe area 계산을 시스템에 맡기면 기기별(인디케이터 유무·높이) 분기가 사라집니다. 자주 쓰는 컨트롤을 엄지 근처에 두는 reachability 방향과도 일치.
Tip
키보드가 올라올 때 바의 거취를 확인하세요 — 입력과 함께 쓰는 바라면 키보드 위로 따라 올라가야 자연스럽습니다.
적절한 예
① 재생 컨트롤 바 ② 장바구니 합계 + 결제 버튼 바 — 콘텐츠 끝이 자동 인셋
잘못된 예
① 자동 인셋을 못 믿고 수동 패딩을 중복 — 이중 여백 ② 홈 인디케이터 영역을 침범하는 커스텀 배치
제목
하단 safe area에 커스텀 바 — 홈 인디케이터 회피는 시스템 몫
5.1.4

Bottom, Hard Scroll Edge Effect, with Toolbar Items

하단 커스텀 바 + hard 가장자리 효과 + 시스템 툴바 아이템이 공존하는 구성.

어느 상황에서 사용하는가
커스텀 바와 시스템 툴바 아이템이 하단에 함께 있고, 콘텐츠와의 경계가 또렷해야 하는 구조적 화면(표·입력 폼 위).
이렇게 해야하는 이유
핵심은 커스텀 바도 시스템 바와 같은 가장자리 효과 문법을 따른다는 것 — scrollEdgeEffectStyle이 safeAreaBar에도 적용되므로, 시스템 툴바와 커스텀 바가 하나의 하단 시스템으로 읽힙니다. hard를 고르는 기준은 1.3.2와 동일: 분위기보다 명료함.
Tip
툴바 아이템 + 커스텀 바로 하단이 두 층이 되면 무겁습니다 — 한 층으로 합칠 수 있는지 먼저 검토하세요.
적절한 예
① 입력창(hard로 경계 명확) + 시스템 툴바 버튼 공존 ② 결제 바 + 도움말 버튼 — 커스텀과 시스템의 역할 분담
잘못된 예
① 경계가 중요한 입력창 위에 soft 유지 — 시작점 모호 ② 커스텀 바와 시스템 아이템의 겹침(z-순서)을 방치
제목
하단 커스텀 바 + 툴바 아이템 — hard 구분선으로 경계 명시
5.1.5

Top & Bottom, Soft Scroll Edge Effect, with Toolbar Items

상·하단 동시에 safe area bar + soft 효과 + 툴바 아이템 — 수직 방향 풀 구성.

어느 상황에서 사용하는가
위에는 필터·상태, 아래에는 컨트롤이 동시에 상주해야 하는 대시보드·플레이어형 화면.
이렇게 해야하는 이유
위아래가 같은 효과(soft)로 통일되어야 콘텐츠가 “두 유리 사이를 지나는 하나의 면”으로 읽힙니다 — 위는 soft인데 아래만 hard면 화면의 재질 은유가 깨짐. 인셋이 양 끝에서 자동 적용되어 스크롤 처음과 끝에서 콘텐츠가 가려지지 않는 것도 이 API의 몫.
Tip
상단 바 + 하단 바 + 툴바까지 겹치면 콘텐츠 영역이 급격히 줄어듭니다 — 작은 기기에서 실제 가시 영역을 확인하세요.
적절한 예
① 위 필터 바 + 아래 액션 바를 둔 커머스 목록 ② 위 상태 배너 + 아래 재생 바 — 방향별 역할 분리
잘못된 예
① 상하 바 합계가 화면의 40%를 점유 — 콘텐츠 압사 ② 두 바의 재질·가장자리 효과가 제각각 — soft/hard 무원칙 혼용
상·하단 동시 — 양쪽 모두 soft 페이드로 통일
5.2

Horizontal Safe Area Bars

safe area는 상하에만 있는 게 아닙니다 — 좌우 가장자리(가로 모드의 노치·베젤)에도 같은 문법이 적용됩니다. edge만 바뀌고 개념(인셋 + 효과)은 동일.

5.2.1

Leading, Top Alignment, with Material

.safeAreaBar(edge: .leading, alignment: .top) + material 배경 — 왼쪽 가장자리 위쪽에 세로 바.

어느 상황에서 사용하는가
가로 화면·iPad에서 세로 도구 막대가 필요할 때 — 그리기 앱의 도구 팔레트, 세로 탭 스트립, 문서 뷰어의 페이지 도구.
이렇게 해야하는 이유
수직 바와 같은 API를 방향만 바꿔 일반화한 설계 — 개발자가 좌우 safe area(가로 모드 노치)를 따로 계산하지 않아도 됩니다. material 배경은 콘텐츠가 옆을 스쳐 지나갈 때의 가독성 장치로, 상단 바의 가장자리 효과와 같은 역할.
Tip
leading은 RTL 로케일에서 오른쪽이 됩니다 — 물리적 왼쪽이 필요한 도구(왼손 파지 배려 등)라면 의도를 재확인하세요.
적절한 예
① iPad 그리기 앱의 세로 도구 팔레트 ② 영상 편집의 좌측 도구 바 — 가로 공간이 넓은 기기
잘못된 예
① iPhone 좁은 폭에 세로 바 — 콘텐츠 폭 잠식 ② material 없이 불투명 단색 — 뒤 콘텐츠 흐름이 뚝 끊김
왼쪽(leading) 가장자리, 위 정렬 — 세로 도구 팔레트
5.2.2

Trailing, Center Alignment

.safeAreaBar(edge: .trailing, alignment: .center)오른쪽 가장자리 정중앙에 배치.

어느 상황에서 사용하는가
세로로 긴 제스처 컨트롤 — 줌 슬라이더, 인덱스 바, 타임라인 스크러버처럼 위아래로 쓸어올리며 조작하는 것.
이렇게 해야하는 이유
center 정렬의 근거는 엄지의 호(arc) — 오른손 파지 시 화면 오른쪽 중앙이 세로 슬라이드 제스처의 자연 위치입니다. 정렬 옵션이 존재하는 이유: 세로 바의 용도가 위(도구 선택)와 중앙(연속 제스처)에서 다르기 때문에, 위치로 용도를 구분하는 것.
Tip
오른쪽 가장자리는 스크롤 인디케이터의 자리이기도 합니다 — 스크롤 뷰 위에 얹을 땐 간섭하지 않는지 확인하세요.
적절한 예
① 연락처식 스크롤 인덱스(ㄱ~ㅎ) 바 ② 지도 우측의 확대/축소·현위치 버튼 묶음
잘못된 예
① 오른손 엄지에 가려지는 위치에 핵심 버튼 배치 ② 좌우 가장자리 바를 동시에 사용 — 양쪽 모두 잠식
오른쪽(trailing) 가장자리, 중앙 정렬 — 엄지 호에 맞는 세로 컨트롤
6

System Materials — Materials · Vibrancy

6.1

Materials

material은 색이 아니라 배경과의 관계입니다 — 뒤를 블러·채도 조정으로 비추는 반투명 레이어라서, 같은 material도 배경에 따라 표정이 달라집니다. 이 데모가 “여러 배경 위”를 보여주는 이유.

6.1.1

Materials in Different Backgrounds

.ultraThinMaterial ~ .thickMaterial — 뒤 배경을 비추는 두께가 다른 반투명 레이어. 밝은 배경, 사진, 다크모드 어디서든 자동 적응.

어느 상황에서 사용하는가
콘텐츠 위에 떠 있는 레이어(바·카드·패널)의 배경이 필요한 모든 곳. 두께 선택 기준은 하나 — 뒤로 지나갈 콘텐츠가 복잡할수록 두껍게(1.3.3의 가독성 논리와 동일).
이렇게 해야하는 이유
고정 색 배경은 배경과 단절된 “스티커”처럼 보입니다 — material은 뒤를 비춤으로써 “이 레이어는 콘텐츠 위에 떠 있다”는 깊이 관계를 형태로 표현합니다. 라이트/다크·배경 밝기에 맞춰 시스템이 자동 보정하므로, 개발자가 배경별 색을 계산하지 않아도 대비가 유지됨 — material이 “색”이 아니라 “재질”인 이유.
Tip
material에 색을 얹어 커스텀하지 말고 두께로만 고르세요. 그 위의 텍스트·아이콘은 다음 항목(vibrancy)과 세트로 써야 완성됩니다.
적절한 예
① 사진 위 컨트롤 배경에 .thinMaterial — 배경이 비쳐도 판 유지 ② 라이트/다크 적응을 시스템에 위임하고 색을 하드코딩하지 않음
잘못된 예
① 스크린샷 기준으로 rgba 반투명색을 하드코딩 — 다른 배경·다크모드에서 깨짐 ② material 위에 또 material을 중첩 — 뿌옇게 겹쳐 탁해짐
ultraThin — 배경이 많이 비침
regular — 균형
thick — 거의 불투명
같은 material, 다른 두께 — 뒤가 복잡할수록 두껍게
6.2

Vibrancy

material이 “유리”라면 vibrancy는 유리에 새기는 법 — material 위의 콘텐츠가 배경색을 끌어와 렌더링되어, 분리되지 않고 또렷해집니다.

6.2.1

Vibrancy

material 위의 텍스트·심볼이 배경색을 혼합해 렌더링되는 효과 — .foregroundStyle(.secondary) 같은 시맨틱 스타일이 material 위에서 자동으로 vibrant해짐.

어느 상황에서 사용하는가
material 배경 위에 올라가는 모든 텍스트와 아이콘 — 특히 보조 정보(secondary·tertiary). 유리 바 안의 라벨, 카드 위의 캡션.
이렇게 해야하는 이유
material 위에 불투명 고정 회색을 얹으면 배경과 단절되어 탁해집니다 — vibrancy는 뒤 색을 섞어 “유리에 새겨진” 통합감과 가독 대비를 동시에 확보합니다. primary/secondary/tertiary 계층이 vibrancy 강도와 연결되어, 색이 아니라 위계로 정보를 구분하는 시스템 철학의 텍스트 버전.
Tip
material 위에서는 커스텀 고정색 대신 시맨틱 스타일(.primary/.secondary)을 쓰세요 — vibrancy가 자동 적용됩니다. 고정 hex를 쓰는 순간 이 효과를 전부 잃습니다.
적절한 예
① material 위 보조 텍스트에 .secondary — 자동으로 배경과 조화 ② SF Symbol에 시맨틱 스타일 적용 — 어떤 배경에서도 판독 유지
잘못된 예
① material 위에 고정 회색 hex — 배경과 섞이지 않아 탁하고 죽은 색 ② 본문 긴 문단까지 vibrant 처리 — 읽기 피로 증가
vibrant — 배경과 섞여 또렷vibrant secondary — 위계 표현고정 회색 — 탁하고 분리됨
material 위 텍스트 — vibrancy가 배경색을 끌어와 대비와 통합감을 동시에
7

Menu — Menu Configurations

7.1

Menu

메뉴는 “요청할 때만 나타나는 UI”의 대표 장치입니다 — 평소엔 버튼 하나의 존재감, 탭하면 전체 선택지. minimization 원칙이 액션 목록에 적용된 형태입니다.

7.1.1

Menu Configurations

Menu — 버튼을 탭하면 열리는 액션 목록. 아이콘·섹션(Divider)·서브메뉴·role(.destructive)·Toggle/Picker 포함까지 조합 가능.

어느 상황에서 사용하는가
한 컨트롤에 여러 관련 액션을 접을 때 — 더보기(⋯) 버튼, 정렬·필터 옵션, 항목별 액션. 화면에 버튼을 늘어놓기엔 많고, 시트를 열기엔 가벼운 중간 지대. 툴바 overflow(1.1.7)가 자동으로 만드는 것도 결국 이 메뉴.
이렇게 해야하는 이유
배치 규약이 시스템 전역에서 동일해 학습이 필요 없는 것이 메뉴의 가치 — 자주 쓰는 항목은 버튼 가까운 쪽(열리는 방향에 따라 위/아래), 관련 항목은 섹션으로 묶고, 파괴적 액션은 Divider로 분리해 빨간색. 아이콘을 곁들이는 이유는 텍스트보다 스캔이 빠르기 때문 — 메뉴는 정독이 아니라 훑는 UI입니다.
Tip
서브메뉴는 1단까지만 — 2단부터는 발견 불가능해집니다. 항목이 8개를 넘으면 메뉴가 아니라 구조 문제: 섹션을 나누거나 일부를 시트·화면으로 승격하세요.
적절한 예
① ⋯ 메뉴 — 관련 액션끼리 섹션을 나누고, 삭제는 맨 아래 분리 + 빨강 ② 정렬 기준을 Picker로 넣어 현재 값에 체크 표시
잘못된 예
① 삭제를 일반 항목들 사이에 섞어 배치 — 오탭 사고 ② 메뉴 안에 서브메뉴 3단 중첩 — 사용자가 길을 잃음
참고 자료
⋯ 버튼에서 열리는 액션 목록 — 섹션 구분, 서브메뉴(›), 파괴적 액션은 분리 + 빨강
8

디자인 원칙 & 기준 — 잘된 예 · 나쁜 예로 검증하기

8.1

원칙별 기준과 사례

1~7장 68개 항목의 적절한 예·잘못된 예를 관통하는 원칙은 결국 일곱 가지입니다. 각 원칙마다 판단 기준을 한 문장으로 정의하고, 그 기준을 통과한 적절한 예와 기준을 위반한 잘못된 예를 대조합니다. 괄호 번호는 본문의 해당 항목.

8.1.1

Content-First · Minimization — UI는 콘텐츠를 위해 물러난다

크롬(제목·바·버튼)은 콘텐츠를 돕는 수단이지 주인공이 아님. 안 쓰는 순간에는 접히거나 사라져야 함.

기준
"이 UI 요소가 지금 이 순간 사용자의 과업에 기여하는가?" 기여하지 않는 순간이 있다면 그 순간에는 축소·접힘·숨김이 기본이어야 한다.
적절한 예
Large 타이틀의 스크롤 축소 (1.2.1) — 진입 순간엔 방향감이 과업에 기여하므로 크게, 읽기 시작하면 기여가 끝나므로 inline으로 접혀 공간을 콘텐츠에 반납. "지금 기여하는가" 기준을 순간마다 다시 묻는 동작 ② Overflow 자동 접힘 (1.1.7)과 Menu (7.1.1) — 드물게 쓰는 액션은 지금의 과업에 기여할 확률이 낮으므로 접어둠. 기능의 완전성은 유지하면서 화면 점유는 기여도에 비례 ③ searchToolbarBehavior(.minimize) (1.4.6) — 검색이 조연인 화면에서 돋보기 버튼 크기로 접어 한 탭 거리는 유지하되 평소 점유는 최소.
잘못된 예
액션이 하나뿐인 화면에 bottom bar 신설 (1.1.1 위반) — 하단 바 전체가 상시 세로 공간을 차지하지만 기여하는 건 버튼 하나. "기여하지 않는 순간에도 화면을 점유"하는 기준 위반 ② 저빈도 검색 화면에 drawer .always (1.4.4 위반) — 대부분의 순간 과업에 기여하지 않는 검색바가 세로 한 줄을 상시 소모 ③ leading·principal·trailing·bottom 전부 채우기 (1.1.9 위반) — "자리가 있으니 채운다"는 기준의 정반대.
8.1.2

Reachability — 빈도가 높을수록 엄지에 가깝게

큰 화면에서 상단은 한 손으로 닿기 어려움. 사용 빈도가 배치 높이를 결정한다는 원칙.

기준
"자주·반복해서 누르는가?" 그렇다면 하단(엄지의 홈 그라운드). 가끔 쓰는 확정성 액션(완료·저장)이라면 상단. 빈도와 높이가 반비례해야 한다.
적절한 예
메일의 "새 메일 작성"을 bottom bar에 (1.1.4) — 메일함에서 가장 자주 반복되는 액션이므로 기준상 하단이 정답. 실제 iOS 메일 앱의 배치 ② iOS 26의 검색 하단 이동 (1.4.1) — 고빈도 기능인 검색이 기존엔 가장 닿기 어려운 상단에 있었음. 빈도-높이 반비례 기준에 맞게 시스템 차원에서 교정한 사례. iPad는 양손 파지 기준으로 상단 trailing — 같은 기준을 기기 인체공학에 맞게 적용.
잘못된 예
1회성 "완료" 버튼을 bottom bar에 — 완료는 화면당 한 번 누르는 저빈도 확정 액션이므로 기준상 상단 trailing 자리. 하단에 두면 고빈도 자리를 낭비하고, 탭바(이동)와 인접해 역할 혼동까지 유발 (1.1.4 Tip 위반) ② 가장 자주 쓰는 액션을 상단 구석에 두고 하단은 비움 — 카메라 앱의 셔터를 상단 trailing에 두는 격. 빈도 최상위 컨트롤이 도달성 최하위 위치에 있어 한 손 사용 시 매번 그립을 바꾸게 됨.
8.1.3

위치·묶음의 문법 — 자리와 캡슐 자체가 의미다

leading=이동 · principal=정체성 · trailing=확정 · bottom=빈도. 그리고 같은 유리 캡슐 = 한 세트. 위치와 묶음이 곧 언어.

기준
"이 컨트롤의 역할이 그 자리의 문법과 일치하는가? 한 캡슐에 묶인 것들이 정말 한 세트인가?" 문법이 지켜져야 사용자가 처음 보는 앱에서도 버튼 위치를 예측할 수 있다.
적절한 예
"지도/목록" 세그먼트를 principal에 (1.1.5) — 이 컨트롤 값에 따라 화면 전체 내용이 바뀌므로 "화면의 정체성"이라는 principal의 문법과 정확히 일치 ② 도구 클러스터(leading)와 완료 버튼(trailing)의 분리 (1.1.2) — 보기 전환·정렬·필터는 한 캡슐(한 세트=도구), 완료는 별도 단일 캡슐(결정). 캡슐 사이의 빈 공간이 "서로 다른 일"이라는 정보를 전달 (1.1.3).
잘못된 예
단순 공유 버튼을 principal에 (1.1.5 위반) — 공유는 화면의 정체성이 아니라 부가 액션. 위계상 가장 강한 중앙 자리에 두면 제목까지 사라지면서 "이 화면이 무엇인지"를 말할 장치가 없어짐 ② 관계없는 기능들을 한 캡슐에 몰아넣기 (1.1.3 위반) — 정렬·공유·설정·삭제를 한 유리 캡슐에 붙이면 사용자는 "한 세트"로 읽음. 묶음이 거짓 정보가 되어 인지 부담 증가 ③ Custom Large Title 자리에 버튼·입력 필드 (1.2.6 위반) — 제목 자리는 "화면 정체성" 문법. 인터랙티브 컨트롤을 넣으면 자리의 문법이 깨짐.
8.1.4

가독성 > 미학 — 투명함과 읽힘이 충돌하면 읽힘이 이긴다

Liquid Glass의 투명함은 미학이고, 컨트롤이 읽히는 건 기능. 충돌 시 우선순위는 항상 가독성·접근성.

기준
"최악의 배경(사진·고대비 그래픽) 위에서, 그리고 접근성 설정(큰 글씨·투명도 감소)에서도 읽히고 눌리는가?" 가장 좋은 조건이 아니라 가장 나쁜 조건이 검증 기준이다.
적절한 예
사진·영상 위 Hard + Thick Material (1.3.3) — 복잡한 배경에서 반투명 유리의 대비가 부족해지면 투명도(미학)를 포기하고 불투명 배경으로 가독성을 확보. "예쁜데 안 읽힌다"에 대한 공식 탈출구 ② Overflow의 최소 터치 타깃 보장 (1.1.7) — 아이템이 많다고 버튼을 무한정 축소하면 손가락 크기 이하로 작아지므로, 시스템이 자동으로 접어 "눌리는가" 기준을 지킴.
잘못된 예
사진 피드 화면에서 scroll edge effect를 hidden으로 (1.3.4 위반) — 밝은 화면 한 조건에서만 확인하고 끄면, 흰 사진이 바 뒤를 지나는 순간 컨트롤이 사라짐. "최악의 배경에서 검증" 기준을 건너뛴 경우 ② 접근성 큰 글씨를 확인하지 않은 lineLimit(1) (2.1.1 위반) — 기본 글자 크기에선 멀쩡해 보여도 Dynamic Type 최대 설정에선 핵심 정보가 첫 어절만 남고 잘림 ③ 유리 툴바 위 커스텀 뷰에 불투명 배경색 (1.1.8 위반) — 시스템이 배경 대비를 관리하는 유리 위에 임의 배경을 얹으면 재질 계층이 깨지고 다크모드·투명도 감소 설정에서 대비가 예측 불가능해짐.
8.1.5

공간은 계약, 텍스트는 가변 — 의미론이 처리 방식을 정한다

공간은 유한한데 텍스트 길이는 예측 불가. 잘림·축소·예약 중 무엇을 쓸지는 그 텍스트가 "문장"인지 "값"인지가 정한다.

기준
"잘려도 뜻이 통하는가?" 통하면 자르고(문장 → truncation), 잘리면 뜻이 죽으면 줄이고(값 → scale), 레이아웃 균일성이 목적이면 공간을 예약한다(reserve). 그리고 잘림·축소는 안전장치이지 레이아웃 설계 수단이 아니다.
적절한 예
메일 목록의 본문 2줄 미리보기 (2.1.1) — 본문은 문장이라 잘려도 앞부분으로 뜻이 통하고, 전문은 상세 화면이 담당. 목록의 목적(훑기)에 맞게 높이를 계약으로 고정한 정석 ② 타이머·금액에 minimumScaleFactor (2.1.3) — "12:34:56"은 잘리는 순간 정보가 파괴되는 "값"이므로 자르지 않고 줄임 ③ 파일 경로에 .middle truncation (2.1.2) — 경로는 앞이 공통 접두사라 앞만 보이면 구분 불가. 정보 가치가 양 끝에 있으니 가운데를 접는 것이 기준에 맞는 선택.
잘못된 예
금액·타이머를 기본 .tail로 자르기 (2.1.3 위반) — "₩1,234,0…"은 뜻이 통하는 게 아니라 틀린 값을 보여주는 것. "잘려도 뜻이 통하는가"에 노(No)인 텍스트에 문장용 해법을 적용한 오류 ② scaleFactor 0.3까지 내려 우겨넣기 (2.1.3 위반) — 절반 이하로 줄여야 들어간다면 축소가 아니라 설계 문제. 폭을 늘리거나 표기를 줄이는(1,234,000 → 1.2M) 게 정답 ③ 세로 목록 전체에 reservesSpace (2.1.4 위반) — 공간 예약의 목적은 그리드·가로 카드의 균일성. 균일성이 필요 없는 세로 목록에선 짧은 셀마다 빈 공간만 상시 소모.
8.1.6

데이터와 표기의 분리 — 값은 앱이, 표기는 로케일이

단위·이름·날짜의 표기 규칙은 문화권마다 다름. 앱은 값만 소유하고 표기는 시스템(FormatStyle)에 위임해야 함.

기준
"데이터를 문자열로 직접 조립하고 있는가? 그 표기 규칙이 문화권마다 다른가?" 둘 다 예스라면 국제화 버그가 이미 심어진 것 — FormatStyle로 옮겨야 한다.
적절한 예
Measurement + .measurement 포맷 (2.2.1) — 앱은 "5km"라는 문자열이 아니라 거리 값만 소유. 같은 데이터가 한국에선 "5킬로미터", 미국에선 "3.1 miles"로 자동 렌더링 — 값과 표기의 분리 기준 그대로 ② PersonNameComponents + .abbreviated로 아바타 이니셜 (2.2.2) — 이니셜 추출 규칙조차 문화권마다 다르므로 직접 substring 하지 않고 시스템에 위임.
잘못된 예
"\(distance) km" 문자열 조립 (2.2.1 위반) — 표기 규칙(단위계)이 문화권마다 다른데 문자열로 굳혔으니 기준의 두 조건을 모두 위반. 미국 사용자에게 킬로미터를 강요하는 국제화 버그 ② "이름 성" 순서 하드코딩 (2.2.2 위반) — "\(firstName) \(lastName)"은 홍길동을 "길동 홍"으로 표기. 이름 순서는 데이터가 아니라 문화권 규칙인데 앱이 소유해버린 경우.
8.1.7

직접 조작 — 대상에 대한 액션은 대상 자체에

액션의 대상이 화면에 보인다면, 별도 버튼을 만들어 관계를 유추시키지 말고 대상을 직접 조작하게 한다.

기준
"이 액션의 대상이 화면에 보이는가? 사용자가 버튼과 대상의 관계를 유추해야 하는가?" 대상이 보이는데 유추가 필요하다면, 액션을 대상 위로 옮겨야 한다.
적절한 예
toolbarTitleMenu (1.2.5) — 현재 폴더 이름(=대상)이 제목으로 보이므로, 이름변경·전환은 제목을 탭해서. 대상과 액션이 한 몸이라 관계 설명이 필요 없고, 툴바 버튼 하나도 절약 ② 인증 코드·주소에 textSelection(.enabled) (2.1.5) — "복사"라는 액션의 대상이 그 텍스트 자체이므로, 별도 복사 버튼 대신 텍스트를 길게 눌러 직접 가져가게 함.
잘못된 예
제목 옆에 별도 "폴더 변경" 버튼 (1.2.5 위반) — 대상(폴더 제목)이 화면에 보이는데 액션은 떨어진 버튼에 있어, 사용자가 "이 버튼이 저 제목에 대한 것"임을 유추해야 함 ② title menu에 설정·로그아웃 같은 화면 전체 액션 (1.2.5 위반) — 제목 메뉴는 "제목이 가리키는 대상"에 대한 액션 자리. 무관한 액션을 넣으면 대상-액션 결합이라는 문법 자체가 거짓이 되어 이후의 모든 title menu를 못 믿게 만듦.