** ๐Ÿ“Œ 4-1๋‹จ๊ณ„: Ajax ์ƒํƒœ ์ผ๊ด€์„ฑ ๋ฌธ์ œ์™€ ์š”์ฒญ ์ทจ์†Œ ์ฒ˜๋ฆฌ**


โ— ์—ฌ๋Ÿฌ ๊ฐœ์˜ Ajax ์š”์ฒญ์ด ๋™์‹œ์— ์ฒ˜๋ฆฌ๋  ๋•Œ ๋ฐœ์ƒํ•˜๋Š” ์ˆœ์„œ ๊ผฌ์ž„ ๋ฌธ์ œ,

๐Ÿ‘‰ ๊ทธ๋ฆฌ๊ณ  ๊ทธ๊ฑธ ์ทจ์†Œํ•˜๋Š” ๋ฐฉ๋ฒ•๊นŒ์ง€ ์™„๋ฒฝํ•˜๊ฒŒ ๋งˆ์Šคํ„ฐํ•˜๋Š” ๋‹จ๊ณ„์ž…๋‹ˆ๋‹ค.


โœ… 1. ์ƒํƒœ ์ผ๊ด€์„ฑ์ด ๋ญ์•ผ?

โ— ํ™”๋ฉด์— ๋ณด์—ฌ์ง€๋Š” ๋‚ด์šฉ์ด ์‹ค์ œ ์„œ๋ฒ„ ์ƒํƒœ์™€ ์ •ํ™•ํžˆ ์ผ์น˜ํ•˜๋Š” ๊ฒƒ


๐Ÿ‘ฆ๐Ÿป ์‰ฌ์šด ์˜ˆ

1. ๊ฒ€์ƒ‰์ฐฝ์— "apple" ์ž…๋ ฅ โ†’ Ajax ์š”์ฒญ 1 ๋ฐœ์‚ฌ
2. ๋ฐ”๋กœ "banana" ์ž…๋ ฅ โ†’ Ajax ์š”์ฒญ 2 ๋ฐœ์‚ฌ

๐Ÿšจ ๊ทธ๋Ÿฐ๋ฐโ€ฆ

๐Ÿ’ฅ ๊ฒ€์ƒ‰์ฐฝ์—๋Š” โ€œbananaโ€๋ผ๊ณ  ์ผ๋Š”๋ฐ,

๊ฒฐ๊ณผ๋Š” apple์ด ๋‚˜์™€๋ฒ„๋ฆฌ๋Š” ๋ฌธ์ œ ๋ฐœ์ƒ!

โ†’ ์ด๊ฑธ ์‘๋‹ต ์ˆœ์„œ ์—ญ์ „ ๋ฌธ์ œ (Race Condition)๋ผ๊ณ  ํ•ด์š”.


โœ… 2. Race Condition (๋ ˆ์ด์Šค ์ปจ๋””์…˜)

๐Ÿ“ฆ ์ •์˜

์—ฌ๋Ÿฌ ์š”์ฒญ์ด ๋™์‹œ์— ์ฒ˜๋ฆฌ๋  ๋•Œ, ๋„์ฐฉ ์ˆœ์„œ๊ฐ€ ๊ผฌ์ด๋ฉด์„œ ๊ฒฐ๊ณผ๊ฐ€ ์—‰ํ‚ค๋Š” ํ˜„์ƒ


๐Ÿง  ์™œ ๋ฐœ์ƒํ•˜๋‚˜์š”?


โŒ ์ž˜๋ชป๋œ ์˜ˆ์‹œ ์ฝ”๋“œ

input.addEventListener("input", e => {
  fetch(`/search?q=${e.target.value}`)
    .then(res => res.text())
    .then(html => {
      resultBox.innerHTML = html;
    });
});

โ†’ ๋น ๋ฅด๊ฒŒ ํƒ€์ดํ•‘ํ•˜๋ฉด ์˜ค๋ž˜๋œ ์‘๋‹ต์ด ๋‚˜์ค‘์— ๋„์ฐฉํ•ด ๊ฒฐ๊ณผ๊ฐ€ ๋’ค๋ฐ”๋€œ


โœ… 3. ํ•ด๊ฒฐ ์ „๋žต โ‘ : ์š”์ฒญ ์ทจ์†Œ (AbortController)

