** πŸ“Œ 9단계 문제 λ‹€μ‹œ 보기**

100개의 μƒν’ˆ 정보λ₯Ό Ajax둜 λΆˆλŸ¬μ˜€λŠ”λ°

μ‚¬μš©μžκ°€ λΉ λ₯΄κ²Œ μŠ€ν¬λ‘€ν•˜λ©΄μ„œ 계속 μš”μ²­μ„ 보낸닀.

μ„œλ²„λŠ” 처리 κ°€λŠ₯ν•œ 횟수(TPS)κ°€ μ œν•œλ˜μ–΄ μžˆλ‹€.


λ‹Ήμ‹ μ˜ λͺ©ν‘œλŠ”?

  1. βœ… μ„œλ²„ κ³ΌλΆ€ν•˜ λ°©μ§€
  2. βœ… 쀑볡 μš”μ²­ 제거
  3. βœ… UI 응닡성 μœ μ§€

βœ… ν•΄κ²° μ „λž΅ ν•œλˆˆμ— 보기

μ „λž΅ λͺ©μ 
Debounce λ„ˆλ¬΄ 자주 μš”μ²­ν•˜μ§€ μ•Šλ„λ‘ λ”œλ ˆμ΄ 쀌
μš”μ²­ 큐 μˆœμ„œλŒ€λ‘œ μ°¨λ‘€μ°¨λ‘€ μš”μ²­ν•˜κ²Œ 함
응닡 캐싱 이미 받은 λ°μ΄ν„°λŠ” λ‹€μ‹œ μš”μ²­ν•˜μ§€ μ•ŠμŒ
μš”μ²­ μ·¨μ†Œ 이전에 λ‚ λ¦° μš”μ²­μ΄ 아직 μ•ˆ 끝났닀면 μ·¨μ†Œν•¨

βœ… 1. Debounce둜 μš”μ²­ λΉˆλ„ 쑰절


πŸ“– κ°œλ…

μ‚¬μš©μžκ°€ λΉ λ₯΄κ²Œ μŠ€ν¬λ‘€ν•΄λ„ 0.3초 λ™μ•ˆ λ©ˆμΆ”λ©΄ κ·Έλ•Œ 1번만 μš”μ²­


πŸ‘¦πŸ» μ‰¬μš΄ μ„€λͺ…

β€œμ—„λ§ˆ~ μ—„λ§ˆ~ μ—„λ§ˆ~ μ—„λ§ˆ!”

β†’ 0.3초 λ™μ•ˆ μ•ˆ λΆ€λ₯΄λ©΄ κ·Έλ•Œ 말 λ“€μ–΄μ£ΌλŠ” 것 🧏


βœ… μ½”λ“œ μ˜ˆμ‹œ

function debounce(fn, delay) {
  let timer;
  return function (...args) {
    clearTimeout(timer);
    timer = setTimeout(() => fn.apply(this, args), delay);
  };
}

const requestItems = debounce(() => {
  fetchItems(); // Ajax 호좜
}, 300);

βœ… μ‚¬μš©μžκ°€ μŠ€ν¬λ‘€ν•  λ•Œλ§ˆλ‹€ ν˜ΈμΆœν•΄λ„ 300ms λ©ˆμΆ”λ©΄ 1번만 μ‹€ν–‰


βœ… 2. μš”μ²­ 큐둜 κ³ΌλΆ€ν•˜ λ°©μ§€


πŸ“– κ°œλ…

μ„œλ²„λŠ” ν•œ λ²ˆμ— 많이 λͺ» λ°›μœΌλ‹ˆ, μš”μ²­μ„ 쀄 μ„Έμ›Œμ„œ ν•˜λ‚˜μ”© 보내야 함


πŸ‘¦πŸ» μ‰¬μš΄ μ„€λͺ…

햄버거 κ°€κ²Œμ—μ„œ ν•œκΊΌλ²ˆμ— 50λͺ…이 λͺ°λ¦¬λ©΄ μ£Όλ¬Έ λͺ» λ°›μŒ

β†’ 쀄 μ„Έμ›Œμ„œ 1λͺ…μ”© μ²˜λ¦¬ν•˜λ©΄ 문제 μ—†μŒ πŸ”


βœ… μ½”λ“œ μ˜ˆμ‹œ

class AjaxQueue {
  constructor() {
    this.queue = [];
    this.running = false;
  }

  enqueue(task) {
    this.queue.push(task);
    this.runNext();
  }

  async runNext() {
    if (this.running || this.queue.length === 0) return;
    this.running = true;
    const task = this.queue.shift();
    await task();
    this.running = false;
    this.runNext();
  }
}

const queue = new AjaxQueue();
queue.enqueue(() => fetch("/api/products?page=1"));

βœ… μš”μ²­μ€ ν•˜λ‚˜ 끝날 λ•ŒκΉŒμ§€ λ‹€μŒ μš”μ²­ λŒ€κΈ° β†’ TPS 보호!


βœ… 3. 응닡 μΊμ‹±μœΌλ‘œ 쀑볡 제거


πŸ“– κ°œλ…

