Upgrade to Pro — share decks privately, control downloads, hide ads and more …

DevFest 2024 Incheon/Songdo - 웹 접근성으로...

limkhl
December 21, 2024

DevFest 2024 Incheon/Songdo - 웹 접근성으로 보는 오픈소스

2024년 12월 21일 토요일 송도컨벤시아에서 열린 DevFest에서 '웹 접근성으로 보는 오픈소스' 주제로 발표한 자료입니다.

limkhl

December 21, 2024
Tweet

More Decks by limkhl

Other Decks in Technology

Transcript

  1. 안녕하세요. 오늘 웹 접근성으로 보는 오픈소스를 주제로 발표하게 된 임경희입니다.

    저는 퀄슨에서 웹 프론트엔드 개발자로 리얼클래스라는 영어 교육 서비스를 만들고 있습니다.
  2. 먼저 웹 접근성이 무엇인지 짚고 넘어갈 거고요. 오픈소스 UI 컴포넌트

    라이브러리 중에 웹 접근성 대응이 잘 되어 있는 프로젝트들이 많거든요. 오늘은 이 오픈소스들이 어떻게 웹 접근성 대응을 하고 있는지 가볍게 살펴볼 예정입니다. 또 웹 접근성으로 오픈소스에 기여할 수 있는 방법을 소개하면서 마치겠습니다.
  3. 지난 12월 3일 밤 비상 계엄이 선포됐었죠. 저는 TV가 없어서

    단체 톡방에서 처음으로 소식을 들었는데요. 계엄 선포가 된 거면 정말 큰 일인데 아무런 안내가 없어서 이게 진짜 맞나? 싶더라고요. 비상계엄 선포 방송 때도 수어통역이 없어서 농인들은 계엄 소식을 알 수가 없었다고 하더라고요. 계엄 해제가 안됐더라면 일상이 완전히 무너질 만한 중요한 일이었는데 정보 전달이 안돼서 대비할 새 없이 속수무책으로 당할 수 있었다고 생각하니 더 아찔하게 느껴졌습니다.
  4. 이번 일로 접근성의 중요성을 더 절감하게 됐는데요. 농인뿐만 아니라 집에

    TV가 없는 저를 포함해 누구라도 정보에 접근할 수 있도록 보장하는 것을 접근성이라고 합니다. 웹사이트에 있는 정보를 누구나 접근 가능하게 만드는 것이 웹 접근성이고요.
  5. 웹의 창시자인 팀 버너스 리는 “웹의 힘은 보편성에 있다. 장애에

    관계없이 모든 사람이 접근할 수 있도록 하는 것은 필수적인 요소이다.”라고 말했습니다. 저도 웹이야 말로 접근성을 확장하기에 가장 좋은 매체라고 생각해요. 그래서 웹 프론트엔드 개발자로서 누구나 접근 가능한 방식으로 웹을 만들기 위해 책임감을 가져야한다고 생각하고 있어요.
  6. 그럼 웹 프론트엔드 개발자는 어떻게 웹 접근성을 대응할 수 있을까요?

    마크업 할 때 html 요소에 WAI-AREA 속성을 넣어주면 스크린리더에서 잘 읽어주도록 처리할 수 있습니다. 텍스트를 가지고 있지 않은 아이콘 같은 요소는 스크린리더가 읽지 않기 때문에 실제로 유저가 존재를 알아야 하는 요소라면 라벨링도 해줘야 하고요. 키보드로만 요소를 이동할 수 있도록 대응해줘야 합니다. 또, 모바일은 PC와 다르게 키보드가 없기 때문에 모바일 스크린 리더를 위해 따로 처리해줘야 하는 것도 있고요. 실제로 스크린리더에서 잘 읽히는지 voiceover나 talkback과 같은 스크린리더로 테스팅도 해야 합니다. 간단하게만 정리해봐도 정말 공수가 많이 들 것 같고 이걸 언제 다 대응하나 절망적이게 느껴지는데요. 1번부터 시도해보려고 해도 뭐부터 해줘야하나 막막한데요. 저는 어디 베스트 프랙티스라도 있다면 클론 코딩하면서 익히고 싶다는 생각부터 들더라고요.
  7. UI 컴포넌트 라이브러리는 UI 하나하나 디자인하고 구현할 필요 없이 미리

    만들어진 컴포넌트를 제공하는 라이브러리입니다. 전에는 부트스트랩을 많이 사용했었죠.
  8. 요새 웹 프론트엔드에는 정말 많은 UI 컴포넌트 라이브러리가 있습니다. 크게

    4가지 분류로 나눠보았는데요. Headless는 로직만 제공하고 스타일은 완전히 사용자가 정의하는 방식, Unstyled은 최소한의 스타일만 제공하고, 사용자가 자유롭게 커스터마이징 가능한 방식, Style Starter은 기본 스타일이나 테마를 제공하는 방식, Full UI Kit, Design System은 스타일 완성도가 높고 완전한 UI 스타일을 제공하는 방식입니다.
  9. 많은 UI 컴포넌트 라이브러리가 있지만 웹 접근성을 잘 대응하고 있다는

    라이브러리만 분류 안에 넣어보았습니다. React Aria, Radix UI Primitives는 Headless, Radix UI, Headless UI, React Aria Components는 Unstyled, Chakra UI, shadcn은 Style Starter, MUI, React Spectrum, daisyUI는 Full UI Kit에 묶입니다.
  10. 가장 큰 생태계는 radix, 다음은 mui, 다음은 headlessui, 다음은 react-aria,

    다음은 chakra-ui입니다. 생태계가 큰 라이브러리부터 특징과 웹 접근성을 어떻게 대응하고 있는지 소개하겠습니다.
  11. Radix Primitives는 접근성을 우선시하는 철학을 갖고 있기 때문에 접근성의 우선순위가

    높은 프로젝트에 좋은 라이브러리입니다. 또, 최소한의 스타일만 제공하는 unstyled 방식의 라이브러리이기 때문에 커스터마이징 하기 편하지만 스타일을 정의하는 과정이 필요하기 때문에 사용 편의성은 약간 낮은 편입니다. Install 명령어를 보시면 특이한 점이 있는데 필요한 컴포넌트를 각각 설치하는 방식으로 사용합니다.
  12. 유저에게 꼭 전달해야하는 중요한 정보를 담고 있는 Alert Dialog 컴포넌트를

    기준으로 실제 컴포넌트를 VoiceOver로 읽을 때 어떻게 읽는지 확인해봤는데요. 들을 때 어떠신 것 같나요? 내용이 잘 이해가 되시나요? Button의 Collapsed 상태도 잘 읽고 다이얼로그가 뜰 때 초점도 잘 이동합니다. 확인이 아닌 취소 버튼부터 초점이 이동하게 만든 것도 의도한 동작 같네요. 다이얼로그에서 탭하면 다이얼로그 안에서만 초점이 이동하고요. 다만 다이얼로그로 이동할 때 내용이 아닌 버튼부터 읽는 건 약간 어색하게 느껴지지만 어쨌든 내용도 잘 읽어줍니다. 다이얼로그를 닫으면 초점도 다시 잘 돌아오고요.
  13. aria-expanded 속성으로 열고 닫는 상태를 넘겨줘서 요소가 열려있는지 접혀있는지 나타낼

    수 있도록 보조하고 있어요. 아까 버튼을 읽을 때 "collapsed"라고 읽었던 게 이 속성 때문입니다.
  14. Radix에서는 dialog가 열릴 때 초점이 dialog 내부의 첫번째 포커스 가능한

    요소로 이동하고 닫힐 때 이전 초점으로 복원되는 처리를 FocusScope 컴포넌트를 이용해 처리하고 있습니다.
  15. hideOthers는 Dialog가 열리면 dialog 외부의 다른 콘텐츠를 aria-hidden 속성으로 숨겨서

    스크린리더가 읽지 않도록 처리해주는 함수입니다.
  16. Shadcn은 radix를 좀 더 편하게 사용할 수 있도록 기초 스타일을

    입혀 래핑한 라이브러리라 radix입니다. shadcn의 특징은 설치하는 방식 이외에도 코드 스니펫을 제공해 radix만 설치하고 shadcn의 컴포넌트 코드를 복사 붙여넣기 해서 사용할 수 있다는 점입니다. 기존에 정의된 스타일을 덮어쓸 필요 없이 그냥 복사한 코드를 바로 수정하면 된다는 점이 편리합니다. 설치할 필요가 없으니 tailwind를 사용하고 있다면 한번 찍먹해보셔도 좋을 것 같아요.
  17. MUI는 구글의 UI 컴포넌트 라이브러리입니다. 접근성 지원이 잘 되어 있고

    디자인 시스템 방식의 라이브러리이기 때문에 커스터마이징 자유도는 조금 떨어지는 대신 스타일을 따로 정의할 필요 없이 바로 가져다 쓸 수 있어서 편의성이 높습니다. 유의할 점은 MUI는 emotion에 대한 의존성을 가지고 있다는 점입니다. 특히 SSR에서는 styled-component 대신 emotion을 사용하라고 강하게 권장하고 있습니다.
  18. 마찬가지로 Alert Dialog 컴포넌트를 voiceover로 읽어봤습니다. 초점 이동은 잘 되나

    다이얼로그 안에 있는 본문을 읽어주지 않아서 어떤 내용인지 알 수 없다는 문제가 있습니다.
  19. Dialog 코드를 살펴보면 radix와 비슷한 aria 속성이 정의되어 있는데요. 한가지

    다른 점은 aria-modal이 정의되어 있습니다. 이 속성은 현재의 dialog가 모달 상태, 즉 dialog 외부 콘텐츠에 접근할 수 없는 상태임을 스크린리더에게 알리는 역할입니다. Radix에서는 이 속성 대신 hideOthers 함수로 다이얼로그 외부의 요소는 무시하게끔 처리하고 있었죠.
  20. Headless UI는 tailwind css 제작자가 개발한 UI 라이브러리입니다. 다른 unstyled

    방식의 라이브러리와 비슷하게 최소한의 스타일만 있기 때문에 개발자가 커스터마이징하기 편리한 대신 사용 편의성은 조금 떨어집니다. 접근성 대응 수준은 높다고 하는데요. 한번 확인해볼까요.
  21. 접근성 대응이 잘 되어 있지 않은 느낌인데요. 다이얼로그가 떠도 초점이

    이동하지 않아서 탭을 해야 이동하고 본문도 읽어주지 않고 탭을 하면 다이얼로그 안에서만 초점이 이동해야 하는데 밖으로 벗어나버립니다. alert dialog만 이러고 다른 컴포넌트는 잘 대응이 됐을 수도 있겠지만요. alert dialog면 중요한 정보를 전달하고 있는 컴포넌트일텐데 정말 접근성 대응이 잘 되어 있는지 의심이 되긴 합니다.
  22. 코드를 보면 aria 속성을 잘 넣어주고 있긴 해요. aria를 잘

    넣어주는 것만으로 접근성을 다 대응할 수 없다는 사실을 알아갈 수 있는 지점이구요.
  23. 다음은 react aria 입니다. adobe 사에서 만든 라이브러리입니다. 정확히는 headless

    방식의 react aria, unstyled 방식의 react aria components, design system 방식의 react spectrum 라이브러리로 구분되어 있습니다. React-aria는 hook에서 반환한 prop을 개발자가 마크업한 요소에 넣어주는 방식으로 사용합니다.
  24. React aria components의 alert dialog 컴포넌트를 스크린리더로 읽어보겠습니다. 지금까지 시연

    중 가장 자연스럽게 느껴지지 않으신가요? 다른 라이브러리들과 다르게 다이얼로그에 진입하자마자 본문을 먼저 읽어줍니다. 다른 동작들도 자연스럽고요.
  25. React-aria에서 useDialog의 구현부를 보면 사파리에서는 다이얼로그에 진입하면 다이얼로그 내부의 첫

    번째로 포커스 가능한 요소에 포커스를 강제하는 버그가 있어서 aria-modal prop을 쓰지 않고 다이얼로그 외부 요소를 모두 aria-hidden 처리하는 방식을 사용한다는 주석이 있습니다.
  26. React aria components의 구현부를 보면 aria-label, aria-labelledby 속성을 지정하지 않으면

    콘솔에 워닝을 띄우는 대응이 되어 있습니다. 최고 수준의 접근성 지원으로 평가받는 라이브러리 답게 꼼꼼하게 신경 쓴다는 느낌을 받았습니다.
  27. React-spectrum의 개발자 devon govett의 트윗인데요. React aria가 다른 라이브러리와 다른

    점으로 모바일 스크린 리더까지 대응하고 있다는 점을 얘기했습니다. 많은 라이브러리들이 ARIA Rractices Guide를 기반으로 구현하고 있는데 여기에도 제대로 다루고 있지 않은 부분이라고요. 예를 들면 모바일에서는 키보드가 없어서 팝요소를 없애고 싶을 때 esc 키로 없앨 수 없습니다. React aria는 Esc 키를 대신할 숨겨진 버튼을 제공하는 방식으로 대응하고 있다고 합니다.
  28. 마지막으로 Chakra UI입니다. 간단한 스타일을 제공하는 style starter 방식으로 unstyled에

    비하면 커스터마이징에 제약이 있지만 사용하기 편리하다는 장점이 있습니다.
  29. 코드를 보면 이제까지 함께 계속 봐왔던 aria 속성들이 들어가 있는

    것을 확인할 수 있습니다. Chakra UI의 조금 특별한 점은 zag라는 상태머신 라이브러리에서 해당 속성을 주입해주고 있다는 점이었습니다.
  30. 지금까지 살펴보니 많은 UI 라이브러리에서 접근성을 잘 대응해주고 있는 것

    같은데요. 그럼 우리는 접근성 신경 쓸 필요 없이 잘 가져다 쓰기만 하면 될까요?
  31. 오늘 발표에서는 aria 속성 위주로 살펴봤는데요. 하지만 aria 속성만 넣어주면

    접근성 대응이 잘 되는 걸까요? ant design의 케이스를 봐볼게요. 여기서 select 컴포넌트가 필수 요소로 들어가야 해서 aria-required 속성을 줘야 하는데요. 현재 ant design에는 해당 요소가 잘못 들어가 있습니다. 무엇이 잘못 되었을까요?
  32. div에는 aria-requied 속성이 잘못 들어가 있었습니다. Input 요소에 적절히 넣어줘야

    합니다. 이처럼 aria 속성이 잘못 들어가게 되면 오히려 넣지 않은 것보다 혼란을 줄 수도 있습니다. 이렇게 오픈소스 프로젝트에서 접근성이 잘못 대응되어 있다면 우리는 무엇을 할 수 있을까요?
  33. 바로 직접 오픈소스를 수정하는 방법이 있습니다. 웹 접근성으로 오픈소스에 기여하는

    방법을 아주 짧게 설명해보려고 하는데요. 일단 이슈를 찾습니다. 우리는 이미 headless ui의 alert dialog 이슈를 하나 찾았죠? 그런 다음 레포를 포크하고 컨트리뷰팅 가이드를 확인합니다. 가이드에 맞춰서 디버깅을 하고 test code나 가이드에 제시되어 있는 방식대로 테스팅을 진행합니다. 문제없이 동작하면 PR을 올립니다.
  34. 이슈를 찾을 때 라벨이 분류되어 있거나 메인테이너가 자주 활동하는 레포를

    찾는게 좋은데요. Ant deșign 이슈를 보면 accessibility 태그가 달린 이슈가 많네요. 오픈소스 기여할 기회입니다.
  35. 컨트리뷰팅 가이드는 주로 리드미가 있는 경로에 있어요. 프로젝트마다 다르겠지만 빌드하는

    방법, 테스트하는 방법에 대한 가이드가 있으니 참고해서 디버깅하시면 됩니다.
  36. 마지막으로 저도 react-spectrum에 첫 오픈소스 기여를 했는데요. 저도 영어 울렁증

    있고 오픈소스 기여를 하려고 해도 막막해서 손도 못 대던 사람이었어요. 혹시 저처럼 어려움을 겪고 계신 분이 있다면 여러분도 오픈소스에 기여 할 수 있다는 응원을 보내드리며 발표를 마치겠습니다.