๐Ÿ“ฆ AbortController๋ž€?

JavaScript์—์„œ ํ˜„์žฌ ์ง„ํ–‰ ์ค‘์ธ fetch ์š”์ฒญ์„ ์ค‘๋‹จํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” API


โœ… ์˜ˆ์‹œ ์ฝ”๋“œ

let controller;

function search(keyword) {
  if (controller) controller.abort(); // ์ด์ „ ์š”์ฒญ ์ค‘๋‹จ
  controller = new AbortController();

  fetch(`/search?q=${keyword}`, { signal: controller.signal })
    .then(res => res.text())
    .then(data => {
      resultBox.innerHTML = data;
    })
    .catch(err => {
      if (err.name === "AbortError") {
        console.log("์š”์ฒญ์ด ์ค‘๋‹จ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.");
      }
    });
}

โœ… 4. ํ•ด๊ฒฐ ์ „๋žต โ‘ก: ๊ฐ€์žฅ ๋งˆ์ง€๋ง‰ ์š”์ฒญ๋งŒ ๋ฐ˜์˜

๐Ÿ“ฆ ์ „์—ญ ์š”์ฒญ ID ๋ฐฉ์‹

let latestRequestId = 0;

function search(keyword) {
  const currentId = ++latestRequestId;

  fetch(`/search?q=${keyword}`)
    .then(res => res.text())
    .then(data => {
      if (currentId === latestRequestId) {
        resultBox.innerHTML = data; // ์ตœ์‹  ์š”์ฒญ๋งŒ ๋ฐ˜์˜
      }
    });
}

๐Ÿ‘‰ ์˜ค๋ž˜๋œ ์š”์ฒญ์ด ์‘๋‹ตํ•˜๋”๋ผ๋„, ID๊ฐ€ ๋‹ค๋ฅด๋ฉด ๋ฌด์‹œํ•จ

โ†’ โ— ์ด ๋ฐฉ์‹์€ โ€œ์ทจ์†Œโ€๋Š” ์•ˆ ํ•˜์ง€๋งŒ โ€œ๊ฒฐ๊ณผ๋ฅผ ๋ฌด์‹œโ€ํ•ด์„œ ์•ˆ์ •์ ์ž„


โœ… 5. Axios CancelToken (Axios 0.x)

Axios์—์„œ๋Š” ๊ณผ๊ฑฐ์— CancelToken์„ ์‚ฌ์šฉํ•ด ์š”์ฒญ์„ ์ค‘๋‹จํ–ˆ์–ด์š” (ํ˜„์žฌ๋Š” AbortController ๊ถŒ์žฅ)


์˜ˆ์‹œ ์ฝ”๋“œ

let cancel;

axios.get('/search', {
  cancelToken: new axios.CancelToken(function executor(c) {
    cancel = c; // ์ทจ์†Œ ํ•จ์ˆ˜ ๋“ฑ๋ก
  })
});

// ์ทจ์†Œํ•˜๊ธฐ
if (cancel) cancel("์š”์ฒญ ์ทจ์†Œ๋จ");

๐Ÿ’ก ํ˜„์žฌ๋Š” fetch์˜ AbortController๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋” ํ‘œ์ค€์ด์—์š”.


โœ… 6. ๋ฉด์ ‘ ์งˆ๋ฌธ ์˜ˆ์‹œ + ํ•ด์„ค

โ“ Q. ๋น ๋ฅด๊ฒŒ ๋ฐ˜๋ณต๋˜๋Š” Ajax ์š”์ฒญ์—์„œ ์‘๋‹ต์ด ๊ผฌ์ด๋Š” ๋ฌธ์ œ๋ฅผ ๋ฐฉ์ง€ํ•˜๋ ค๋ฉด ์–ด๋–ป๊ฒŒ ์ฒ˜๋ฆฌํ•˜์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ?

โœ… A.


โœ… ์ „์ฒด ์š”์•ฝ ์นด๋“œ

