요즘 웬만한 쇼핑몰이나 포털 사이트에는 전부 검색어 자동완성 기능이 있는 걸 볼 수 있다.
그래서 자동완성 기능을 자바스크립트로 구현해보았다.
네이버, 유튜브 등에서 제공하는 검색어 자동완성 기능.
HTML은 검색어 입력을 받을 <input>
태그,
그리고 추천 검색어들을 리스트로 담을 <ul>
태그,
마지막으로 ul
자체를 감싸는 <container>
태그를 준비한다.
<input class= "search_input">
<container class = "rel_search">
<ul class="pop_rel_keywords">
</ul>
</container>
사실
container
는div
로 해도 상관없긴 한데 좀 더 본연의 역할에 맞는 태그명을 짓기로 했다.
여기서는 기능 구현에만 초점을 맞출 것이므로 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%
}
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초 정도 차이가 나게 된다.
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
함수가 재귀적으로 다시 실행되도록 했다.
const loadData = (input) => {
const url = `https://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 에게 감사드립니다)
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초마다 불러온다.
이미 불러온 데이터를 또 불러오는 건 네트워크 자원 낭비이므로 뭔가 개선이 필요할 듯 싶다.
좋았던 점은 아직도 잘 이해가 가지 않는 비동기랑 통성명은 한 느낌..?