2021 03 11 - adelakim5/fe-w5-searchUI GitHub Wiki

๋ชฉ์ฐจ

  1. ํ”„๋กœํ† ํƒ€์ž… ๊ฐ์ฒด
  2. session-id ๋ฌธ์ œ

ํ”„๋กœํ† ํƒ€์ž… ๊ฐ์ฒด

class์˜ ํ˜•ํƒœ๊ฐ€ ์•„๋‹ˆ๋ผ prototype์œผ๋กœ ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค๊ณ  ์ƒ์†๊ด€๊ณ„๋ฅผ ์ง“๋Š” ์—ฐ์Šต์„ ํ•ด๋ณด์•˜๋‹ค.

๊ทธ ์ „์— ํ”„๋กœํ† ํƒ€์ž…์ด๋ž€ ๋ฌด์—‡์ธ์ง€์— ๋Œ€ํ•ด ์•Œ๊ณ  ๋„˜์–ด๊ฐ€๋Š”๊ฒŒ ์ข‹์€๋ฐ, ์‹œ์ค‘์— ํŒŒ๋Š” ์ฑ…์ด๋‚˜ ์ธํ„ฐ๋„ท์— ๋„๋ฆฐ ํ”„๋กœํ† ํƒ€์ž…์˜ ์ •์˜๋Š” ํ•œ๋ฒˆ ๋ด์„  ์ข€์ฒ˜๋Ÿผ ์ดํ•ดํ•˜๊ธฐ ์–ด๋ ค์šด ๋ฌธ์žฅ์œผ๋กœ ๊ตฌ์„ฑ๋˜์–ด ์žˆ์—ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ๋ช‡๋ฒˆ์˜ ์‹ค์Šต์„ ํ•˜๋ฉด์„œ ๋Š๋‚€ ํ”„๋กœํ† ํƒ€์ž…์ด๋ž€, ์‚ฌ์ „์  ์ •์˜ ๊ทธ๋Œ€๋กœ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ ์›ํ˜•์ด๋ผ๊ณ  ์ƒ๊ฐํ•˜๋ฉด ์‰ฌ์› ๋‹ค.

let animal = {
   eats: true
};

function Rabbit(name) {
   this.name = name;
}

Rabbit.prototype = animal; // Rabbit์˜ ํ”„๋กœํ† ํƒ€์ž…(์›ํ˜•)์€ animal ๊ฐ์ฒด

let rabbit = new Rabbit("White Rabbit"); // rabbit.__proto__ == animal

์œ„ ์ฝ”๋“œ์—์„œ Rabbit.prototype = animal;์„ ํ†ตํ•ด rabbit์˜ [[Prototype]]์€ animal๋กœ ์„ค์ •๋˜์—ˆ๋‹ค.

์ฆ‰, Rabbit์˜ ์ธ์Šคํ„ด์Šค์ธ rabbit ๊ฐ์ฒด์˜ ํ”„๋กœํ† ํƒ€์ž…์€ animal์ด ๋˜๋Š” ๊ฒƒ์ด๋‹ค.

์ด๋ ‡๊ฒŒ ํ•œ ๊ฐ์ฒด์˜ "์›ํ˜•"์„ ์„ค์ •ํ•ด์คŒ์— ๋”ฐ๋ผ ๊ฐ์ฒด์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์—์„œ ๋„๋ฆฌ ์‚ฌ์šฉ๋˜๋Š” "์ƒ์†" ๊ด€๊ณ„๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜๋Š” ๊ฒƒ์ด๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ class๋ผ๋Š” ์•„์ฃผ ์„คํƒ•๋ฐœ๋ฆฐ ๋ฌธ๋ฒ•์— ์ค‘๋…๋˜์–ด ์žˆ๋˜ ๋‚˜๋Š” extends, super๋“ฑ๊ณผ ๊ฐ™์€ ๋ฌธ๋ฒ•์— ๋Œ€์‘๋˜๋Š” prototype์˜ ๋ฌธ๋ฒ•์—์„œ ๋‚œ๊ด€์„ ๋งŽ์ด ๋งˆ์ฃผ์น˜๊ฒŒ ๋˜์—ˆ๋Š”๋ฐ...

