[React] 일치하는 검색어에 <mark>로 하이라이트 주기

planted-ji·2023년 6월 19일
0
post-thumbnail

왜 하필이면 <mark>야?

검색한 내용과 일치하는 부분에 색상을 넣는 건 해당 텍스트를 강조하기 위해서이다. 이러한 효과를 주기 위해 보통 <span>으로 감싸거나 CSS 속성을 통해 스타일을 부여하지만, 마크업에 시맨틱한 의미를 주기 위해 보다 적절한 태그를 사용해보자는 생각이 들었다. 그래서 적용한 것이 <mark>이다.

<mark>에 대하여

MDN 공식 문서 : <mark>

간단하게 설명하자면, <mark>는 사용자의 현재 활동과 연관이 있는 부분을 나타내며 주의를 끌기 위한 목적의 태그라고 할 수 있다. 이번에 내가 적용한 쓰임새처럼 실제로 검색 결과를 나타내는 데 사용되기도 한다.

코드 작성

먼저, searchKeyword 값을 토대로 "gi" 플래그를 사용해 대소문자를 구분하지 않고 전역적으로 일치하는 모든 패턴을 찾도록 설정했다.

function renderLinkContent() {
    const regex = new RegExp(searchKeyword, "gi");

userName 문자열에서 regex에 일치하는 패턴을 찾아 하이라이트 처리된 문자열을 생성하도록 작성했다. replace 메서드는 첫 번째 인자로 전달한 정규 표현식에 일치하는 부분을 두 번째 인자인 콜백 함수로 대체해 하이라이트 처리된 문자열을 생성한다.

const userNameWithHighlight = userName.replace(
     regex,
     match => `<mark>${match}</mark>`,
   );

dangerouslySetInnerHTML 속성을 사용해 userNameWithHighlight 변수를 HTML로 해석해 출력한다. dangerouslySetInnerHTML 속성을 사용할 때는 사용자가 입력하는 텍스트가 html 태그로 인식되지 않게 주의해야 한다. 검색창을 <Input>으로 작성해 모든 문자열을 텍스트로 인식할 수 있었기 때문에 추가로 HTML 이스케이프를 적용하지는 않았다.

return (
        <>
          <Avatar profileImg={profileImg} size={40} />
          <div>
            <strong
              dangerouslySetInnerHTML={{ __html: userNameWithHighlight }}
            />
            {id ? <p>@{account}</p> : ""}
          </div>
        </>
      );
    }

전체 코드

  function renderLinkContent() {
    if (SEARCH) {
      const regex = new RegExp(searchKeyword, "gi");
      const userNameWithHighlight = userName.replace(
        regex,
        match => `<mark class="highlight">${match}</mark>`,
      );

      return (
        <>
          <Avatar profileImg={profileImg} size={40} />
          <div>
            <strong
              dangerouslySetInnerHTML={{ __html: userNameWithHighlight }}
            />
            {id ? <p>@{account}</p> : ""}
          </div>
        </>
      );
    }

기능 구현에 대한 고민

시맨틱한 코드를 위해 <mark>를 적용했지만, 검색어를 강조하는 방법을 검색해보면 내가 사용한 코드를 설명하는 글은 찾아볼 수가 없었다. 그래서 이 방법을 적용하는 게 맞는지 여러 차례 고민을 거치기도 했다. 아래로 이어지는 글은 강사님의 피드백으로 고민에 대한 결론을 정리한 것.

Q. 올바른 사용 방법인가? 또는 실무에서 사용되는가?

A. 단순 표시만을 위한 게 아니라면 <mark>를 사용해도 된다. 스크린 리더에서는 내용은 읽지만 <mark> 요소의 존재를 읽지 않는다. 따라서 실무에서는 <mark> 보다 <span><css>로 처리하는 경우가 많긴 하다.

추가로 MDN의 <mark> 접근성 내용을 읽어보길 추천해주셨다.

스크린리더 사용자를 위한 <mark>의 접근성 개선 기능을 일치 검색어 강조에 사용해도 되는가?

위 사진에서 확인할 수 있는 mdn의 <mark> 접근성 설명을 보면 해당 기술은 남용하면 안 되는 것이기 때문에 콘텐츠의 이해에 강조표시 유무가 꼭 필요할 때만 사용해야 한다는 설명이 나와있다. 저시력자 분들이 검색 기능을 사용할 때 시각적인 하이라이트를 확인하기가 불편한 경우가 발생할 수 있으니 음성 쪽에 강조를 넣어주는 게 맞는지, 아니면 이런 상황에서는 남용에 해당할 수 있으니 강조를 지양하는 게 좋은지에 대한 고민이었다.

A. 음성 강조도 좋고, 시각적인 강조도 좋다. 접근성을 채울 수 있는 유형은 굉장히 다양하다. 강조를 전달할 수 있는 수단이 다양하다면 가능한 많이 사용할수록 좋다고 생각한다. 현재 적용하고자 하는 <mark>의 쓰임새는 적절하며, 남용이 아닌 좋은 시도이다.

나만의 기능 테스트

이러한 Q&A를 참고하여 개인적인 테스트를 시도해보기도 했다. 과연 <mark>의 스크린리더 접근성 기술을 적용했을 때 실제로 얼마나 도움이 될 지 알아보기 위한 소소한 테스트였다. 나는 안경을 벗으면 모니터 텍스트가 전혀 보이지 않을 만큼 시력이 좋지 않았기에, 안경을 벗고 화면이 인식되지 않는 상태에서 window의 보이스 오버를 사용해 검색 기능을 사용해보기로 했다. 이를 통해 <mark>의 접근성 기술을 적용하면 화면이 잘 인식되지 않는 상태에서도 어떤 사용자의 닉네임이 내가 검색한 텍스트와 정확하게 일치하는지 조금 더 구분하기 용이해진다는 것을 알 수 있었고, 결과적으로 전보다 확신을 가지고 기술을 적용할 수 있게 되었다.

0개의 댓글