[JavaScript30] 6. AJAX Type Ahead with fetch() | fetch(), Spread Operator, RegExp
language/javascript

[JavaScript30] 6. AJAX Type Ahead with fetch() | fetch(), Spread Operator, RegExp

๐Ÿ“ƒ ์š”๊ตฌ์‚ฌํ•ญ

  1. input์ฐฝ์— ๋ฌธ์ž๋ฅผ ์ž…๋ ฅํ•˜๋ฉด, ์ผ์น˜ํ•˜๋Š” city๋‚˜ state์˜ ๊ฐ’์„ ํ•˜๋‹จ์— ์ถœ๋ ฅํ•œ๋‹ค.

 

โœจ ๊ฒฐ๊ณผํ™”๋ฉด

๋…ธ๋ž€ ๋ฐฐ๊ฒฝ์ด ๋ง˜์—๋“ ๋‹ค! ใ„ฑใ…‡ใ…‡

 

๐Ÿ’ป ์†Œ์Šค์ฝ”๋“œ

๐Ÿ™„ ๋‚ด๊ฐ€ ์ž‘์„ฑํ•œ ์ฝ”๋“œ

๋ฉฐ์น ๊ฐ„ ์ด๊ฒƒ์ €๊ฒƒ ์ฐพ์•„๋ณด๋ฉด์„œ ํ—ค๋งธ๋Š”๋ฐ, json ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์™€์„œ city, state, population ๋ฐ์ดํ„ฐ๋ฅผ ๋ฝ‘์•„๋‚ด๊ณ  if๋ฌธ์œผ๋กœ ์กฐ๊ฑด์„ ์ฃผ๋Š” ๊ฒƒ๊นŒ์ง€ ์ž‘์„ฑํ–ˆ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ๋‚ด๊ฐ€ ์“ด ์ฝ”๋“œ๋Š” ํ•œ li์•ˆ์— ์ถ”์ถœ๋œ ๋ชจ๋“  object๊ฐ€ ๋“ค์–ด๊ฐ€๋Š”(;;;) ๋ฌธ์ œ๊ฐ€ ์žˆ์—ˆ๋‹ค. ๊ฒฐ๋ก ์€ ์ „๋ฐ˜์ ์œผ๋กœ ์™„๋ฒฝํ•˜๊ฒŒ ์™„์„ฑํ•˜์ง€ ๋ชปํ–ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๊ฐ•์˜๋ฅผ ๋ณด๊ณ  ๋”ฐ๋ผ ์ณ๋ณด๋ฉด์„œ ์™„์„ฑ์‹œ์ผœ๋ณธ ๋‹ค์Œ, ๊ฐœ์ธ์ ์œผ๋กœ ๋‹ค์‹œ ํ•œ ๋ฒˆ ํ’€์–ด๋ณด๊ธฐ๋กœ ํ–ˆ๋‹ค.

 

๐Ÿค— ๊ฐœ์„ ๋œ ๊ฐ•์˜ ์ฝ”๋“œ

HTML

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Type Ahead ๐Ÿ‘€</title>
    <link rel="stylesheet" href="style.css" />
    <script src="before.js" async></script>
  </head>
  <body>
    <form class="search-form">
      <input type="text" class="search" placeholder="City or State" />
      <ul class="suggestions">
        <li>Filter for a city</li>
        <li>or a state</li>
      </ul>
    </form>
  </body>
</html>

JS

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

const cities = []; // ์ผ์น˜ํ•˜๋Š” ์•„์ดํ…œ์„ ๋‹ด์„ ๋นˆ ๋ฐฐ์—ด

fetch(endpoint)
  .then((blob) => blob.json())
  .then((data) => cities.push(...data));

function findMatches(wordToMatch, cities) {
  return cities.filter((place) => {
    // ์ž…๋ ฅ๊ณผ ์ผ์น˜ํ•˜๋Š” city๋‚˜ state ์ฐพ๊ธฐ
    const regex = new RegExp(wordToMatch, "gi");
    return place.city.match(regex) || place.state.match(regex);
  });
}