๊ฐœ๋… ์„ค๋ช…
์ƒํƒœ ์ผ๊ด€์„ฑ ํ™”๋ฉด๊ณผ ์„œ๋ฒ„ ์ƒํƒœ๊ฐ€ ์ •ํ™•ํžˆ ์ผ์น˜ํ•˜๋Š” ๊ฒƒ
Race Condition ์˜ค๋ž˜๋œ ์š”์ฒญ์ด ๋‚˜์ค‘์— ๋„์ฐฉํ•ด์„œ ๊ฒฐ๊ณผ๋ฅผ ๋ฎ์–ด์”€
AbortController ์ง„ํ–‰ ์ค‘์ธ fetch ์š”์ฒญ์„ ์ทจ์†Œํ•  ์ˆ˜ ์žˆ์Œ
์š”์ฒญ ID ์ถ”์  ์ตœ์‹  ์š”์ฒญ๋งŒ ๋ฐ˜์˜ํ•˜๊ณ  ์ด์ „ ๊ฒฐ๊ณผ๋Š” ๋ฌด์‹œํ•จ
Axios CancelToken Axios ์š”์ฒญ์„ ์ทจ์†Œํ•˜๋Š” ๋ฐฉ์‹ (์ด์ „ ๋ฐฉ์‹)

โœ… ์‹œ๋‚˜๋ฆฌ์˜ค ๋น„๊ต ์ •๋ฆฌ

์ƒํ™ฉ ํ•ด๊ฒฐ ์ „๋žต
๋น ๋ฅธ ์ž…๋ ฅ ์ค‘ Ajax ์ค‘๋ณต ๋ฐœ์ƒ Debounce + AbortController
์‘๋‹ต ์ˆœ์„œ๊ฐ€ ๊ผฌ์—ฌ ํ™”๋ฉด์ด ์—‰ํ‚ด ์š”์ฒญ ID ๋น„๊ต ๋˜๋Š” ์‘๋‹ต ๋ฌด์‹œ
์‹ค์‹œ๊ฐ„ ๊ฒ€์ƒ‰/ํ•„ํ„ฐ๋ง ๋งˆ์ง€๋ง‰ ์š”์ฒญ๋งŒ ๋ฐ˜์˜ or ์ด์ „ ์š”์ฒญ ์ทจ์†Œ

โœ… 4-2๋‹จ๊ณ„: ๋ณ‘๋ ฌ Ajax ์ฒ˜๋ฆฌ์™€ Promise ๋ณ‘๋ ฌ์„ฑ ์™„์ „์ •๋ณต

โ€œ๋™์‹œ์— ์—ฌ๋Ÿฌ Ajax๋ฅผ ๋ณด๋‚ด์„œ ๋” ๋น ๋ฅด๊ฒŒ ์ฒ˜๋ฆฌํ•˜๋ ค๋ฉด?โ€

โ†’ Promise์™€ async/await๋กœ ๋˜‘๋˜‘ํ•˜๊ฒŒ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์–ด์š”!


โœ… 1. ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋Š” โ€œ๋‹จ์ผ ์“ฐ๋ ˆ๋“œโ€ ์–ธ์–ด์ž…๋‹ˆ๋‹ค


๐Ÿ“ฆ ์‰ฝ๊ฒŒ ๋งํ•˜๋ฉด:

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋Š” ํ•œ ๋ฒˆ์— ํ•œ ์ค„์”ฉ๋งŒ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์–ด์š”

(๐Ÿ“ ํ•œ ์ค„ ์š”๋ฆฌ์‚ฌ๊ฐ€ ํ•œ ๋ฒˆ์— ํ•˜๋‚˜์”ฉ๋งŒ ์š”๋ฆฌํ•˜๋Š” ๋А๋‚Œ)

ํ•˜์ง€๋งŒ Ajax ๊ฐ™์€ ๋„คํŠธ์›Œํฌ ์š”์ฒญ์€ ๋น„๋™๊ธฐ๋‹ˆ๊นŒ

โ€œ์ผ๋‹จ ๋ณด๋‚ด๊ณ , ๋‚˜์ค‘์— ๊ฒฐ๊ณผ ์˜ค๋ฉด ์ฒ˜๋ฆฌโ€๋ฅผ ํ•  ์ˆ˜ ์žˆ์–ด์š”.

โ†’ ์ด๊ฑธ ๋™์‹œ์„ฑ(Concurrency)์ด๋ผ๊ณ  ํ•ด์š”!


โœ… 2. ์—ฌ๋Ÿฌ Ajax๋ฅผ ๋™์‹œ์— ๋ณด๋‚ด๊ณ  ์‹ถ๋‹ค๋ฉด?


