서론
moti는 더 나은 사용자 경험을 위해 노력한 앱입니다.
지금까지 작성한 인터랙션 애니메이션, 메모리 개선 등이 그 예시인데요.
이번 포스팅에서 다루는 보이스 오버도 더 나은 사용자 경험을 위해 적용한 기능입니다.
또한, 큰 기업 위주이지만 올해부터 모바일에도 접근성 지원을 필수로 적용해야 합니다.
접근성이 드디어 모바일에도 적용이 되는구나 느껴졌던 현상이에요.
이러한 흐름을 따라 우리 moti 앱에도 보이스 오버를 적용해보자고 결심했습니다.
보이스 오버인 이유
저와 팀원 모두 접근성을 처음 적용해보았습니다.
사실 접근성이 뭔지도 네이버 부스트캠프에서 배웠어요.
이정도로 접근성에 대해 아는 게 적었기 때문에 어떤 접근성 지원을 구현할지 고민이었습니다.
저희가 뽑은 후보는 두 개입니다.
첫 번째는 보이스 오버, 두 번째는 다이나믹 타입입니다.
보이스 오버는 화면을 목소리로 읽어주는 기능이고,
다이나믹 타입은 사용자가 설정한 크기대로 글씨 크기가 변하는 접근성 기능이에요.
두 개 다 적용하면 좋았겠지만... 짧은 일정 내에는 무리였고 하나를 선택해야 했습니다.
저희는 최종적으로 보이스 오버를 적용하기로 결정했어요.
저희가 다이나믹 타입보다 보이스 오버를 선택한 이유는 아래와 같습니다.
- 적용하기 쉽다.
- 사진이 핵심 콘텐츠인 앱이기 때문에 보이스 오버의 의미가 더 크다
보이스 오버는 적용하기 쉽습니다.
다이나믹 타입은 글자 크기에 따라 View 구성을 바꿔줘야 하기 때문에 꽤나 복잡한 작업으로 예상되었습니다.
반면 보이스 오버는 적용하기 쉽고, 사이드 이펙트도 없습니다. (accessibility 프로퍼티를 잘못 사용하고 있는게 아니면요.)
이것도 중요한 이유였지만, 저희는 2번때문에 보이스 오버에 더 매력을 느꼈습니다.
접근성을 고민할 때 시각 장애인이 우리 moti 앱을 사용할 수 있을까? 시각 장애인에게 사진을 어떻게 보여줘야할까? 고민이 있었기 때문입니다.
이걸 해결하는 방법이 보이스 오버기 때문에 다이나믹 타입보다는 보이스 오버가 더 매력적으로 느껴졌어요.
위아 같은 이유로 저희는 moti 앱에 보이스 오버를 적용하기로 결정했습니다.
보이스 오버 적용 전
먼저 보이스 오버를 적용하기 전, 보이스 오버 동작 영상을 먼저 보겠습니다.
https://youtube.com/shorts/s_9Cztp5mbY
카테고리 리스트까지는 어느정도 제대로 읽어주지만,
가장 중요한 도전 기록 리스트는 전혀 읽어주지 않고, 심지어 클릭 이벤트도 적용되지 않습니다.
moti 앱을 전혀 설명하지 못하고 동작도 제대로 안 되는 모습입니다.
보이스 오버 적용 방법
보이스 오버는 accessibility 프로퍼티를 설정해서 적용할 수 있습니다.
대표로 도전 기록 리스트를 보겠습니다.
적용할 View에 accessibility를 설정합니다.
도전 기록 리스트는 CollectionViewCell이므로 해당 Custom View에 들어가서 설정해주겠습니다.
imageView.isAccessibilityElement = true
보이스 오버가 View를 읽도록 설정합니다.
The default value for this property is false unless the element is a standard UIKit control, in which case, the value is true
공식문서(https://developer.apple.com/documentation/objectivec/nsobject/1615141-isaccessibilityelement)에서 볼 수 있듯이 표준 UIKit 컨트롤이 아니라면 기본적으로 false로 설정되어 있습니다.
위 영상에서 보이스 오버가 리스트 아이템을 읽어주지 않은 이유입니다.
저희는 리스트 아이템도 읽어야 하기 때문에 true로 설정했습니다.
반대로 보이스 오버로 안 읽었으면 좋겠다면 false로 바꿔주면 됩니다.
imageView.accessibilityLabel = title
accessibilityLabel을 이용해 보이스 오버가 어떻게 읽어줄지 설정할 수 있습니다.
moti에서는 이미지가 도전 기록 섬네일이기 때문에 도전 기록 제목을 읽어주도록 설정했습니다.
imageView.accessibilityTraits = [.image, .button]
accessibilityTraits은 보이스 오버가 읽어주는 View의 역할을 설정할 수 있습니다.
trait은 꽤 세부적으로 나뉘어져 있고, https://developer.apple.com/documentation/uikit/uiaccessibilitytraits에서 확인할 수 있습니다.
도전 기록 리스트 아이템은 이미지면서 누를 수도 있기 때문에 image와 button으로 설정해줬습니다.
여기서 주의할 점은 위 순서는 변경할 수 없습니다.
구현이 OptionSet으로 되어 있기 때문입니다.
OptionSet은 비트마스크를 이용한 자료구조입니다.
OptionSet이기 때문에 순서를 설정할 수 없죠. (Set이니까요)
따라서 [.image, .button]과 [.button, .image]는 동일하게 읽어줍니다. (참고로 버튼 -> 이미지로 읽습니다.)
보이스 오버 적용 후
보이스 오버를 적용한 후 어떻게 변했는지 보겠습니다.
https://youtube.com/shorts/aIYzfGv2FMw
도전 기록 리스트도 잘 읽어주고, 기타 세부적으로도 좀 더 명확하게 읽어줍니다.
마무리
접근성에 대한 관심이 상당히 증가했고, 올해에는 큰 회사이지만 모바일 앱에 접근성 적용이 필수가 되었습니다.
열심히 광고하는 앱도 아니고, 네이버 부스트캠프에서 진행한 작은 프로젝트지만 접근성에 대한 고민을 했다는 것 자체가 의미있다고 생각합니다.
그만큼 재밌기도 하고, 신기하기도 하고, 왜 이걸 이제서야 알게 되었을까 반성도 했습니다.
혹시 이 포스팅을 읽고 계신 분이 계시다면 구현 방법이 쉬우니 한 번 도전해 보세요.
감사합니다.
아직은 초보 개발자입니다.
더 효율적인 코드 훈수 환영합니다!
공감과 댓글 부탁드립니다.