[Javascript 30] Day 06 - 검색 자동완성 기능 구현

이사감·2021년 2월 1일
13

Javascript 30

목록 보기
6/15
post-thumbnail

Day 6는 ㄹㅇ 다 처음 해보는 것들이라 강의 외적으로도 찾아 공부할게 많아서 오늘은 글이 엄청 길다 🤯

요구사항

  • input 검색창에 입력시 자동완성된 검색 결과가 하단에 주르륵~ 뜸
  • 검색은 대소문자에 영향을 받지 않음
  • city, state, population을 검색결과로 출력
  • 검색창에 입력된 문자열은 검색 결과에서 하이라이트 됨
  • json데이터를 받아 활용할 것

TIL

JSON

: Javascript Object Notation

JSON 공홈

  • 서버에서 클라이언트로 데이터를 보낼 때 사용하는 양식
  • 자바스크립트에서 객체를 만들 때 사용하는 표현식
  • 좀 더 쉽게 데이터를 교환, 저장하기 위해 만들어진 데이터 교환 표준
  • '속성-값' 또는 '키-값' 으로 이루어진 데이터 객체를 인간이 읽을 수 있도록 텍스트 형식으로 작성
  • AJAX를 위해 사용하는 주요 데이터 포맷
  • 데이터 용량이 작은 경량의 데이터 교환 형식이라, xml을 대체하여 많이 사용됨

AJAX

: 비동기적인 웹 애플리케이션 제작을 위해 아래와 같은 조합을 사용하는 웹 개발 기법

  • html,css
  • 자바스크립트, dom
  • xml, xslt, xmlHttpRequest 등

비동기는 요청과 결과가 동시에 일어나지 않음을 의미한다. 따라서 요청을 처리하는 동안 다른 작업을 할 수 있다.

우선 JSON 데이터를 가져오기 위해 fetch라는 api를 사용한다. Day 6에서는 요 JSON을 사용함


fetch()

참고 자료
AJAX 외에도 서버에 요청을 하여 데이터를 가져올 수 있는데 그 방법 중 하나가 fetch() API이다.
fetch()는 콜백 함수가 아닌 promise를 사용한다.

  • 기본 문법
    let promise = fetch(url, [options])
    - url : 접근하고자 하는 주소. 이 실습에서는 위의 JSON url을 의미
    - options : 선택 매개변수로, 메소드나 header 등을 지정할 수 있는데 아무것도 입력하지 않으면 요청은 get 메소드로 진행된다. get 메소드는 url로부터 콘텐츠를 다운로드한다.

  • then()
    fetch() 는 비동기로 이루어지기 때문에 안정성을 위해 데이터 다운로드가 모두 끝난 뒤 다음 동작을 하게끔 할 때 사용한다.

예제
fetch() 를 사용하여 json 데이터를 다운로드 하고, cities라는 배열에 데이터를 집어넣는다.

const endpoint = 'https://gist.githubusercontent.com/Miserlou/c5cd8364bf9b2420bb29/raw/2bf258763cdddd704f8ffd3ea9a3e81d25e2c6f6/cities.json';

const cities = [];

fetch(endpoint) //options가 입력되지 않아 get메소드로 진행되어 url로부터 콘텐츠를 다운로드 함
.then(blob => blob.json())
.then(data => cities.push(...data));

전개 구문

위의 예제에서 json 데이터를 cities 배열에 집어넣을 때, 전개 연산자인 점 3개 ...을 적어 전개 구문을 사용했다.

전개 구문이란 ES6에서 추가된 문법으로, 전개 연산자를 사용하여 객체 혹은 배열들을 펼칠 수 있게 해준다.

예제 : ...data
.then(data => cities.push(...data));

전개 연산자를 활용한 데이터 추가는 배열에 새로운 요소를 추가한단 점에서 push와 비슷해보이지만, 다르다. 그냥 push를 사용하면

const cities = [1,2,3,4] 일 때

.then(data => cities.push(...data)); 해버리면

cities는 [1, 2, 3, 4, Array(1000)] 가 되어버림

이렇게 배열 안에 값 따로 배열 따로 들어있게 된다. Array(1000) 요놈을 배열을 풀어서 그 안의 요소들을 1,2,3,4처럼 cities 배열 안에 넣기 위해 전개 연산자를 사용한다.

그럼 요로코롬 성공적이게 배열에 데이터 추가가 완료된다.

cities
(1004) [{…}, {…}, {…}, {…}, {…}, {…}, …] 
// 길어서 대충 줄임

match() 메소드와 RegExp

