아티클

iOS 커스텀 탭 막대(TabBar) 구현 시 접근성 적용하기

2021-06-18 14:15:13

안녕하세요, 엔비전스입니다.

작년 이맘때쯤 널리 포럼에 여러 접근성 팁을 게시하기 시작하면서 iOS 접근성 API 중에 TabBar trait 에 대해 간단하게 다룬 적이 있었으며 자세한 아티클을 조만간 발행하겠다고 약속을 드렸습니다. 그래서 포럼에서 언급한 커스텀 탭 바 구현 시 접근성 적용 방법에 대해 본 아티클을 통하여 자세하게 다루어 보고자 합니다.

iOS에서 말하는 탭 막대(TabBar)란?

일반적으로 화면 하단에 2개 이상의 탭 요소들을 표시하고 선택된 탭에 따라 탭에 속한 콘텐츠를 담고 있는 하위 뷰 컨트롤러를 화면에 표시하는 구조를 말합니다. 따라서 탭 요소들 중 단 한 요소만 선택이 가능하며 대부분 탭이 전환되더라도 하단의 탭 요소들은 고정되어 있습니다.

네이티브 탭 바는 UITabBarController 클래스로 탭을 구현하게 되는데 네이티브 탭 바로 탭을 구현 시에는 다음과 같은 접근성 정보가 자동으로 제공됩니다.

  1. 요소 유형: VoiceOver 사용자가 하단의 탭 요소에 초점을 맞췄을 때 해당 요소 유형이 탭이라는 것을 알려줍니다.
  2. 몇 개의 탭이 있으며 현재 초점을 맞추고 있는 요소는 몇 번째의 탭인지를 알려줍니다.
  3. 컨테이너 단위로 이동하면 탭 컨트롤이 표시되는 요소로 바로 이동이 가능해서 탭 영역으로 이동이 쉽습니다.
  4. 다른 탭을 선택할 경우 화면 전환이 되었다는 것을 사운드를 통해 알립니다.

위에서 설명을 비추어 생각해 보면 네이티브 탭 컨트롤을 사용하면 접근성을 별도로 신경 쓰지 않아도 된다는 것을 알 수 있습니다. 그러나 이미 커스텀으로 만든 탭 컨트롤에 대해서는 몇 가지 접근성 기능을 구현을 해 주어야 합니다.

탭 요소 유형 알리기

가장 중요한 것은 당연히 각 탭 요소를 탭이라고 안내하도록 해야 합니다. 커스텀 탭 구현의 형태는 다양하겠으나 여기서는 UIView 컨테이너 안에 과일, 채소, 육류 3개의 UIButton 요소를 두고 탭을 선택할 때마다 이에 대한 콘텐츠가 표시되는 형태라고 가정해 보겠습니다. 만약 접근성 고려하지 않았다면 탭 영역에 포커스 해도 채소 버튼, 육류 버튼, 과일 버튼과 같은 식으로 읽어줄 것이므로, 사용자가 여러 요소 중 하나가 선택되는 형태라는 정보를 전혀 알 수 없게 됩니다. 따라서 우리는 TabBar accessibilityTraits 속성을 통해서 명확한 요소 유형을 정해 줄 필요가 있습니다.

  1. 일반적으로 button, link 와 같은 accessibilityTraits는 스토리보드의 Identity Inspector 내의 접근성 섹션에서 체크, 혹은 해제하는 형태로 적용을 할 수 있습니다. 그런데 TabBar accessibilityTraits는 해당 Inspector에는 없으며 Swift에서 코드 형태로 추가를 해 주어야 합니다.
  2. 네이티브 탭 바는 탭 바 컨테이너 하위에 여러 뷰 컨트롤러를 두는 형태이므로 커스텀 탭 바에서도 TabBar accessibilityTraits 는 육류, 채소와 같은 각 탭 요소에 별도로 부여하는 것이 아닌, 탭 요소를 품고 있는 상위 컨테이너에 적용을 해야 합니다.

    예: customTabContainer.accessibilityTraits = .tabBar

    위의 예시와 같이 적용하면 컨테이너 하위 요소가 버튼이더라도 컨테이너에 부여된 accessibilityTraits 속성이 TabBar 이므로 하위 각 요소들을 탭으로 읽게 되며 네이티브 탭 바와 마찬가지로 탭에 포커스 하면 전체 탭 개수와 현재 초점을 받은 요소가 몇 번째 개수인지를 함께 읽어주게 됩니다.

