일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- stateobject
- Animation
- arkit
- RxSwift
- Network
- withAnimation
- state
- dataflow
- iphone
- combine
- gesture
- GCD
- authentication
- auth
- ios
- swift
- view
- UIKit
- Performance
- SwiftUI
- WWDC
- avsession
- 달력
- toolbarvisibility
- 네트워크
- CS
- 접근성제어
- Concurrency
- 최적화
- firebase
- Today
- Total
XLOG
[SwiftUI] VoiceOver 사용자를 위한 Accessibility 요소 적용기 본문
2022년 애플아카데미에 있을 때 Accessibility 관련 주제에 대해 얘기를 들은 적이 있었다.
옛 직장에서 홍보관 리뉴얼을 진행할 때 휠체어를 탄 사람들이 관람하기 어려운 곳이란 판단에 그 부분에 대한 업데이트를 요청한 적이 있었다. 국내 성인이면 누구나 알만한 대기업이 었지만 금액, 효율 등의 이유로 바로 반려당한 적이 있던 나였다.
하지만 Apple 은 아카데미를 오픈할 당시 자동문의 사이즈가 휠체어 사용자를 위한 사이즈를 충족하지 못하였기에 오픈을 연기했었다. 그런 기억이 있기에 Accessibility 에 관한 내용을 처음 접했을 때 어떤 유저든 사용편의성을 주기 위한 노력을 하는 기업이구나란 생각을 했고, 나도 앱을 개발하게 되면 그런 노력을 해야겠다고 생각을 했는데....여태 잊고 있다 최근 다시 접하며 고민을 하게 되었다.
사용법은 워낙 많이 작성이 되어 있으므로, 주로 사용했던 ModifiedContent 에 대한 정리만 해볼까 한다.
1. Accessibility Inspector

2. 많이 사용했던 요소와 이유
- .accessibilityLabel
기본적으로 SwiftUI 는 각 View 마다 본인만의 Label을 가진다. 하지만 일반적인 입력 Form 에는 다양한 TextField 가 존재한다.
또한 Button 도 마찬가지다. 이때 VoiceOver 사용자만을 위한 Label 을 적용할 수 있다. 인자로는 Text() 를 받는다. - .accessibilityHint
Hint 는 Label 의 설명이 부족할 때 그 설명을 보충해 주는 요소로 WWDC 영상을 보다 보면 Label 은 간결하게 쓰길 권장하기에 부가적인 설명을 작성하라고 한다. - .accessibilityValue
TextFiled 나, Toogle 등의 상태값을 VoiceOver 를 통해 얘기할 수 있도록 한다. - .accessibilityElement
주로 ViewHierarchy 에세 자식요소에 대해 어덯게 Navigate 할지, 설명할지 등을 정의할 때 사용한다. 이 부분이 가장 많은 고민을 불러 일으켰다. VoiceOver 기능을 켜게 되면 직접적인 터치로 Focus 를 줄 수 있지만 화면이 보이지 않는다면, 제스쳐를 통해 순서대로 하나하나 이동을 해야한다.
대부분 우리가 CollectionView, TableView, List 등에 하나의 Cell 을 설계할 때 수 Cell 은 1개 이상의 ViewHierarchy 를 갖는다. 예를 들어 하나의 Cell 에 View 가 5가지이고, 검색한 갯수가 20개 일 경우 20번째 요소까지 가기 위해선 기본적으로 95번의 제스쳐를 한 후에 20번째 요소에 접근이 가능하다는 걸 알 수 있다. 여기서 Cell 내부에 Button 1개와 Text 4개로 구성이 되어 있다고 하면 해당 요소는 하나의 Button 으로 Accessibility 요소를 묶을 수 있다. 그렇게 되면 95번의 제스쳐가 19번의 제스쳐로 줄어들 수 있게 된다.
children 프로퍼티에 사용할 수 있는 값은 <#T##AccessibilityChildBehavior#> 타입으로 .combine, .contain, .ignore 가 있다.
.combine 은 자식요소를 하나로 묶는다. 그렇기에 제스쳐로 요소 하나하나 navigate(접근) 이 된지 않는다. 해당 객체의 타입은 액션을 동작시키는 View 를 대표 타입으로 설정한다.
.contain 은 기본값으로 하나하나 접근이 가능하다.
.ignore 는 말그대로 무시기 때문에 내부에 요소가 아무것도 없다고 처리가 된다.

