티스토리 뷰
const highlightKeyword = (title: string, keyword: string) => {
const parts = title.split(new RegExp(`(${keyword})`, "gi"));
return parts.map((part, index) =>
part.toLowerCase() === keyword.toLowerCase() ? (
<span key={index} className={styles["highlight"]}>
{part}
</span>
) : (
part
)
);
};
<li className={styles["search-data-title"]}>
{highlightKeyword(item.title, debouncedKeyword)}
</li>
- RegExp: 정규 표현식을 사용하기 위한 내장 객체
- new RegExp((${keyword}), "gi")는 키워드(keyword)를 대소문자 구분 없이 찾기 위한 정규 표현식이다 gi 플래그는 전역 검색(g)과 대소문자 구분 없이(i) 찾도록 설정된다
- 주의할 점 (${keyword}) 키워드를 꼭 소괄호로 한번 더 묶어줘야 키워드를 하나의 그룹으로 묶어준다
- split
- split(regex)는 키워드를 기준으로 문자열을 분리한다 분리된 결과는 키워드가 포함된 문자열을 각 배열 항목으로 나누고 일치하는 부분만 하이라이트 할 수 있게 된다
- map
- 분리된 키워드는 새 배열로 반환되기 때문에 map으로 배열을 순회한다
- 제목과 키워드를 toLowerCase()으로 소문자로 변환해 대소문자 관계없이 비교할 수 있도록 한다
- 조건문으로 제목과 키워드가 일치하는 부분을 찾아 span태그로 감싼다
- 일치하지 않는 나머지는 그대로 사용한다
- 결과 title : bookPang , keyword :Book (또는 book) = > bookPang
어차피 맵에서 소문자로 변환하는데 왜 정규식을 'g'가 아닌 'gi'를 쓰는가
'g'만 사용해도 원하는 대로 작동하지만, 예기치 못한 오류를 방지하고자 코드 안정성을 위해 사용자가 입력한 키워드를 대소문 구분 없이 분리하고 맵에서 소문자로 변환해 비교하는 방식을 사용했다