ํ”„๋กœํ† ํƒ€์ž…์˜ ์ƒ์†

function Keyword(searchingInput, rollingKeywordHtml) {
   this.currIndex = 0; 
   // ...
   this.searchingInput = searchingInput;
   this.rollingKeywordHtml = rollingKeywordHtml;
}

Keyword.prototype = {
   constructor: Keyword,
   getTopten,
   createTemplate, 
   init,
};

function getTopten () {
   // ...
}

function createTemplate() {
   // ...
}

function init() {
   // ...
}

Keyword.prototype.fn = function () = {} ๋Œ€์‹ , Keyword.prototype = { fn }์„ ํ•ด๋„ ๊ฐ™์€ ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์˜จ๋‹ค.

๋‹จ ์ด๋•Œ๋Š” prototype ๊ฐ’์„ ๋‹ค๋ฅธ ๊ฐ์ฒด๋กœ ๋ฐ”๊พธ๋Š” ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์—, contructor๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š๊ฒŒ ๋˜๋Š” ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.

์ด๋ฅผ ์œ„ํ•ด ์•ˆ์— constructor = Keyword๋ฅผ ํ•ด์ค„ ์ˆ˜ ์žˆ๋‹ค.

์œ„ ๊ฐ์ฒด๋ฅผ ์ƒ์†๋ฐ›๋Š” ๋‹ค๋ฅธ ๊ฐ์ฒด๋“ค์€ ๊ทธ๋Ÿผ ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์„๊นŒ?

function RecommItems(keywordState, rollings) {
   const {searchingInput} = keywordState;
   const {rollingKeywordHtml} = rollings;

   Keyword.call(this, searchingInput, rollingKeywordHtml); // super()์™€ ๊ฐ™์€ ๊ฐœ๋…

   // ... 
}

RecommItems.prototype = Object.create(Keyword.prototype); // extends์™€ ๊ฐ™์€ ๊ฐœ๋…

RecommItems.prototype.init = function () {
   // ...
   // ์ƒ์†๋ฐ›์€ initํ•จ์ˆ˜ ์•ˆ์— RecommItem์ด ์ˆ˜ํ–‰ํ•  ๊ธฐ๋Šฅ ๊ตฌํ˜„
}

Keyword.call(this, arg1, arg2)๋ฅผ ํ•จ์œผ๋กœ์จ Keyword์˜ ํ”„๋กœํผํ‹ฐ๋“ค์„ RecommItem์˜ this๋กœ ๋งคํ•‘ํ•˜์—ฌ ๊ฐ€์ ธ์˜จ ํ›„ ์ฆ‰์‹œ ํ˜ธ์ถœํ•˜๋ฉด **๋งˆ์น˜ class์—์„œ super()**์„ ํ•œ๊ฒƒ๊ณผ ๊ฐ™์ด ๋ถ€๋ชจ์˜ ํ”„๋กœํผํ‹ฐ๋ฅผ ์ž์‹์—๊ฒŒ๋กœ ๊ฐ€์ ธ์˜ค๋Š” ๊ฒƒ๊ณผ ๊ฐ™๊ฒŒ ๋œ๋‹ค.

๋˜ํ•œ Object.create(Keyword.prototype)๋กœ Keyword์˜ ํ”„๋กœํ† ํƒ€์ž…์„ ๊ฐ€์ง€๋Š” ์ƒˆ ๊ฐ์ฒด๋ฅผ RecommItems์˜ ํ”„๋กœํ† ํƒ€์ž…์œผ๋กœ ์ง€์ •ํ•ด์คŒ์œผ๋กœ์จ class์—์„œ์˜ extends ์ฒ˜๋Ÿผ ์ƒ์† ๊ด€๊ณ„๋ฅผ ์—ฐ๊ฒฐ์‹œ์ผœ์ค€๋‹ค.