โŒ ์ž˜๋ชป๋œ ๋ฐฉ๋ฒ•: ์ˆœ์ฐจ ์ฒ˜๋ฆฌ

const res1 = await fetch('/user');
const res2 = await fetch('/posts');
const res3 = await fetch('/comments');

์ด๊ฑด 1๊ฐœ๊ฐ€ ๋๋‚˜์•ผ ๋‹ค์Œ ์š”์ฒญ ์‹œ์ž‘

โ†’ ์ด 3์ดˆ ๊ฑธ๋ฆด ์ˆ˜ ์žˆ์Œ (๊ฐ 1์ดˆ ์†Œ์š”๋ผ๊ณ  ๊ฐ€์ • ์‹œ)


โœ… ์˜ฌ๋ฐ”๋ฅธ ๋ฐฉ๋ฒ•: ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ (Promise.all)


๐Ÿ“ฆ Promise.all์ด๋ž€?

์—ฌ๋Ÿฌ ๊ฐœ์˜ ๋น„๋™๊ธฐ ์ž‘์—…์„ ํ•œ ๋ฒˆ์— ๋ณ‘๋ ฌ๋กœ ์‹œ์ž‘ํ•ด์„œ,

โ†’ ๋ชจ๋‘ ์™„๋ฃŒ๋˜๋ฉด ๊ฒฐ๊ณผ๋ฅผ ํ•œ๊บผ๋ฒˆ์— ๋ฐ›๋Š” ๋ฐฉ์‹


๐Ÿ‘ฆ๐Ÿป ์‰ฌ์šด ์„ค๋ช…

3๊ฐœ์˜ ํ–„๋ฒ„๊ฑฐ ์ฃผ๋ฌธ์„ ํ•œ ๋ช…์”ฉ ๋ฐ›๋Š” ๊ฒŒ ์•„๋‹ˆ๋ผ,

โ†’ 3๊ฐœ ๋™์‹œ์— ๋งŒ๋“ค์–ด์„œ ํ•œ ๋ฒˆ์— ๋ฐ›๋Š” ๋А๋‚Œ!


โœ… ์˜ˆ์‹œ ์ฝ”๋“œ

const [user, posts, comments] = await Promise.all([
  fetch('/user').then(r => r.json()),
  fetch('/posts').then(r => r.json()),
  fetch('/comments').then(r => r.json())
]);

console.log(user, posts, comments);

โœ… 3. Promise.race


๐Ÿ“ฆ race๋ž€?

์—ฌ๋Ÿฌ ์ž‘์—… ์ค‘ ๊ฐ€์žฅ ๋จผ์ € ๋๋‚˜๋Š” ๊ฒƒ ํ•˜๋‚˜๋งŒ ๋ฐ˜ํ™˜ํ•˜๊ณ  ๋‚˜๋จธ์ง€๋Š” ๋ฌด์‹œ!


๐Ÿ‘ฆ๐Ÿป ์‰ฌ์šด ์„ค๋ช…

๋‹ฌ๋ฆฌ๊ธฐ ๊ฒฝ์ฃผ์ฒ˜๋Ÿผ, ๊ฐ€์žฅ ๋จผ์ € ๋„์ฐฉํ•œ ๊ฒฐ๊ณผ๋งŒ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ์‹


โœ… ์˜ˆ์‹œ ์ฝ”๋“œ

const fastest = await Promise.race([
  fetch('/mirror1'),
  fetch('/mirror2'),
  fetch('/mirror3')
]);

๐Ÿ“Œ ์—ฌ๋Ÿฌ ์„œ๋ฒ„ ์ค‘ ๊ฐ€์žฅ ๋น ๋ฅธ ์„œ๋ฒ„์˜ ์‘๋‹ต๋งŒ ์‚ฌ์šฉ

โ†’ CDN, ๋ฐฑ์—… ์„œ๋ฒ„, ์†๋„ ์šฐ์„  ์ „๋žต์— ์œ ์šฉ


โœ… 4. async/await์™€ ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ ํ•จ๊ป˜ ์“ฐ๊ธฐ


๐Ÿ“ฆ async/await๋ž€?