이미 λ°›μ•„μ˜¨ νŽ˜μ΄μ§€λŠ” λ‹€μ‹œ μš”μ²­ν•˜μ§€ μ•Šκ³  μΊμ‹œμ— μ €μž₯ν•œ κ±Έ κ·ΈλŒ€λ‘œ λ³΄μ—¬μ€Œ


πŸ‘¦πŸ» μ‰¬μš΄ μ„€λͺ…

λ§ˆνŠΈμ—μ„œ 같은 물건 또 μ‚¬λŸ¬ κ°€λ €λŠ”λ°

β€œμ–΄? 집에 μžˆλ„€?” β†’ λ‹€μ‹œ μ•ˆ 가도 됨 🏠


βœ… μ½”λ“œ μ˜ˆμ‹œ

const cache = {};

function getProducts(page) {
  if (cache[page]) return Promise.resolve(cache[page]);
  return fetch(`/api/products?page=${page}`)
    .then(res => res.json())
    .then(data => {
      cache[page] = data;
      return data;
    });
}

βœ… λ„€νŠΈμ›Œν¬ λ‚­λΉ„ μ—†μŒ

βœ… μ„œλ²„ λΆ€λ‹΄ 절감

βœ… μ‚¬μš©μž 체감 속도↑


βœ… 4. μš”μ²­ μ·¨μ†Œλ‘œ 쀑볡 응닡 λ°©μ§€


πŸ“– κ°œλ…

λΉ λ₯΄κ²Œ 연속 μš”μ²­ν•˜λ©΄ 이전 μš”μ²­μ΄ λλ‚˜κΈ° 전에 μƒˆλ‘œμš΄ μš”μ²­μ„ 보내야 함

β†’ μ΄λ•Œ 이전 μš”μ²­μ€ abort() 처리


πŸ‘¦πŸ» μ‰¬μš΄ μ„€λͺ…

μ—„λ§ˆν•œν…Œ β€œν–„λ²„κ±° 사와!” ν–ˆλŠ”λ°

1초 뒀에 β€œμ•„λƒ 떑볢이!” β†’ ν–„λ²„κ±°λŠ” μ·¨μ†Œν•΄μ•Ό 함


βœ… μ½”λ“œ μ˜ˆμ‹œ

let controller;

function getPage(page) {
  if (controller) controller.abort(); // 이전 μš”μ²­ μ·¨μ†Œ
  controller = new AbortController();

  return fetch(`/api/products?page=${page}`, {
    signal: controller.signal
  })
    .then(res => res.json());
}

βœ… UIμ—μ„œ λ§ˆμ§€λ§‰ μš”μ²­λ§Œ μ‚΄μ•„λ‚¨κ²Œ λ§Œλ“€ 수 있음

βœ… μ„œλ²„λ„ 덜 νž˜λ“¦


βœ… μ΅œμ’… μ „λž΅ μš”μ•½ (πŸ’Ž 싀무 μ μš©ν˜•)

🧠 μ‚¬μš©μžκ°€ λΉ λ₯΄κ²Œ 슀크둀 β†’
  1. Debounce둜 μš”μ²­ λΉˆλ„ μ œμ–΄ β†’
  2. 이미 λ³Έ νŽ˜μ΄μ§€λŠ” μΊμ‹œλ‘œ λ°˜ν™˜ β†’
  3. μƒˆ μš”μ²­μ€ Ajax Queue둜 쀄 μ„Έμš°κΈ° β†’
  4. 쀑간에 μ·¨μ†Œλ˜λ©΄ AbortController둜 이전 μš”μ²­ μ·¨μ†Œ 

βœ… λ©΄μ ‘ 질문 μ˜ˆμ‹œ + μ •λ‹΅ ꡬ쑰


❓ Q. μƒν’ˆ λͺ©λ‘μ„ λΉ λ₯΄κ²Œ μŠ€ν¬λ‘€ν•˜λ©΄μ„œ Ajax μš”μ²­μ΄ 반볡될 λ•Œ,

μ„œλ²„ κ³ΌλΆ€ν•˜ 없이 효율적으둜 응닡성과 μ„±λŠ₯을 μœ μ§€ν•˜λ €λ©΄ μ–΄λ–»κ²Œ ν•˜μ‹œκ² μŠ΅λ‹ˆκΉŒ?

βœ… A.


βœ… 전체 μš”μ•½ μΉ΄λ“œ

기술 λͺ©μ  μ„€λͺ…
Debounce λΉˆλ„ μ œν•œ 연속 μž…λ ₯을 λ¬Άμ–΄μ„œ ν•œ 번만 μ‹€ν–‰
Ajax Queue κ³ΌλΆ€ν•˜ λ°©μ§€ μš”μ²­μ„ μˆœμ„œλŒ€λ‘œ 1κ°œμ”© 처리
응닡 캐싱 쀑볡 제거 이미 받은 λ°μ΄ν„°λŠ” μž¬μ‚¬μš©
μš”μ²­ μ·¨μ†Œ κΌ¬μž„ λ°©μ§€ 쀑간 μš”μ²­μ€ Abort둜 제거