얼마 전, 프로젝트에 적용하기 위해서 Masonry 컴포넌트를 만들었고, 이 과정을 정리해서 블로그에 글을 작성한 적이 있다. 하지만 웹 접근성에 대해서 공부하고, 프로젝트에 적용을 하면서 절대로 이런 컴포넌트가 탄생해서는 안되는 것이었다는 걸 깨닫고, 이 글을 통해서 그에 대한 반성문이자 정정하는 글을 써보고자 한다.
기존의 컴포넌트
선택 이유와 구현 방식
먼저 기존에 Masonry 컴포넌트가 필요했던 이유와 구현했던 방식에 대해서 설명하면 다음과 같다.
먼저 필요했던 이유는 다음과 같이 작성했었다.
2차원으로 나열하고자 하는 컨텐츠에 크기가 가지각색이고 그 컨텐츠를 크기를 변경하지 않고자 하는 경우 일종의 딜레마에 빠지게 된다. Grid의 경우 기본적으로 한 행이 그 행의 가장 큰 높이를 가진 자식 요소의 높이를 선택하게 되기 때문이다. 따라서 Grid 만으로 위 사진에서처럼 다음 컨텐츠가 같은 열의 이전 행에 있는 요소 바로 아래에 붙도록 구현하는 것은 불가능에 가깝다. 위 사진과 같은 배치를 Masonry 레이아웃이라고 칭한다.
글에 적혀있는 내용을 보면 전적으로 디자인적인 필요성, 그러니까 높이가 다를 수 있는 요소들을 자연스럽고 아름답게 보여주기 위해서 선택한 방식이었다.
그 구현 방식은 아래와 같다.
마치 ‘2차원 Flex’처럼 수직 방향의 flex를 수평 방향의 flex로 감싼 형태였다. 그리고 그 내용물의 순서를 보장하기 위해서 순서를 직접 분배해서 넣어주는 방식으로 구현했다.
문제점
이와 같은 방식에는 두 가지 큰 문제점이 존재한다.
하나는 접근성 측면에서 최악의 선택이라는 점이다. 스타일을 제외하면 웹페이지의 본질은 결국 문서이다. 문서에는 논리적인 순서가 존재하며 스크린리더는 그 순서를 기준으로 탐색한다. 즉 스타일을 통해서 문서의 논리적인 순서를 변경해 원하는 디자인을 달성하는 방식은 지양해야 한다. 이는 곧 문서의 시각적인 순서와 실제 순서가 동일하게 구성되어야 한다는 것을 의미한다.
하지만 현재 구현한 Masonry 컴포넌트는 이 논리적인 순서를 무시하는 디자인이다. 시각적인 순서는 왼쪽에서 오른쪽으로, 그 다음 위에서 아래로 순서를 가지고 있지만 스타일을 반영하기 위해서 준 문서 순서의 변경 때문에 위에서 아래로, 그 다음의 왼쪽에서 오른쪽 순서로 구성되어있다. 위 이미지 기준의 숫자로 이야기 하면 문서의 순서는 1 > 4 > 2 > 5 > 3 > 6이 되는 것이다.
심지어 현재 이 목록에는 페이징 방식으로 무한 스크롤이 적용되어있는데, 따라서 좌 > 우 탐색이 먼저 이루어지지 않고 위 > 아래 탐색이 먼저 이루어지면 새로운 페이지가 로딩되기 때문에 모든 페이지를 다 불러오고 나서야 두 번째 행으로 이동할 수 있다.
이러한 접근성 문제를 타개한 Masonry 컴포넌트로 수정하기 위해서 검색을 하던 과정에서 두 번째 문제를 발견할 수 있었다. 바로 Masonry 컴포넌트에서는 애초에 항목의 명확한 순서를 구분하기 어렵다는 점이다.
위 그림에서와 같이 새로운 열의 시작을 어디로 인식하는 지에 따라서 논리적인 순서가 달라질 수 있다. 이전 줄에서 가장 짧은 요소가 끝나는 지점을 다음 줄의 시작으로 본다면 좌측이 더 적절할 것이고, 그러한 요소와 상관 없이 왼쪽 > 오른쪽, 위 > 아래 순서를 명확하게 지킨다고 가정했을 때는 오른쪽이 더 적절하다고 할 수 있다. 실제로 나는 오른쪽을 당연하다고 생각했는데, 특정 글들은 자연스럽게 왼쪽 방식에 대해서 설명하고 있었다.
이런 논리적인 순서의 문제는 극단적으로는 아래와 같은 문제를 초래할 수도 있다.
조금 극단적으로 표현되긴 했지만 컨텐츠의 높이가 다르다는 가정 하에 충분히 발생할 수 있는 현상이다. 즉 순서를 아무리 논리적으로 맞춘다고 하더라도 높이에 따라서 달라지는 레이아웃에서는 위아래 항목 사이의 순서는 보장되지만 좌우 항목 사이의 순서는 전혀 보장할 수 없다. 이는 앞선 문제와 반대로 시각 사용자에게 명확한 순서를 지킨 콘텐츠를 제공할 수 없다는 데에서 문제가 된다.
해결 방법
그렇다면 이런 문제는 어떻게 해결하는 것이 좋을까? 상황에 따라서 크게 두 가지로 나눌 수 있다.
디자인을 변경할 수 있는 상황이라면 디자인을 변경하는 것이 최선의 선택이다. 논리적인 순서를 보장할 수 없는 요소를 만드는 것보다는 조금은 덜 역동적이지만 일정한 열 높이가 보장되는 grid 요소를 사용하는 것이 접근성 측면에서도, 단순히 사용성 측면에서도 더 나은 선택일 수 있다.
두 번째 방법은 문서의 순서를 최대한 보장하면서 Masonry 컴포넌트를 구현하는 것이다. 중요한 것은 시각적으로도 순서가 중요할 때, 즉 정렬 기준이 서비스를 사용하는 데에 있어서 중요한 경우에는 사용을 지양해야 한다는 점이다. 배치의 순서가 크게 유의미하지 않을 때에는 그대로 디자인을 유지시키고 단지 문서의 순서만 보장하는 방식으로 수정할 수 있다. 그에 대한 많은 아이디어와 사용할 수 있는 라이브러리들은 아래 링크에서 제공하고 있다.
마무리
프로젝트를 진행하면서 접근성 측면에서 바쁘기 때문에 세세하게는 못 지키지만 큰 틀에서는 유의하고 있다고 생각했는데 가장 많이 재사용 되는 컴포넌트인 Masonry 컴포넌트가 가장 접근성이 보장되지 않았던 컴포넌트였다는 사실에 충격을 받았다. UI와 디자인이 복잡해질 수록 “문서의 순서와 시각적인 순서가 동일하게 구현한다”는 원칙에 항상 유의하면서 구현할 수 있도록 노력해야겠다는 다짐을 다시금 하게 된 계기였다.