Promise๋ฅผ ๋” ์ฝ๊ธฐ ์‰ฌ์šด ์ฝ”๋“œ๋กœ ๋ฐ”๊ฟ”์ฃผ๋Š” ๋ฌธ๋ฒ•


์˜ˆ์‹œ

async function getAll() {
  const [a, b] = await Promise.all([
    fetch('/a').then(res => res.json()),
    fetch('/b').then(res => res.json())
  ]);
  return a + b;
}

โœ… 5. ์‹ค๋ฌด์—์„œ์˜ ๋™์‹œ์„ฑ ์ œ์–ด


๊ธฐ์ˆ  ์„ค๋ช…
Promise.all() ๋ชจ๋“  ์ž‘์—…์ด ๋๋‚  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆผ
Promise.race() ๊ฐ€์žฅ ๋น ๋ฅธ ๊ฒฐ๊ณผ๋งŒ ์‚ฌ์šฉ
Promise.any() ๊ฐ€์žฅ ๋จผ์ € ์„ฑ๊ณตํ•œ ๊ฒƒ๋งŒ ์‚ฌ์šฉ (์‹คํŒจ๋Š” ๋ฌด์‹œ)
async/await ๋น„๋™๊ธฐ ์ฝ”๋“œ๋ฅผ ์ˆœ์ฐจ์ฒ˜๋Ÿผ ์ž‘์„ฑ ๊ฐ€๋Šฅ
AbortController ์ค‘๊ฐ„์— ์š”์ฒญ์„ ์ทจ์†Œํ•  ์ˆ˜ ์žˆ์Œ
์š”์ฒญ ํ ์ˆœ์„œ๋ฅผ ์ •ํ•ด์„œ ์š”์ฒญ์„ ๊ด€๋ฆฌ (์ค‘์ฒฉ ๋ฐฉ์ง€)

โœ… ๋ฉด์ ‘ ์งˆ๋ฌธ ์˜ˆ์‹œ + ํ•ด์„ค

โ“ Q. ์—ฌ๋Ÿฌ Ajax๋ฅผ ๋ณ‘๋ ฌ๋กœ ์ฒ˜๋ฆฌํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. ์–ด๋–ป๊ฒŒ ํ•˜์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ?

โœ… A.


โœ… ์ „์ฒด ์š”์•ฝ ์นด๋“œ

๊ธฐ์ˆ  ์„ค๋ช… ์‚ฌ์šฉ ์ƒํ™ฉ
Promise.all ๋ชจ๋‘ ์„ฑ๊ณตํ•ด์•ผ ๊ฒฐ๊ณผ ๋ฐ˜ํ™˜ ๋ณ‘๋ ฌ ๋กœ๋”ฉ
Promise.race ๊ฐ€์žฅ ๋น ๋ฅธ ๊ฒฐ๊ณผ๋งŒ ์‚ฌ์šฉ ์„œ๋ฒ„ ์†๋„ ์šฐ์„ 
async/await Promise๋ฅผ ๊น”๋”ํ•˜๊ฒŒ ํ‘œํ˜„ ๋Œ€๋ถ€๋ถ„์˜ ์‹ค๋ฌด ์ฝ”๋“œ
์š”์ฒญ ํ ์ˆœ์„œ๋Œ€๋กœ Ajax ์ฒ˜๋ฆฌ ์ค‘์ฒฉ ๋ฐฉ์ง€, ์†๋„ ์กฐ์ ˆ
AbortController ์š”์ฒญ ์ทจ์†Œ ๊ธฐ๋Šฅ ๋น ๋ฅธ ์ž…๋ ฅ ์ทจ์†Œ, ์ค‘๋ณต ์ œ๊ฑฐ

โœ… ์‹œ๋‚˜๋ฆฌ์˜ค ๋น„๊ต

์ƒํ™ฉ ์‚ฌ์šฉ ๊ธฐ์ˆ 
์‚ฌ์šฉ์ž ์ •๋ณด + ๊ธ€ + ๋Œ“๊ธ€ โ†’ ๋ชจ๋‘ ํ•„์š” Promise.all()
์—ฌ๋Ÿฌ ์„œ๋ฒ„ ์ค‘ ๋น ๋ฅธ ๊ฒƒ๋งŒ ์‚ฌ์šฉ Promise.race()
๊ฒ€์ƒ‰ ์ค‘ ๋น ๋ฅด๊ฒŒ ์ด์ „ ์š”์ฒญ ์ทจ์†Œ AbortController
์ฝ”๋“œ ๊ฐ€๋…์„ฑ ํ–ฅ์ƒ async/await