RecommItems์˜ prototype์€ Keyword์˜ prototype์ด ๋˜๊ณ  ๋‚œ ํ›„, RecommItems์—์„œ๋งŒ ์‚ฌ์šฉํ•˜๋Š” ํ•จ์ˆ˜๋“ค์„ ๊ตฌํ˜„ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด?

  • ์•„๊นŒ์ฒ˜๋Ÿผ RecommItems.prototype = {}์œผ๋กœ ํ•˜๋ฉด ํ”„๋กœํ† ํƒ€์ž…์„ ๋ฎ์–ด์”Œ์›Œ๋ฒ„๋ฆฌ๋Š” ๊ผด์ด ๋˜์–ด๋ฒ„๋ฆฐ๋‹ค.
  • ๊ธฐ์กด์˜ prototype ์ƒํƒœ์— ํ•จ์ˆ˜๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ  ์‹ถ์€ ๊ฒƒ์ด๋ฏ€๋กœ RecommItems.prototype.fn = function () {} ์ด๋Ÿฐ์‹์œผ๋กœ ๊ตฌํ˜„ํ•œ๋‹ค.

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๊ฐ์ฒด๋ฅผ ๋””๋ฒ„๊น… ํˆด๋กœ ์‚ดํŽด๋ณด๋ฉด __proto__๊ฐ€ ๋‚˜์˜จ๋‹ค. ์—ฌ๊ธฐ์— ์ด ๊ฐ์ฒด๊ฐ€ ์ƒ์†๋ฐ›๊ณ  ์žˆ๋Š” ๊ฐ์ฒด๋Š” ๋ฌด์—‡์ธ์ง€์— ๋Œ€ํ•ด ์•Œ ์ˆ˜ ์žˆ๋‹ค. (๋‹น์—ฐํžˆ ํ•ด๋‹น ๊ฐ์ฒด์˜ ํ”„๋กœํผํ‹ฐ๋„ ๋‚˜์˜จ๋‹ค.)

๋‚˜๋Š” ๊ฐœ์ธ์ ์œผ๋กœ ์ด ์ผ๋ จ์˜ ๊ณผ์ •์—์„œ ์™œ ์ด๋ฆ„์ด prototype์ธ์ง€์— ๋Œ€ํ•ด ๊ฐ์ด ์žกํžŒ ๊ฒƒ ๊ฐ™์•˜๋‹ค.

์ด ๊ฐ์ฒด์˜ ์›ํ˜•์€ ๋ญ์ง€? -> A ๊ฐ์ฒด -> ์ด ๊ฐ์ฒด์˜ ์›ํ˜•์€ ๋ญ์ง€? -> B ๊ฐ์ฒด -> ... -> ์ด ๊ฐ์ฒด์˜ ์›ํ˜•์€ ๋ญ์ง€? -> Object 

session-id์—์„œ ๋ถˆ๊ฑฐ์ง„ ์ด์Šˆ

์ด๋ฒˆ ๋ฏธ์…˜์—์„œ ๋‚˜๋Š” ์—ฐ๊ด€๊ฒ€์ƒ‰์–ด๋ฅผ amazon ๊ฒ€์ƒ‰ url๋กœ ๋ฐ›์•„์™”๋‹ค.

๊ทธ๋Ÿฐ๋ฐ, ์‚ฌ์šฉ์ž๊ฐ€ ๊ฒ€์ƒ‰์ฐฝ์— ์ž…๋ ฅํ•œ ๊ฐ’๊ณผ ๋งค์น˜๋˜๋Š” ์—ฐ๊ด€๊ฒ€์ƒ‰์–ด์˜ ์š”์†Œ๋ฅผ ํ•˜์ด๋ผ์ดํŠธ ํ•ด์ฃผ๋Š” ๋ถ€๋ถ„์—์„œ ์•Œ ์ˆ˜ ์—†๋Š” ์˜ค๋ฅ˜๋ฅผ ๋งˆ์ฃผ์น˜๊ฒŒ ๋˜์—ˆ๋‹ค.

