Html 검색 자동완성 - html geomsaeg jadong-wanseong

소개

요즘 웬만한 쇼핑몰이나 포털 사이트에는 전부 검색어 자동완성 기능이 있는 걸 볼 수 있다.
그래서 자동완성 기능을 자바스크립트로 구현해보았다.


네이버, 유튜브 등에서 제공하는 검색어 자동완성 기능.


HTML

HTML은 검색어 입력을 받을 <input> 태그,
그리고 추천 검색어들을 리스트로 담을 <ul> 태그,
마지막으로 ul 자체를 감싸는 <container> 태그를 준비한다.

<input class= "search_input"> <container class = "rel_search"> <ul class="pop_rel_keywords"> </ul> </container>

사실 container는 div로 해도 상관없긴 한데 좀 더 본연의 역할에 맞는 태그명을 짓기로 했다.


CSS

여기서는 기능 구현에만 초점을 맞출 것이므로 CSS는 거의 건들지 않기로 했다.

.hide { display: none !important; /* 사용자가 아무것도 입력하지 않았을 때 검색창을 숨기는 용도*/ } .rel_search { display:flex; flex-direction:column; justify-content : space-around; border: 1px solid red; border-radius: 12px; } .pop_rel_keywords { list-style: none; margin-right: 30%; } .pop_rel_keywords > li { /* JS에서 동적으로 li를 생성할 때 적용될 스타일*/ line-height : 250% }

JS

  • 우선 웹 페이지 내에서 동적으로 변경할 DOM 객체들을 선택한다.
const ul = document.querySelector(".pop_rel_keywords"); const searchInput = document.querySelector(".search_input"); const relContainer = document.querySelector(".rel_search");

DOM 객체를 선택하는 데에 getElementbyId 등 선택 방법은 많지만 querySelector가 class, id, tag 등 좀 더 포괄적으로 선택할 수 있어서 선택했다.

  • 사용자가 검색어를 입력하는 타자 속도는 컴퓨터의 연산보다 빠르지 않다.
    이를 감안해서 서버와의 통신 비용을 줄이기 위해
    일정 시간을 간격으로 검색창을 검사할 함수를 만든다.
const checkInput = () => { const beforeInput = searchInput.value; timer(beforeInput); }

checkInput 이 실행되는 시점에서의 searchInput.value와 timer 가 실행되는 시점에서의 searchInput.value 는 timer 함수에 의해 n초 정도 차이가 나게 된다.

  • 0.5 초 정도 여유를 두고 주기적으로 실행되는 함수를 만든다. 0.5초 이후에 검색창을 봤을 때 검색창의 내용이 변했다면 서버로부터 자동완성될 데이터를 불러온다.
const timer = (beforeInput) => { setTimeout(() => { if(searchInput.value === beforeInput) { console.log("입력멈춤"); loadData(searchInput.value); // 0.5초 내에 입력창이 변했다면 데이터 로드 checkInput(); } else { console.log("입력변함"); checkInput(); } if(searchInput.value === "") { // 입력창이 비었다면 추천 검색어 리스트 숨김 relContainer.classList.add("hide"); } else { relContainer.classList.remove("hide"); } }, 500); }

검색창 검사는 주기적으로 실행되어야 하므로, 어느 조건에서든 checkInput 함수가 재귀적으로 다시 실행되도록 했다.

  • 지정한 url 로부터 데이터를 불러와서, li 에 적을 데이터의 프로퍼티를 추출하는 과정이다.
    사용자의 입력에 맞춘 데이터를 가져와야 하므로, url 주소의 쿼리 부분에 매개변수를 넣었다.
const loadData = (input) => { const url = `//completion.amazon.com/... 중략...prefix=${input}&event=onFocusWithSearchT`; // 매개변수 input 값에 따라 서버에서 해당 검색어와 연관된 추천검색어가 담긴 데이터가 불러와진다. if(cache === url) return; // 이전에 부른 데이터랑 다를 때만 fetch로 데이터를 새로 불러온다. else { cache = url; fetch(url) .then((res) => res.json()) .then(res => fillSearch(res.suggestions)) } }

데이터는 직접 만들기에 무리가 있어서 아마존 웹사이트의 url를 활용했다.
(지식 공유해주신 swing 에게 감사드립니다)

* 마지막으로, 불러온 데이터를 미리 만들어둔 HTML 에 뿌려주기만 하면 된다.

const fillSearch = (suggestArr) => { ul.innerHTML = ""; suggestArr.forEach((el, idx) => { const li = document.createElement("li"); li.innerHTML = el.value; ul.appendChild(li); }) }

실행화면

전체 코드

See the Pen 검색자동완성 by junzero741 (@junzero741) on CodePen.

회고

아직은 데이터를 그냥 불러와서 보여주는 수준인 점이 아쉽다.
진정한 자동완성이 되려면 추천검색어가 띄워진 상태에서 키보드 입력을 받아,
자동으로 검색어를 완성해주는 기능이 추가되어야 할 것 같다.
(개선완료)

또 사용자 입력이 0.5초간 멈췄을 때 데이터를 불러와서 띄워주는 로직이므로,
사용자가 검색어를 입력하다가 계속 멈춰있는 경우에도 데이터를 0.5초마다 불러온다.
이미 불러온 데이터를 또 불러오는 건 네트워크 자원 낭비이므로 뭔가 개선이 필요할 듯 싶다. (개선완료)

좋았던 점은 아직도 잘 이해가 가지 않는 비동기랑 통성명은 한 느낌..?

Toplist

최신 우편물

태그