โœ… 4-3๋‹จ๊ณ„: Ajax ์š”์ฒญ ํ ์„ค๊ณ„์™€ ๋ฐฑ์˜คํ”„ ์ „๋žต ์™„์ „์ •๋ณต

๐Ÿ“Š ์š”์ฒญ์ด ๋„ˆ๋ฌด ๋งŽ์„ ๋•Œ, ์„œ๋ฒ„๊ฐ€ ๋ฉˆ์ถ”์ง€ ์•Š๊ฒŒ ํ•˜๊ณ ,

์š”์ฒญ์„ ์ˆœ์„œ๋Œ€๋กœ, ๋˜‘๋˜‘ํ•˜๊ฒŒ, ํšจ์œจ์ ์œผ๋กœ ๋ณด๋‚ด๋Š” ์„ค๊ณ„๋ฅผ ๋ฐฐ์›๋‹ˆ๋‹ค.


โœ… 1. ์š”์ฒญ ํ(Request Queue)๋ž€?

์—ฌ๋Ÿฌ ๊ฐœ์˜ Ajax ์š”์ฒญ์ด ์žˆ์„ ๋•Œ,

ํ•œ ๋ฒˆ์— ๋‹ค ๋ณด๋‚ด์ง€ ์•Š๊ณ  ์ค„์„ ์„ธ์›Œ์„œ ์ˆœ์„œ๋Œ€๋กœ ํ•˜๋‚˜์”ฉ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ตฌ์กฐ


๐Ÿ‘ฆ๐Ÿป ์‰ฌ์šด ์„ค๋ช…

ํ–„๋ฒ„๊ฑฐ ๊ฐ€๊ฒŒ์—์„œ ์†๋‹˜์ด ๋งŽ์„ ๋• ๋ฒˆํ˜ธํ‘œ๋ฅผ ๋ฝ‘๊ณ  ์ค„ ์„œ์„œ ์ฐจ๋ก€๋Œ€๋กœ ์ฃผ๋ฌธํ•˜์ฃ ?

โ†’ ๋ฐ”๋กœ ์ด๊ฒŒ ์š”์ฒญ ํ์ž…๋‹ˆ๋‹ค!


๐Ÿง  ์™œ ํ•„์š”ํ•œ๊ฐ€์š”?

์ƒํ™ฉ ๋ฌธ์ œ
Ajax ์š”์ฒญ์ด ๋™์‹œ์— 50๊ฐœ ๋ฐœ์ƒ ์„œ๋ฒ„ ๊ณผ๋ถ€ํ•˜ / ์‘๋‹ต ์ง€์—ฐ / UI ๋ฒ„๋ฒ…๊ฑฐ๋ฆผ
์ค‘๋ณต๋œ ์š”์ฒญ์ด ๋ฐ˜๋ณต๋จ ๋‚ญ๋น„, ๊ผฌ์ž„, ์ •ํ•ฉ์„ฑ ์˜ค๋ฅ˜

โ†’ ๊ทธ๋ž˜์„œ ์šฐ๋ฆฌ๋Š” ์š”์ฒญ์„ ์ˆœ์„œ๋Œ€๋กœ, ์šฐ์„ ์ˆœ์œ„๋ณ„๋กœ, ํ•„์š”ํ•  ๋•Œ๋งŒ ๋ณด๋‚ด๋Š” ์„ค๊ณ„๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.


โœ… 2. ๊ธฐ๋ณธ ๊ตฌ์กฐ: ์ž‘์—… ํ ๋งŒ๋“ค๊ธฐ

๐Ÿ› ๏ธ ์˜ˆ์ œ ๊ตฌ์กฐ (๊ธฐ๋ณธ ํ)

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

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

  async runNext() {
    if (this.isRunning || this.queue.length === 0) return;

    this.isRunning = true;
    const nextTask = this.queue.shift();

    try {
      await nextTask();
    } catch (e) {
      console.error("์š”์ฒญ ์‹คํŒจ:", e);
    }

    this.isRunning = false;
    this.runNext(); // ๋‹ค์Œ ์ž‘์—… ์‹คํ–‰
  }
}