참고: iOS 14 버전이 출시되었을 때에는 tabBar accessibilityTraits 속성을 적용하더라도 전체 탭 개수와 현재 포커스 하고 있는 탭이 몇 번째 탭인지를 제대로 읽어주지 못하였으나 iOS 14.6에서 해당 문제가 해결되었습니다.

선택됨 상태 정보 구현

선택된 커스텀 탭에 isSelected 속성을 추가했다면 VoiceOver가 해당 속성을 통해 선택된 탭에 대한 정보를 제공할 수 있지만 시각적으로 디자인을 준 형태로 구현했다면 상태 정보에 대한 구현이 필요합니다. 상태 정보에 대한 구현은 아주 간단합니다. 선택된 탭 요소에 selected accessibilityTraits 속성만 적용하면 됩니다.

  1. 화면이 처음 표시되었을 때 선택된 기본 탭 요소에 selected trait 속성을 줍니다.
    예: vegetableTab.accessibilityTraits = .selected
  2. 사용자가 다른 탭을 선택했을 때는 기존 선택됨 정보는 해제하고(none accessibilityTraits 적용) 변경된 탭에 selected accessibilityTraits 속성을 줍니다.

참고: accessibilityTraits .none 속성은 해당 요소에 아무런 접근성 속성 및 상태를 포함하지 않을 때 사용합니다. 여기서 탭 요소로 읽는 것은 상위 컨테이너의 접근성 정보를 상속받아 탭이라고 읽어주는 것이므로 none trait 속성을 적용하더라도 탭 요소 정보는 유지됩니다.

탭 전환 시 화면 변경 알림 적용하기

네이티브 탭 바는 탭 바 뷰 컨트롤러 하위에 각 탭 콘텐츠에 대한 별도의 하위 뷰 컨트롤러들이 존재하며, 탭이 전환될 때 뷰 컨트롤러가 전환됩니다. 따라서 VoiceOver에서는 화면이 변경되었다는 사운드를 출력합니다. 커스텀 탭 바의 경우 각 탭 콘텐츠가 별도의 뷰 컨트롤러로 적용되지 않았을 경우에는 탭을 전환하더라도 화면 변경에 대한 사운드는 출력하지 않으므로 이 역시 추가 구현이 필요합니다. 화면 변경에 대한 접근성 이벤트는UIAccessibility.post(notification: .screenChanged 속성을 사용할 수 있습니다. 해당 속성을 사용하면 다른 뷰 컨트롤러로 화면이 전환되지 않았음에도 마치 다른 뷰 컨트롤러가 표시된 것 같은 접근성 이벤트가 발생하여 사용자에게 화면이 변경되었음을 알리게 됩니다. 여기서 중요한 것은 argument인데 nil을 주면 현재 화면에서 접근성 초점을 받을 수 있는 가장 첫 요소로 초점을 이동시킵니다. Nil이 아닌, 화면에 표시된 객체들 중 하나를 주면 그 객체로 초점을 이동시킵니다.

탭 요소는 화면이 변경되었을 때 초점이 탭에 유지하도록 하는 것이 범용적이므로 화면 변경 이벤트 역시 argument: sender 와 같은 형식으로 적용하여 선택한 탭에 초점이 유지되도록 합니다.

 

지금까지 커스텀 탭 요소에 대한 접근성 구현 방법에 대해 살펴보았습니다. 이 글을 작성하면서 네이티브 컨트롤 사용이 접근성 구현 측면에서 얼마나 개발 리소스를 줄일 수 있는지 다시 한번 생각해 보게 됩니다. 이 글이 네이티브 컨트롤 사용을 높이고 커스텀 탭으로 이미 구현된 요소의 접근성을 향상시키는 데 도움이 되었으면 합니다.

댓글 0
댓글을 작성하려면 해주세요.