findMatches라는 함수는 사용자가 검색창에 입력한 문자열을 wordToMatch라는 매개변수로 받아 활용한다. (입력한 것을 wordToMatch로 받는건 후술)

findMatches 함수가 어떤 기능을 하게 하려냐면, 데이터 중에 city와 state에 wordToMatch가 대소문자 관계 없이 포함되어 있다면, 해당 city와 state를 보여주게 한다.

예를들어, bos가 wordToMatch로 들어왔다면 bos 문자열이 포함된 city와 state는 Boston, Bossier City가 있으므로 이 두가지 데이터가 필터링되어 반환된다.

이를 filter 메소드와 match 메소드를 활용해 다음과 같이 작성할 수 있다.

function findMatches(wordToMatch, cities) {
    return cities.filter(place => {
        const regex = new RegExp(wordToMatch, 'gi');
        return place.city.match(regex) || place.state.match(regex)
    });
}

이때 const regex = new RegExp(wordToMatch, 'gi'); 구문이 작성된 이유는, 아래 match 메소드와 RegExp 생성자를 통해 이해할 수 있다.

- match()

참고 자료
string(문자열)이 regexp(정규식)과 매치하는 부분을 검색함.

문자열이 정규식과 일치하면 일치하는 전체 문자열을 첫 번째 요소로 포함하는 배열을 반환함. 일치하는 것이 없으면 null을 반환함

  • 기본 문법
    string.match(regexp)

wordToMatch가 변수인데 match()안에 wordToMatch를 넣으면 변수가 아니라 텍스트 문자열로 인식하여 string과 비교한다. 변수로 사용하기 위해서는 RegExp를 활용해 따로 변수를 정의해야 한다.

- RegExp

참고 자료
패턴을 사용해 텍스트를 판별할 때 사용한다.

  • 기본 문법
    패턴과 플래그를 매개변수로 받는다. 플래그는 선택 매개변수.
    • new RegExp(변수명, '플래그')
    • new RegExp(/ab+c/, '플래그')
    • new RegExp('ab+c', '플래그')
플래그 이름플래그 기능
i대/소문자 구분 없이 검색
g패턴과 일치하는 모든 것들을 찾음.
없으면 패턴과 일치하는 첫 번째 결과만 반환됨
m다중 행 모드를 활성화 함
s.이 개행 문자 \n도 포함하도록 ‘dotall’ 모드를 활성화
u유니코드 전체를 지원.
서로게이트 쌍을 올바르게 처리할 수 있다
y문자 내 특정 위치에서 검색을 진행하는
'sticky'모드를 활성화

예제
const regex = new RegExp(wordToMatch, 'gi');
wordToMatch 변수에 들어있는 것을 패턴으로 판별, 판별시 대소문자 구분이 없고 패턴과 일치하는 모든 것들을 찾음.


Input 입력값 받기

input 입력값을 findMatches함수의 매개변수 wordToMatch로 받는 코드는 다음과 같다.

const searchInput = document.querySelector('.search');

searchInput.addEventListener("change", displayInputValue);
searchInput.addEventListener("keyup", displayInputValue);

function displayInputValue(){
    const matchedArray = findMatches(this.value, cities);
   }

- keyup 이벤트

참고 자료
keyup 이벤트는 키를 놓을 때 이벤트가 발생한다.

이 강의에서는 input에 입력하는 값을 감지하는 이벤트로 change 이벤트와 keyup 이벤트를 사용했다.
둘을 함께 사용한 이유는 change 이벤트는 입력을 마치고 완전히 빠져나와야 input.value의 변화를 감지하기 때문이다.
입력 중의 실시간 변화 감지를 위해 keyup 이벤트도 함께 활용했다.

- input 이벤트

참고 자료

input 이벤트는 input, select, textarea 요소의 value 속성이 바뀔 때마다 발생한다.

change 이벤트와 keyup 이벤트를 사용하지 않고, 다음과 같이 input 이벤트 하나로 기능을 구현할 수 있었다.
searchInput.addEventListener("input", displayInputValue);

※ 호환성을 확인하여 input 이벤트를 사용하거나, change & keyup 이벤트를 사용한다.

join();

참고 자료
배열의 모든 요소를 연결해 하나의 문자열로 만든다.

  • 기본 문법
    배열.join([separator])

  • separator
    배열의 각 요소를 구분할 문자열을 지정함. 생략하면 배열의 요소들이 쉼표로 구분됨. separator를 빈 문자열로 작성하면(join('')) 배열의 요소들이 사이에 쉼표도 문자도 아무것도 없이 연결됨


구현

profile
https://emewjin.github.io

0개의 댓글