โœ… ์‚ฌ์šฉ ์˜ˆ

const queue = new AjaxQueue();

queue.enqueue(() => fetch("/user1"));
queue.enqueue(() => fetch("/user2"));
queue.enqueue(() => fetch("/user3"));

๐Ÿ‘‰ ์š”์ฒญ์€ ํ•˜๋‚˜์”ฉ ์ฐจ๋ก€๋Œ€๋กœ ์‹คํ–‰๋จ

โœ… ์„œ๋ฒ„ ๊ณผ๋ถ€ํ•˜ ๋ฐฉ์ง€

โœ… ์‘๋‹ต ์ˆœ์„œ ๋ณด์žฅ


โœ… 3. ์šฐ์„ ์ˆœ์œ„ ๊ธฐ๋ฐ˜ ์š”์ฒญ ํ


๐Ÿ“ฆ ๊ฐœ๋…

๊ธ‰ํ•œ ์š”์ฒญ์€ ๋จผ์ € ์ฒ˜๋ฆฌํ•˜๊ณ , ๋œ ๊ธ‰ํ•œ ๊ฑด ๋‚˜์ค‘์— ์‹คํ–‰ํ•˜๊ธฐ


๐Ÿ› ๏ธ ์ฝ”๋“œ ์˜ˆ์‹œ

class PriorityQueue {
  constructor() {
    this.queue = [];
    this.isRunning = false;
  }
  
  enqueue(task, priority = 0) {
    this.queue.push({ task, priority });
    this.queue.sort((a, b) => b.priority - a.priority); // ๋†’์€ ์šฐ์„ ์ˆœ์œ„ ๋จผ์ €
    this.runNext();
  }

  async runNext() {
    if (this.isRunning || this.queue.length === 0) return;

    this.isRunning = true;
    const { task } = this.queue.shift();
    try {
      await task();
    } finally {
      this.isRunning = false;
      this.runNext();
    }
  }
}


๐Ÿ‘ฆ๐Ÿป ์‰ฌ์šด ์„ค๋ช…

โ€œ์‘๊ธ‰ ํ™˜์ž ๋จผ์ €, ๊ฐ๊ธฐ ํ™˜์ž๋Š” ๋‚˜์ค‘์—โ€

โ†’ ์šฐ์„ ์ˆœ์œ„์— ๋”ฐ๋ผ ๋จผ์ € ์ฒ˜๋ฆฌ


โœ… ์‹ค๋ฌด ์˜ˆ์‹œ

์š”์ฒญ ์šฐ์„ ์ˆœ์œ„
๋กœ๊ทธ์ธ ์š”์ฒญ ๐ŸŸฅ 10 (๊ฐ€์žฅ ์šฐ์„ )
์•Œ๋ฆผ ์ฒดํฌ ๐ŸŸจ 5
์ถ”์ฒœ ๊ฒŒ์‹œ๋ฌผ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ ๐ŸŸฉ 2

โœ… 4. ๋ฐฑ์˜คํ”„ ์ „๋žต(Back-off)


๐Ÿ“ฆ ๋ฐฑ์˜คํ”„๋ž€?

์š”์ฒญ์ด ์‹คํŒจํ•˜๊ฑฐ๋‚˜ ์„œ๋ฒ„๊ฐ€ ๊ณผ๋ถ€ํ•˜ ์ƒํƒœ์ผ ๋•Œ,

์ž ๊น ๊ธฐ๋‹ค๋ ธ๋‹ค๊ฐ€ ๋‹ค์‹œ ์š”์ฒญํ•˜๋Š” ์ „๋žต์ž…๋‹ˆ๋‹ค.


๐Ÿ‘ฆ๐Ÿป ์‰ฌ์šด ์„ค๋ช…

๋ฌธ์„ ๋‘๋“œ๋ ธ๋Š”๋ฐ ์‚ฌ๋žŒ์ด ์—†์–ด์š”.

๐Ÿ‘‰ 5์ดˆ ํ›„ ๋‹ค์‹œ ๋‘๋“œ๋ฆผ โ†’ ๊ทธ๋ž˜๋„ ์—†์œผ๋ฉด โ†’ 10์ดˆ ํ›„ ๋‹ค์‹œ โ†’ โ€ฆ