- .accessibilityAction
Action 은 말그대로 VoiceOver를 통해 클릭 액션을 했을 때 발생하는 Action이다. 기존에 Button 이나 onTapGesture 로 동작이 정의되어 있더라도 따로 AccessibilityAction 을 설정해준다면 AccessbilityAction 을 실행하게 된다. 이 기능을 사용했던 이유는 Cell 에 버튼이 두 가지 이상일 때, 그 중 하나는 UI 요소의 변경을 불러일으키는 것이라면(예: 검색한 장소 리스트에서 지도의 center 를 선택한 장소로 이동시키는 것과 해당 장소 정보 보기 버튼) Group 화를 한 후 하나의 action 만을 동작시키도록 하여 navigate 요소를 줄이고 필요로 하는 동작을 할 수 있게끔 하는데 사용했다. - .accessibilitySortPriority
기본적으로 accessibility 의 hierarchy 순서는 top to bottom, left to right 이다. 이걸 사용했던 이유 역시 VoiceOver 에 navigate 방법 때문이다. Gesture 로 이동을 하는 것이기의 View 의 목적이 무엇인지, 목적에 맞게 최단한 적은 횟수로 원하는 동작을 시킬 수 있도록 navigate 의 우선 순위를 조절했다. property 로 Double 을 받으며 높은 숫자일 수록 우선권을 갖는다. - .accessibilityAddTraits
이것은 해당 view 의 타입을 정할 수 있다. 예를 들면 view 의 element 를 ignore 로 설정을 하게 되면 해당 View의 타입이 none 으로 설정되어 있다. 이렇게 되면 유저는 어떤 타입인지 알 수 없기 때문에 선택이 가능한지조차 예상할 수 없다. 그럴 땐 isButton 요소를 추가할 수 있다. 또한 선택된 상태를 알리는 isSelected 도 있는데 이걸 설정하게 되면 해당 요소의 value 가 1 로 설정이 된다. Picker 를 사용하여 Segment 를 만들게 되면 UI 가 제한적이기에 Segment 역할을 할 수 있는 Button 을 만들어서 사용하곤 했는데 이 때 label, trait, hint 등을 활용해 그 용도를 유저에게 알리도록 한다.- accessibilityTrait 종류 - https://developer.apple.com/documentation/swiftui/accessibilitytraits
- .accessibilityHidden
이것은 불필요한 요소에 navigate 가 되지 않도록 하여 제스쳐를 줄이는 데 사용했다. - .accessibilityFocused
TextField 에 FocusState 처럼 @AccessibilityFocusState 프로퍼티 Wrapper 를 정의하여 FocusState 처럼 사용한다.
3. 느낀점
기본적으로 SwiftUI 에는 모두 Accessibility 가 추가가 되어 있기에 크게 고민을 안할 수 있겠구나 싶었지만 직접 VoiceOver를 켜서 안보고 동작을 하려고 했더니 고려해야할 요소들이 많았다. 또한 UI 요소에서도 어떠한 항목이 필요하고, 필요없고에 대한 생각을 할 수 있었던 계기가 되었다. 물론 회사에서 업무를 하게 되면 PM 과 UI/UX 디자이너에 요청에 맞게 개발을 해야하겠지만서도, Accessibility 요소 그리고 다양한 사람들이 사용하는 측면을 고려하다보면 다양한 시각에서 View 를 구성할 수 있다. Button 에 Disabled 또한 시각적으로 직관적이라고 생각을 했다. 하지만 시각적으로 불편한 유저에게는 그 쓰임을 제대로 발휘할 수 없다. 또한 액션이 동작하지 못하기에 필요한 곳으로 Focus 를 옮기는 것 또한 한번이 동작하지 않는다. accessibilityAction 을 정의를 하더라도 VoiceOver 에선 동작하지 않는 버튼이라고 안내를 하기에 눌러볼 생각을 못할 수 있다.
접근성 제어를 고민하다 보면 내가 필요없다고 생각한 UI 요소가 왜 필요한지, 또한 View Layout 을 고민할 때 어떤식으로 그룹화를 하는게 좋을지 등 다시 한번 생각을 할 수 있는 좋은 계기가 되는 것 같다.
참고
https://developer.apple.com/documentation/swiftui/view-accessibility
Accessibility modifiers | Apple Developer Documentation
Make your SwiftUI apps accessible to everyone, including people with disabilities.
developer.apple.com
https://developer.apple.com/design/human-interface-guidelines/accessibility
Accessibility | Apple Developer Documentation
People use Apple’s accessibility features to personalize how they interact with their devices in ways that work for them.
developer.apple.com
WWDC 영상들
'Swift > SwiftUI' 카테고리의 다른 글
[SwiftUI] onChange iOS 분기처리 (0) | 2024.12.25 |
---|---|
[SwiftUI] Observation (feat iOS 17, 써야하는 이유) (2) | 2024.08.17 |
[최적화] View 의 Update 를 최소화 하는 방법 (0) | 2024.07.01 |
[DataFlow] State, Binding, StateObject, ObservedObject, EnvironmentObject 는 무엇이고 차이는? (0) | 2024.07.01 |
[SwiftUI] Environment 활용하기 (0) | 2024.06.25 |