๊ฒ€์ƒ‰์ฐฝ์— ์ž…๋ ฅ๋œ ๊ฐ’์ด ์˜์–ด๋ฉด ์•„๋ฌด ๋ฌธ์ œ๊ฐ€ ์—†๋Š”๋ฐ, ํ•œ๊ธ€์ด๋ฉด ๊ทธ ๊ฐ’์ด ์ œ๋Œ€๋กœ ์žกํžˆ์ง€ ์•Š๋Š” ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ๋‹ค.

const urls = {
  recommendedWords: (inputValue) => `https://completion.amazon.com/api/2017/suggestions?session-id=143-7282527-1203953&customer-id=&request-id=8RSH7H2971TF4M9DSSK8&page-type=Gateway&lop=en_US&site-variant=desktop&client-info=amazon-search-ui&mid=ATVPDKIKX0DER&alias=aps&b2b=0&fresh=0&ks=69&prefix=${inputValue}&event=onKeyPress&limit=11&fb=1&suggestion-type=KEYWORD&suggestion-type=WIDGET&_=1615167756813%27`,
 
}

async function request(urls, inputValue) {
  const response = await fetch(urls(inputValue));
  const data = await response.json();
  return data;
}

RecommItems.prototype.loadRelatedWords = async function (inputValue) {
  const data = await request(urls.recommendedWords, inputValue); // ๋ฐ์ดํ„ฐ ๋ฐ›์„ ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆผ
  const { suggestions } = data; // ์—ฐ๊ด€๊ฒ€์ƒ‰์–ด ๋ฐฐ์—ด
  const tempSuggestions = suggestions.map((item) => item.value); // ๊ฐ’์ด ์—ฐ๊ด€๊ฒ€์ƒ‰์–ด์ธ ์• ๋“ค๋งŒ ๋ฝ‘์•„๋ƒ„ 
  const tempRecommendations = // ํ…œํ”Œ๋ ˆ์ดํŒ…
    `<div class="recommended">` +
    set.reduce((acc, item, i) => {
      const highlightOnItem = item.replace(inputValue, `<span class="highlight">${inputValue}</span>`); // inputValue์™€ ๊ฐ™์€ ๋ถ€๋ถ„์€ spanํƒœ๊ทธ ๋จน์ธ ๋ฌธ์ž์—ด๋กœ ๋Œ€์ฒด
      acc += `<span class="recommended__item" data-id="${i}">${highlightOnItem}</span>`;
      return acc;
    }, ``) +
    `</div>`;
  this.recommWordsToggle.innerHTML = tempRecommendations;
  // ... 
};

์ด๋ ‡๊ฒŒ ํ–ˆ์„ ๋•Œ, (๋งŒ์•ฝ ์‚ฌ์šฉ์ž๊ฐ€ "์•„"๋ฅผ ์ž…๋ ฅํ•˜๋ฉด) ๋‚ด ์˜ˆ์ƒ์œผ๋กœ๋Š” ๊ฐ ์—ฐ๊ด€๊ฒ€์ƒ‰์–ด๋“ค์ด

<span class="recommended__item" data-id="1"><span class="highlight">์•„</span>๋งˆ์กด</span>

์ด๋Ÿฐ์‹์œผ๋กœ ๋ฐ”๋€Œ๋Š” ๊ฑธ ๊ธฐ๋Œ€ํ–ˆ๋Š”๋ฐ, ์ด์ƒํ•˜๊ฒŒ ํ•œ๊ธ€์—์„œ๋Š” ๋˜์—ˆ๋‹ค๊ฐ€ ์•ˆ๋˜์—ˆ๋‹ค๊ฐ€ ์ง€๋ง˜๋Œ€๋กœ(?)์˜€๋‹ค.

๊ทธ๋Ÿฐ๋ฐ, ๋†€๋ž๊ฒŒ๋„ url ์ฃผ์†Œ์—์„œ session-id=143-7282527-1203953 ๋ถ€๋ถ„์„ ์ง€์›Œ์คฌ๋”๋‹ˆ ํ•œ๊ธ€, ์˜์–ด ๋ชจ๋‘ ์ž˜ ๋ฐ”๋€Œ์—ˆ๋‹ค.