function numberWithCommas(x) {
  return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}

function displayMatched() {
  const matchArray = findMatches(this.value, cities);
  const html = matchArray
    .map((place) => {
      const regex = new RegExp(this.value, "gi");
      const cityName = place.city.replace(
        regex,
        `<span class="hl">${this.value}</span>`
      );
      const stateName = place.state.replace(
        regex,
        `<span class="hl">${this.value}</span>`
      );
      return `
        <li>
          <span class="name">${cityName}, ${stateName}</span>
          <span class="population">${numberWithCommas(place.population)}</span>
        </li>
      `;
    })
    .join("");
  suggestions.innerHTML = html;
}

const searchInput = document.querySelector(".search");
const suggestions = document.querySelector(".suggestions");

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

 

๐Ÿ“– TIL

.fetch()

fetch() ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋น„๋™๊ธฐ ๋„คํŠธ์›Œํฌ ํ†ต์‹ ์„ ์•Œ๊ธฐ์‰ฝ๊ฒŒ ๊ธฐ์ˆ ํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ, ๋‹จ์ˆœํžˆ fetch()๋งŒ ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜๋ฉด ๊ทธ๋ƒฅ ๋‹จ์ˆœํžˆ Promise ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค. ๊ทธ๋ž˜์„œ json() ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด, HTTP Response์˜ body์— ์žˆ๋Š” ํ…์ŠคํŠธ๋ฅผ JSON ํ˜•ํƒœ๋กœ ๋ณ€ํ™˜ํ•ด์ฃผ๊ณ , ์ด๊ฒƒ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค. ๊ทธ๋ž˜์„œ ๋ณดํ†ต ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํ˜•ํƒœ๊ฐ€ ๋””ํดํŠธ๋กœ ์‚ฌ์šฉ๋œ๋‹ค.

fetch('http://example.com/movies.json')
	.then((response) => response.json())
    .then((myJson) => console.log(JSON.stringify(myJson)));

API ํ˜ธ์ถœ์ด ์‹คํŒจํ–ˆ์„ ๋•Œ๋Š”, catch()๋ฅผ ํ†ตํ•ด ์˜ˆ์™ธ(error) ๊ฐ์ฒด๋ฅผ rejectํ•  ์ˆ˜ ์žˆ๋‹ค. Promise์— ๋Œ€ํ•œ ๊ฒƒ์€ ์—ฌ๊ธฐ์— ์ •๋ฆฌํ•ด ๋‘์—ˆ์œผ๋‹ˆ, ํ•œ๋ฒˆ ๋ณต์Šตํ•ด๋ณด๋Š” ๊ฒƒ์ด ์ข‹์„ ๊ฒƒ ๊ฐ™๋‹ค. ๊ฐ•์˜์—์„œ๋„ ์œ„์™€ ๊ฐ™์€ ํ˜•์‹์œผ๋กœ JSON์„ ๊ฐ€์ ธ์˜จ ํ›„, cities๋ผ๋Š” ๋นˆ ๋ฐฐ์—ด์— push()ํ•˜์—ฌ ๋„ฃ๊ณ  ์žˆ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ์ฝ”๋“œ๋ฅผ ์ž์„ธํžˆ ๋ณด๋ฉด, ์ด์ƒํ•œ๊ฒŒ ๋ˆˆ์— ๋ˆ๋‹ค.

fetch(endpoint)
  .then((blob) => blob.json())
  .then((data) => cities.push(...data));

๊ทธ๋ƒฅ push(data)๋ฅผ ํ•ด์ค€๊ฒŒ ์•„๋‹ˆ๋ผ ์ธ์ž ์•ž์— ์  ์„ธ๊ฐœ(...)๊ฐ€ ๋ถ™์–ด์žˆ๋‹ค. ์ด๊ฒŒ ๋ญ”์ง€ ๊ถ๊ธˆํ•ด์„œ ์ฐพ์•„๋ดค๋‹ค.

 

