Search창 구현하기

Kimu·2021년 9월 30일
5
post-thumbnail

검색창을 구현하기 위해 먼저 검색 프로세스를 잠시 알아보자.

  1. 백엔드의 검색 시스템 구조
    먼저 가장 기본적인 방식

1) 테이블을 풀 스캔하는 방식: 전체 테이블 로우를 조회하는 방법

초기에 빠르게 만들기 위한 방법으로 사용되고, 서비스가 커짐에 따라 이러한 방식은 잘 사용되지 않는다.

2) 엘라스틱서치(ES)

풀스캔 방식을 개선하기 위해 데이터베이스에 저장할 때, 문장을 키워드 단위로 2)토크나이징하고, 2)역인덱스(inverted index)를 만들어서 저장하는 데이터베이스 프로그램인 엘라스틱 서치를 사용하는 방식이다.

3) 레디스

검색어와 매칭되는 검색결과를 메모리에 저장(검색로그 캐싱) 후 빠르게 찾아쓸 수 있도록 도와주는 데이터베이스 프로그램인 레디스를 사용하는 방식. 서비스가 더 커지게 되면, 수많은 사람들이 검색하는 데이터는 어느정도의 틀에서 크게 벗어나지 않으므로 이런 방식이 효율적이다.

이렇게 백엔드에서는 데이터베이스를 하나가 아닌, 여러가지를 사용하여 효율적인 검색 엔진을 구축할 수 있다.

  1. 이제 프론트엔드 차례이다.
    fetchBoard에 이미 title을 조회하여 검색한 결과를 리턴해주는 api가 마련되어있다. 그렇게 프론트엔드에서 검색 기능을 수행하기 위해 api 요청시에 검색 키워드를 함께 넘겨주고, 결과를 받아온다.
    또한 그리고 검색된 결과의 키워드에 색을 변경해주는 로직도 배웠다.
    이 과정의 핵심은 검색 결과와 페이지네이션관의 관계인데,
    검색어를 기준으로 불러온 보드의 페이지네이션이 새롭게 만들어져야한다. 어떻게 구현할까? (힌트: useState를 하나 더 만들자)
  1. 마지막으로 검색 버튼을 누르지 않고 창에서 바로 검색이 실행되게 만드는 방식이다. 실제로 이렇게 구현하는 사이트도 있으니 경험해본 적이 있을 것이다. 온체인지 이벤트 함수에 쿼리를 걸면 되지 할 것이다. 맞는 말이다. 그럼 안녕하세요 라는 글자를 치면 쿼리는 몇 번이나 날아갈까? 무려... 12번이다. 이렇게 연속적으로 요청되는 쿼리를 막기 위해서 우리가 사용한 방법은, lodash 라이브러리의 debouncing 이라는 기술이 있었다.
    참고로 lodash라는 라이브러리는 무려 4,000만 다운로드! (이 정도의 횟수면 거의 모든 회사에서 사용한다고 봐도 좋다고..!) 디바운싱 말고도 아주 많은 강력한 기능을 제공하는 라이브러리이므로 사용법을 공부해두면 좋을 듯하다
    여기서 잠깐, 브라우저 이벤트를 감지해 쿼리를 날리는 기술을 제어하는 디바운싱과 쓰로틀링의 차이점에 대해 알아보자.
    디바운싱이란, 정한 시간동안 기다렸다가 특정 이벤트를 실행하는 기술, 오늘 구현한 검색창에서 쓰였다.
    쓰로틀링이란, 일단 처음에 한 번 쿼리를 실행 후 정한 시간동안 이벤트의 실행을 멈추는 기술로서, 대표적으로 스크롤 이동을 감지하면 특정 이벤트를 실행시키고, 이동이 멈출때까지, 이벤트가 재실행 되지 않도록 막아준다.
    모두 lodash라이브러리에 있는 기능이다.

UUID란?
리액트 라이브러리에서는 반복적인 html을 일일히 그리지않고 요소를 배열로 받아다가 맵으로 뿌려준다. 그때 반복되는 요소는 고유한 키가 필요하다. 안쓰면 빨간 줄 에러가 사라지지 않는 저주에 걸린다. 그럼 맵을 걸 배열안에 고유한 요소가 있다면 그것을 키로 주면 좋겠지만 언제나 받아오는 배열안에 고유한 요소가 있는 것은 아니다. 키로 할만한 고유한 요소가 map을 걸 배열 안에 없을 때, 사용할 수 있는 라이브러리이다.

return (
     <>
    <div>검색페이지!!!</div>
    검색어: <input type="text" onChange={onChangeSearch} /><button onClick={onClickSearch}>검색</button>
  //_id라는 고유한 요소를 키로 주면 되는 경우
    {data?.fetchBoards.map((el)=> (
      <div key={el._id}>
        <Column>{el.writer}</Column>
        <Column>{el.title
          .replaceAll(myKeyword, `#$%${myKeyword}#$%`)
          .split("#$%")
          .map((el) => (
            // 키로 줄만한 고유한 요소가 없는 경우
            <MyWord key={uuidv4()} isMatched={myKeyword === el}>
              {el}
            </MyWord>  
          ))
        }</Column>
        <Column>{el.createdAt}</Column>
      </div>
    ))}
    {new Array(10).fill(1).map((_, index) => (
      <Page key={uuidv4()}
      onClick={onClickPage}
      id={String(index + 1)}
{index + 1}</Page>
    ))}
    </>
  )

UUID 설치와 사용법

사용방법은 쉽다
1. 일단,

yarn add uuid

이걸 터미널에 쳐서 라이브러리를 설치한다.
yarn이 없고 npm만 깔려있다면 npm 사이트에서 명령어를 찾아서 쓰자.

  1. 그리고 사용하려는 페이지에서 이렇게 불러온다.
import { v4 as uuidv4 } from 'uuid';

이때 v4 뒤에 오는 as 뒤에 사용하는 단어가 이 페이지에서 uuid 기능을 불러올 변수명이 된다. as uuidv4부분을 삭제해도 무방하며 그렇다면 아래에서 v4라는 이름으로 사용하면 되겠다.

  1. 사용할 곳에 이름과 함께 ()를 붙여서 실행해준다.
<Page key={uuidv4()}

🎨 charm shipjo?😃

profile
지속가능한 개발자

0개의 댓글