โ†’ ์ ์  ๊ฐ„๊ฒฉ์„ ๋Š˜๋ฆฌ๋ฉฐ ๊ธฐ๋‹ค๋ฆฌ๋Š” ๊ฑฐ์˜ˆ์š”.


๐Ÿ“ˆ ๋Œ€ํ‘œ ์ „๋žต: ์ง€์ˆ˜ ๋ฐฑ์˜คํ”„ (Exponential Back-off)

let attempt = 0;

function retryAjax() {
  const delay = Math.pow(2, attempt) * 1000; // 1s, 2s, 4s, 8s...

  setTimeout(() => {
    fetch("/data")
      .then(res => res.json())
      .then(data => console.log(data))
      .catch(() => {
        attempt++;
        retryAjax(); // ์‹คํŒจํ•˜๋ฉด ๋‹ค์‹œ ์‹œ๋„
      });
  }, delay);
}

โœ… ์‹ค๋ฌด ์ ์šฉ ์œ„์น˜

์ƒํ™ฉ ๋ฐฑ์˜คํ”„ ์ ์šฉ
์„œ๋ฒ„๊ฐ€ 500 ์—๋Ÿฌ ์‘๋‹ต โœ… ๋ฐฑ์˜คํ”„ ํ›„ ์žฌ์‹œ๋„
๋„คํŠธ์›Œํฌ ๋Š๊น€ โœ… 3์ดˆ, 6์ดˆ, 12์ดˆ ๊ฐ„๊ฒฉ์œผ๋กœ ์žฌ์‹œ๋„
๋„ˆ๋ฌด ๋งŽ์€ ์š”์ฒญ โœ… ์ผ์ • ์‹œ๊ฐ„ ๋™์•ˆ ์ค‘์ง€ ํ›„ ์žฌ์‹œ๋„

โœ… ๋ฉด์ ‘ ์งˆ๋ฌธ ์˜ˆ์‹œ + ํ•ด์„ค


โ“ Q. ์‹ค์‹œ๊ฐ„ Ajax ์š”์ฒญ์ด ๋„ˆ๋ฌด ๋งŽ์•„ ์„œ๋ฒ„๊ฐ€ ๋А๋ ค์ง‘๋‹ˆ๋‹ค. ์–ด๋–ป๊ฒŒ ์ตœ์ ํ™”ํ•˜์‹ค ๊ฑด๊ฐ€์š”?

โœ… A.


โœ… ์ „์ฒด ์š”์•ฝ ์นด๋“œ

๊ธฐ์ˆ  ์„ค๋ช… ํšจ๊ณผ
์š”์ฒญ ํ ์š”์ฒญ์„ ์ค„ ์„ธ์›Œ์„œ ์ˆœ์ฐจ ์ฒ˜๋ฆฌ ๊ณผ๋ถ€ํ•˜ ๋ฐฉ์ง€
์šฐ์„ ์ˆœ์œ„ ํ ๊ธ‰ํ•œ ์š”์ฒญ ๋จผ์ € ์ฒ˜๋ฆฌ UX ๊ฐœ์„ 
๋ฐฑ์˜คํ”„ ์‹คํŒจ ์‹œ ์ ์  ์ฒœ์ฒœํžˆ ์žฌ์‹œ๋„ ์„œ๋ฒ„ ๋ณดํ˜ธ

โœ… ์‹œ๋‚˜๋ฆฌ์˜ค ์ •๋ฆฌ

์ƒํ™ฉ ์ ์šฉ ๊ธฐ์ˆ 
๋กœ๊ทธ์ธ ์š”์ฒญ โ†’ ๊ผญ ๋จผ์ € ์ฒ˜๋ฆฌ๋ผ์•ผ ํ•จ ์šฐ์„ ์ˆœ์œ„ ํ
10๊ฐœ ์š”์ฒญ์„ ์—ฐ์† ๋ณด๋ƒ„ ์ผ๋ฐ˜ ์š”์ฒญ ํ
์„œ๋ฒ„๊ฐ€ ๋ฐ”์  ๋•Œ ์š”์ฒญ ์‹คํŒจ ๋ฐฑ์˜คํ”„ ์ „๋žต