์ด ๋ฌธ์ œ์— ๋Œ€ํ•ด ๊ณ ๋ฏผํ•˜๋ฉฐ ํ•ด๊ฒฐํ•˜๋˜ ์ค‘, ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์›์ธ์„ ์ถ”์ •ํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค.

  • ํ•œ๊ธ€์€ ์ •๊ทœํ™”๋ฅผ ํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค.

data๊ฐ€ ๋“ค์–ด์˜ค๋Š” ๋ถ€๋ถ„์—์„œ ๋””๋ฒ„๊น…์„ ํ•ด๋ณด๋‹ˆ, suggestions[0].value[0]์„ ํ–ˆ์„ ๋•Œ "์•„" ๊ฐ€ ์•„๋‹ˆ๋ผ "ใ…‡"๊ฐ€ ์ถœ๋ ฅ๋˜์—ˆ๋‹ค.

์ฆ‰, ํ•œ๊ธ€์€ ์ž์Œ๊ณผ ๋ชจ์Œ์ด ์กฐํ•ฉ๋œ ๋ฌธ์ž๊ฐ€ ํ•œ ์Œ์ ˆ์ด๋ผ ๊ฐœ๋ณ„ ์•ŒํŒŒ๋ฒณ์˜ ๋‚˜์—ด๋กœ ์ด๋ฃจ์–ด์ง„ ์˜์–ด์™€ ๋‹ฌ๋ผ replace๊ฐ€ ๋จนํžˆ์ง€ ์•Š์•˜๋˜ ๊ฒƒ์ด๋‹ค. ("์•„" !== "ใ…‡")

์ด๋ฅผ ์œ„ํ•ด ๊ฐ๊ฐ์˜ ๋ฐ์ดํ„ฐ ๊ฐ’์— String.prototype.normalize()๋กœ ๋ชจ๋‘ ์ •๊ทœํ™” ์‹œ์ผœ์ฃผ์—ˆ๋‹ค.

RecommItems.prototype.loadRelatedWords = async function (inputValue) {
  const data = await request(urls.recommendedWords, inputValue); 
  const { suggestions } = data; 
  const tempSuggestions = suggestions.map((item) => item.value.normalize("NFC")); // ์ •๊ทœํ˜• ์ •์ค€ ๊ฒฐํ•ฉ (NFC), ์ž์†Œ๋ถ„๋ฆฌ ๋˜์—ˆ๋˜ ํ•œ๊ธ€์„ ๊ฒฐํ•ฉํ•จ
  const tempRecommendations = // ํ…œํ”Œ๋ ˆ์ดํŒ…
  // ... 
}

์ด๋ ‡๊ฒŒ ํ–ˆ๋”๋‹ˆ ํ•˜์ด๋ผ์ดํŒ…์ด ์›ํ•˜๋˜ ๋Œ€๋กœ ์ž˜ ๋จน์—ˆ๋‹ค!

์ด๋Ÿฌํ•œ ๊ณผ์ •์„ ํ†ตํ•ด ๋‚ด๊ฐ€ ๋Š๋‚€ ์ž ์ •์ ์ธ ๊ฒฐ๋ก ์€, ์•„๋งˆ์กด url์— ์žˆ๋˜ session-id=143-7282527-1203953๋กœ ์ธํ•ด ๊ธฐ๋ณธ ์„ค์ •๊ฐ’์ด "NFD"๋กœ ๋˜์–ด์žˆ์—ˆ๊ณ , ๊ณต๊ต๋กญ๊ฒŒ๋„ ์ด๊ฑธ ์ œ๊ฑฐํ•จ์œผ๋กœ์จ ์ž์†Œ๋ถ„๋ฆฌ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š์•˜๋˜ ๊ฒƒ์ด ์•„๋‹๊นŒ ์‹ถ๋‹ค.

โš ๏ธ **GitHub.com Fallback** โš ๏ธ