Spread Operator(...์—ฐ์‚ฐ์ž)

Spread ์—ฐ์‚ฐ์ž๋Š” ES6์—์„œ ์ƒˆ๋กญ๊ฒŒ ๋“ฑ์žฅํ•œ ๋ฌธ๋ฒ•์ด๋‹ค. Spread ์—ฐ์‚ฐ์ž๋Š” ๋ฐฐ์—ด, ๋ฌธ์ž์—ด ๋“ฑ iterable object์˜ element๋ฅผ ํ•˜๋‚˜์”ฉ ๋ถ„๋ฆฌํ•˜์—ฌ ์ „๊ฐœํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•œ๋‹ค. iterable object๋Š” ๋ฐ˜๋ณต ๊ฐ์ฒด๋กœ์จ, ๊ฐ์ฒด์˜ ์›์†Œ์— ํ•˜๋‚˜์”ฉ ์ฐจ๋ก€๋กœ ์ ‘๊ทผ์ด ๊ฐ€๋Šฅํ•˜๋‹ค. MDN์—์„œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ •์˜๋˜์–ด ์žˆ๋‹ค.

์ „๊ฐœ ๊ตฌ๋ฌธ์„ ์‚ฌ์šฉํ•˜๋ฉด ๋ฐฐ์—ด์ด๋‚˜ ๋ฌธ์ž์—ด๊ณผ ๊ฐ™์ด ๋ฐ˜๋ณต ๊ฐ€๋Šฅํ•œ ๋ฌธ์ž๋ฅผ 0๊ฐœ ์ด์ƒ์˜ ์ธ์ˆ˜ (ํ•จ์ˆ˜๋กœ ํ˜ธ์ถœํ•  ๊ฒฝ์šฐ) ๋˜๋Š” ์š”์†Œ (๋ฐฐ์—ด ๋ฆฌํ„ฐ๋Ÿด์˜ ๊ฒฝ์šฐ)๋กœ ํ™•์žฅํ•˜์—ฌ, 0๊ฐœ ์ด์ƒ์˜ ํ‚ค-๊ฐ’์˜ ์Œ์œผ๋กœ ๊ฐ์ฒด๋กœ ํ™•์žฅ์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ž˜ ์ดํ•ด๊ฐ€ ๋˜์ง€ ์•Š์•„์„œ ์ข€ ๋” ์ฐพ์•„๋ณด์•˜๋‹ค. ์•„๋ž˜์— ๊ฐ„๋‹จํ•œ ์˜ˆ์‹œ๊ฐ€ ์žˆ๋‹ค.

const arr = [1, 2, 3, 4, 5];
console.log(arr); // [1, 2, 3, 4, 5]
console.log(...arr); // 1 2 3 4 5

์˜ˆ์‹œ๋ฅผ ๋ณด์•˜์„ ๋•Œ, Spread ์—ฐ์‚ฐ์ž๋Š” ๋ฐฐ์—ด์˜ ๊ฐ ์›์†Œ๋ฅผ ์ชผ๊ฐœ๋Š” ๊ฒƒ ๊ฐ™๋‹ค. 

const arr1 = [1, 2, 3, 4, 5];
const arr2 = [...arr1, 6, 7, 8];
const arr3 = [...arr1, 6, 7, 8, ...arr1];
console.log(arr1); // [1, 2, 3, 4, 5]
console.log(arr2); // [1, 2, 3, 4, 5, 6, 7, 8]
console.log(arr3); // [1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5]

๋˜, ๊ธฐ์กด์˜ Object๋Š” ๊ฑด๋“œ๋ฆฌ์ง€ ์•Š์œผ๋ฉด์„œ๋„ ๊ทธ๊ฒƒ์„ ๋ณต์‚ฌํ•ด์„œ ํŠน์ • ํ•ญ๋ชฉ์„ ์ƒˆ๋กญ๊ฒŒ ์ง‘์–ด๋„ฃ์„ ์ˆ˜ ์žˆ๋‹ค. ์ด ๋•Œ, ์›๋ณธ ๊ฐ์ฒด ๋‚ด์˜ ์š”์†Œ๋ฅผ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒฝ์šฐ์—๋Š” ์ƒˆ๋กœ์šด ๊ฐ์ฒด ์•ˆ์˜ ์š”์†Œ ๊ฐ’๋„ ๋ณ€๊ฒฝ๋œ๋‹ค. ์ด๋Ÿฌํ•œ Spread ์—ฐ์‚ฐ์ž๋Š” ๋Œ€์ฒด๋กœ ๊ฐ์ฒด ๋ณต์‚ฌ, ๊ฐ์ฒด ๋ณ‘ํ•ฉ ๋“ฑ์— ์‚ฌ์šฉ๋˜๋Š” ๊ฒƒ ๊ฐ™๋‹ค. 

 

RegExp

RegExp๋Š” ๋ฌธ์ž์—ด์— ํฌํ•จ๋œ ํŠน์ • ๋ฌธ์ž ์กฐํ•ฉ๊ณผ ๋Œ€์‘์‹œํ‚ค๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋˜๋Š” ํŒจํ„ด์ด๋‹ค. ์ •๊ทœ ํ‘œํ˜„์‹์„ ๊ตฌํ˜„ํ•œ JavaScript ํ‘œ์ค€ ๋‚ด์žฅ ๊ฐ์ฒด์ด๊ณ , ์ƒ์„ฑํ•˜๋Š” ๋ฌธ๋ฒ•์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

new RegExp(๊ฒ€์ƒ‰ํŒจํ„ด[, ํ”Œ๋ž˜๊ทธ]);

ํ”Œ๋ž˜๊ทธ๋Š” ์ •๊ทœํ‘œํ˜„์‹์˜ ๊ฒ€์ƒ‰ ๋ฐฉ์‹์„ ์„ค์ •ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•˜๋Š”๋ฐ, ํ•˜๋‚˜ ์ด์ƒ์˜ ํ”Œ๋ž˜๊ทธ๋ฅผ ๋™์‹œ์— ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค. ๋Œ€ํ‘œ์ ์ธ 3๊ฐ€์ง€์˜ ํ”Œ๋ž˜๊ทธ๋ฅผ ์‚ดํŽด๋ณด๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

i(ignore case) ๋Œ€์†Œ๋ฌธ์ž๋ฅผ ๊ตฌ๋ณ„ํ•˜์ง€ ์•Š๊ณ  ํŒจํ„ด์„ ๊ฒ€์ƒ‰ํ•œ๋‹ค.
g(global) ๋Œ€์ƒ ๋ฌธ์ž์—ด ๋‚ด์—์„œ ํŒจํ„ด๊ณผ ์ผ์น˜ํ•˜๋Š” ๋ชจ๋“  ๋ฌธ์ž์—ด์„ ์ „์—ญ ๊ฒ€์ƒ‰ํ•œ๋‹ค.
m(multi line) ๋ฌธ์ž์—ด์˜ ํ–‰์ด ๋ฐ”๋€Œ๋”๋ผ๋„ ํŒจํ„ด ๊ฒ€์ƒ‰์„ ๊ณ„์†ํ•œ๋‹ค.

 

 

 

๐Ÿ‘€ ์ฐธ๊ณ 

youtube Wes Bos

https://www.youtube.com/watch?v=y4gZMJKAeWs&list=PLu8EoSxDXHP6CGK4YVJhL_VWetA865GOH&index=6 

 

https://developer.mozilla.org/ko/docs/Web/API/Fetch_API/Using_Fetch