** ๐Ÿ“Œ 2-1๋‹จ๊ณ„: Ajax ๊ด€๋ จ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ ์›์ธ ์™„์ „ ์ •๋ณต **

๐Ÿ’ฃ ์‹ค๋ฌด์—์„œ ์‹œ์Šคํ…œ์„ ์ ์  ๋А๋ฆฌ๊ฒŒ ๋งŒ๋“œ๋Š” ์ˆจ๊ฒจ์ง„ ๋ฌด์„œ์šด ๋ฌธ์ œ: ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜


๐Ÿง  ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๋ž€? ์‰ฝ๊ฒŒ ๋งํ•ด์„œโ€ฆ

โ€œ๋” ์ด์ƒ ํ•„์š”ํ•˜์ง€ ์•Š์€ ๋ฐ์ดํ„ฐ๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ์— ๋‚จ์•„์„œ ๊ณ„์† ๊ณต๊ฐ„๋งŒ ์ฐจ์ง€ํ•˜๋Š” ๊ฒƒโ€

๐Ÿ“ฆ ๋น„์œ ํ•˜์ž๋ฉด:

๋ƒ‰์žฅ๊ณ ์—์„œ ๋‹ค ๋จน์€ ์Œ์‹์ธ๋ฐ ์น˜์šฐ์ง€ ์•Š๊ณ  ๊ณ„์† ์Œ“์•„๋‘๋Š” ๊ฒƒ์ด์—์š”.

โ†’ ๊ฒฐ๊ณผ์ ์œผ๋กœ ๋ƒ‰์žฅ๊ณ ๊ฐ€ ๊ฝ‰ ์ฐจ์„œ ์ƒˆ๋กœ์šด ๊ฑธ ๋„ฃ์„ ์ˆ˜ ์—†๊ฒŒ ๋จ


โœ… ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ ๋ฉ”๋ชจ๋ฆฌ๋Š” ๋ˆ„๊ฐ€ ์น˜์šธ๊นŒ?


โœ… 1. append(), innerHTML ๋‚จ๋ฐœ ์‹œ DOM ๋ˆ„์ˆ˜

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

setInterval(() => {
  document.body.innerHTML += "<p>์ถ”๊ฐ€๋จ</p>";
}, 1000);

๐Ÿ”ด ๊ฒฐ๊ณผ:

๐Ÿ” ์›์ธ


โœ… ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•

let div = document.createElement("div");
div.textContent = "์ถ”๊ฐ€๋จ";
document.body.appendChild(div);

โœ… 2. ์ฝœ๋ฐฑ / ํด๋กœ์ €์— ์˜ํ•œ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜

๐Ÿ‘€ ์ฝœ๋ฐฑ/ํด๋กœ์ €๋ž€?

function outer() {
  let bigData = new Array(1000000).fill("๐Ÿ’ฃ"); // ์—„์ฒญ ํฐ ๋ฐฐ์—ด
  return function inner() {
    console.log(bigData[0]);
  };
}

๐Ÿ“Œ ํด๋กœ์ €(Closure)๋Š” โ€œ๋‚ด๋ถ€ ํ•จ์ˆ˜๊ฐ€ ์™ธ๋ถ€ ๋ณ€์ˆ˜๋ฅผ ๊ธฐ์–ตํ•˜๋Š” ๊ฒƒโ€์ด์—์š”


โŒ ์‹ค๋ฌด์—์„œ ์ด๋Ÿฐ ์‹์œผ๋กœ ๋ฐœ์ƒํ•จ

$("#btn").click(function() {
  let bigArray = [...]; // ์•„์ฃผ ํฐ ๋ฐ์ดํ„ฐ
  $.ajax({
    url: "...",
    success: function() {
      console.log(bigArray[0]); // ๋ถˆํ•„์š”ํ•œ ์ฐธ์กฐ
    }
  });
});

โ†’ Ajax ์ฝœ๋ฐฑ ํ•จ์ˆ˜์—์„œ ํฐ ๋ฐ์ดํ„ฐ๋ฅผ ์ฐธ์กฐํ•˜๊ณ  ์žˆ์–ด์„œ GC๊ฐ€ ์ œ๊ฑฐ ๋ชปํ•จ


โœ… ํ•ด๊ฒฐ๋ฒ•


โœ… 3. ํƒ€์ด๋จธ(setInterval, setTimeout) ๋ฏธ์ •๋ฆฌ

โŒ ๋ˆ„์ˆ˜ ์˜ˆ์‹œ

setInterval(() => {
  console.log("๊ณ„์† ์‹คํ–‰");
}, 1000);
// ์ด๊ฑธ clearInterval ํ•˜์ง€ ์•Š์œผ๋ฉด โ†’ ๊ณ„์† ์‚ด์•„ ์žˆ์Œ

โœ… ํ•ด๊ฒฐ๋ฒ•

let timer = setInterval(...);
clearInterval(timer); // โœ… ๊ผญ ์ •๋ฆฌํ•˜๊ธฐ

โœ… 4. ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ๋ˆ„์ˆ˜

const div = document.createElement("div");
div.addEventListener("click", () => {
  alert("ํด๋ฆญ!");
});
document.body.appendChild(div);

โ†’ div๋ฅผ ์‚ญ์ œํ•ด๋„ ์ด๋ฒคํŠธ๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ์— ๋‚จ์•„ ์žˆ์œผ๋ฉด GC๊ฐ€ ๋ชป ์ง€์›€

โœ… ํ•ด๊ฒฐ๋ฒ•

div.removeEventListener("click", ํ•ธ๋“ค๋Ÿฌ๋ช…);

โœ… 5. GC(Garbage Collector)์˜ ์ž‘๋™ ์›๋ฆฌ (์ดˆ๊ฐ„๋‹จ)

๐Ÿ“Œ Mark-and-Sweep ์•Œ๊ณ ๋ฆฌ์ฆ˜

  1. *๋„๋‹ฌํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ’(๋ณ€์ˆ˜, ๊ฐ์ฒด)**๋งŒ ์ฐพ๋Š”๋‹ค (root์—์„œ ๋”ฐ๋ผ๊ฐ€๋ฉฐ)
  2. ๋‚˜๋จธ์ง€๋Š” โ€œ์“ธ๋ชจ ์—†์Œโ€์ด๋ผ๊ณ  ํŒ๋‹จํ•˜๊ณ  ์‚ญ์ œ

โœ… ๊ทธ๋Ÿฐ๋ฐ Ajax ์ฝœ๋ฐฑ์ด ํด๋กœ์ €๋กœ ๋ณ€์ˆ˜๋ฅผ ๋“ค๊ณ  ์žˆ์œผ๋ฉด

โ†’ โ€œ์“ธ๋ชจ ์žˆ๋‹ค๊ณ  ์ฐฉ๊ฐโ€ํ•ด์„œ ๋ชป ์ง€์›€


โœ… ์‹ค์ œ ์‹ค๋ฌด ์‹œ๋‚˜๋ฆฌ์˜ค ์š”์•ฝ

๋ˆ„์ˆ˜ ์›์ธ ์™œ ๋ฌธ์ œ์ธ๊ฐ€? ํ•ด๊ฒฐ๋ฒ•
innerHTML DOM์ด ๊ณ„์† ์ƒˆ๋กœ ์ƒ๊ธฐ๊ณ  ๊ธฐ์กด ์ฐธ์กฐ๋Š” ๋‚จ์Œ createElement, fragment ์‚ฌ์šฉ
์ฝœ๋ฐฑ/ํด๋กœ์ € ํด๋กœ์ €๊ฐ€ ํฐ ๋ณ€์ˆ˜ ๋“ค๊ณ  ์žˆ์Œ ์ฐธ์กฐ ์ œ๊ฑฐ or null ์ฒ˜๋ฆฌ
setInterval ๋ฉˆ์ถ”์ง€ ์•Š๊ณ  ๊ณ„์† ์‹คํ–‰๋จ clearInterval ํ•„์ˆ˜
์ด๋ฒคํŠธ ์š”์†Œ๋Š” ์ œ๊ฑฐ๋ผ๋„ ํ•ธ๋“ค๋Ÿฌ๋Š” ๋‚จ์•„ ์žˆ์Œ removeEventListener ํ•„์š”

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

โ“ Q. Ajax ์—ฐ๋™๋œ ์›น ํŽ˜์ด์ง€์—์„œ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ๋Œ€ํ‘œ์ ์ธ ์›์ธ๊ณผ ๋Œ€์‘ ๋ฐฉ๋ฒ•์€?

โœ… A.


โœ… ์š”์•ฝ ํ‚ค์›Œ๋“œ ์นด๋“œ

๊ฐœ๋… ์„ค๋ช…
๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ GC๊ฐ€ ์ง€์šฐ์ง€ ๋ชปํ•˜๋Š” ์“ธ๋ชจ์—†๋Š” ๋ฐ์ดํ„ฐ
innerHTML ์ƒˆ๋กœ ๋งŒ๋“ค์ง€๋งŒ ๊ธฐ์กด ์ฐธ์กฐ๋Š” ๋‚จ์Œ
ํด๋กœ์ € ๋‚ด๋ถ€ ํ•จ์ˆ˜๊ฐ€ ์™ธ๋ถ€ ๋ณ€์ˆ˜๋ฅผ ๊ณ„์† ๊ธฐ์–ต
setInterval ๋ฌดํ•œ ์‹คํ–‰ โ†’ ์ข…๋ฃŒ ์•ˆ ํ•˜๋ฉด ๋ˆ„์ˆ˜
์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ DOM ์‚ญ์ œ ์‹œ ํ•จ๊ป˜ ์ œ๊ฑฐํ•˜์ง€ ์•Š์œผ๋ฉด ์ฐธ์กฐ ์œ ์ง€๋จ

โœ… ๋‹ค์Œ ์˜ˆ๊ณ :

2-2๋‹จ๊ณ„: ๋ธŒ๋ผ์šฐ์ € GC์™€ ์ฐธ์กฐ ๊ด€๊ณ„, ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๋ฅผ ์žก์•„๋‚ด๋Š” DevTools Memory ํƒญ ์‚ฌ์šฉ๋ฒ•์ž…๋‹ˆ๋‹ค.

โœ… 2-2๋‹จ๊ณ„: ๋ธŒ๋ผ์šฐ์ € GC ๊ด€์ ์—์„œ ๋ณธ ๋ฉ”๋ชจ๋ฆฌ ํšŒ์ˆ˜


๐Ÿ’ก GC๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์–ด๋–ป๊ฒŒ ์ •๋ฆฌํ•˜๊ณ , Ajax๊ฐ€ ์–ด๋–ป๊ฒŒ ๊ทธ๊ฑธ ๋ฐฉํ•ดํ•˜๋Š”์ง€๋ฅผ ์™„๋ฒฝํžˆ ์ดํ•ดํ•˜๋Š” ๋‹จ๊ณ„


โœ… 1. ๋ธŒ๋ผ์šฐ์ €๋Š” ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ž๋™์œผ๋กœ ์ •๋ฆฌํ•œ๋‹ค

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋Š” delete ๊ฐ™์€ ๊ฑธ ๊ฑฐ์˜ ์•ˆ ์จ๋„ ๊ดœ์ฐฎ์•„์š”.

์™œ๋ƒ๋ฉด ๋ธŒ๋ผ์šฐ์ €๊ฐ€ โ€œ๋” ์ด์ƒ ์•ˆ ์“ฐ๋Š” ๋ฐ์ดํ„ฐ๋Š” ์ž๋™์œผ๋กœ ์‚ญ์ œโ€ํ•ด์ฃผ๊ธฐ ๋•Œ๋ฌธ์ด์—์š”.

์ด๊ฑธ Garbage Collector (GC, ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰ํ„ฐ)๋ผ๊ณ  ํ•ด์š”.


โœ… 2. GC๊ฐ€ ์“ฐ๋Š” ๋ฐฉ์‹: Mark-and-Sweep ์•Œ๊ณ ๋ฆฌ์ฆ˜

๐Ÿ“ฆ ์ด๊ฑด ๋งˆ์น˜ โ€œ์•ˆ ์“ฐ๋Š” ๋ฌผ๊ฑด ์ •๋ฆฌํ•˜๊ธฐโ€ ๊ฐ™์•„์š”

1๏ธโƒฃ โ€œ์ด๊ฑฐ ์•„์ง ์“ฐ๊ณ  ์žˆ๋Š” ๊ฑฐ์•ผ?โ€ ํ•˜๊ณ  ํ•˜๋‚˜์”ฉ ํ™•์ธํ•˜๊ณ 

2๏ธโƒฃ โ€œ์•„๋ฌด๋„ ์•ˆ ์“ฐ๋Š” ๊ฑฐ๋„ค?โ€ โ†’ ์“ฐ๋ ˆ๊ธฐํ†ต์œผ๋กœ ๋ณด๋‚ด๊ธฐ


๐Ÿ“Œ ์ž‘๋™ ์ˆœ์„œ (์ค‘ํ•™์ƒ ๋ฒ„์ „)

  1. ๋ชจ๋“  ๋ณ€์ˆ˜/๊ฐ์ฒด๋ฅผ ํ™•์ธํ•œ๋‹ค
  2. ๋ˆ„๊ฐ€ ์“ฐ๊ณ  ์žˆ๋Š”์ง€ ํ‘œ์‹œํ•œ๋‹ค (๐Ÿ“mark)
  3. ์•„๋ฌด๋„ ์•ˆ ์“ฐ๋Š” ๊ฑด ์ •๋ฆฌํ•œ๋‹ค (๐Ÿงนsweep)

๐Ÿง  ์ปดํ“จํ„ฐ๊ณตํ•™์‹ ์„ค๋ช…

๋‹จ๊ณ„ ์„ค๋ช…
Mark โ€œ๋ฃจํŠธ(root)โ€์—์„œ ์‹œ์ž‘ํ•ด์„œ, ์—ฐ๊ฒฐ๋œ ๋ณ€์ˆ˜/๊ฐ์ฒด๋“ค์„ ๋”ฐ๋ผ๊ฐ€๋ฉฐ ํ‘œ์‹œํ•จ
Sweep ํ‘œ์‹œ๋˜์ง€ ์•Š์€ ๊ฐ์ฒด๋“ค์€ โ€œ๋” ์ด์ƒ ์ ‘๊ทผ ๋ถˆ๊ฐ€๋Šฅโ€ โ†’ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ์ œ๊ฑฐํ•จ

โœ… 3. ๋ฃจํŠธ(Root)๋Š” ๋ˆ„๊ตฌ์ธ๊ฐ€?

GC๋Š” โ€œ๊ธฐ์ค€์ โ€์—์„œ ์‹œ์ž‘ํ•ด์„œ ์ฐธ์กฐ๋œ ์• ๋“ค๋งŒ ๋‚จ๊ฒจ์š”.

๋Œ€ํ‘œ์ ์ธ Root๋“ค

โ†’ ์ด Root์—์„œ ์‹œ์ž‘ํ•ด์„œ ๋”ฐ๋ผ๊ฐˆ ์ˆ˜ ์—†๋Š” ์• ๋“ค์€ ์ง€์›Œ์š”!


โœ… 4. ๋„๋‹ฌ ๊ฐ€๋Šฅ์„ฑ (reachability) ๊ฐœ๋…

GC ์ž…์žฅ์—์„œ โ€œ์ด ๊ฐ์ฒด์— ๋„๋‹ฌํ•  ์ˆ˜ ์žˆ์–ด?โ€ โ†’ YES๋ฉด ์‚ด๋ฆฌ๊ณ , NO๋ฉด ์ง€์›Œ์š”

์˜ˆ์‹œ 1: ๋„๋‹ฌ ๊ฐ€๋Šฅ

let a = {name: "ํ™๊ธธ๋™"};
let b = a; // ๐Ÿ‘‰ b๋„ ๊ฐ™์€ ๊ฐ์ฒด๋ฅผ ๊ฐ€๋ฆฌํ‚ด

์˜ˆ์‹œ 2: ๋„๋‹ฌ ๋ถˆ๊ฐ€๋Šฅ

let a = {name: "ํ™๊ธธ๋™"};
a = null; // ๐Ÿ‘‰ ๋” ์ด์ƒ ์•„๋ฌด๋„ ์•ˆ ๊ฐ€๋ฆฌํ‚ด

โœ… 5. Ajax ์ฝœ๋ฐฑ ํ•จ์ˆ˜์˜ ์ฐธ์กฐ ๋ฌธ์ œ

โŒ ์ด๋Ÿฐ ์ฝ”๋“œ๊ฐ€ ๋ฌธ์ œ์ž…๋‹ˆ๋‹ค:

function loadData() {
  let bigData = new Array(1000000).fill("๐Ÿ˜ฑ");
  $.ajax({
    url: "/data",
    success: function() {
      console.log(bigData[0]); // ๐Ÿ‘‰ ์•„์ง๋„ bigData๋ฅผ ์ฐธ์กฐํ•˜๊ณ  ์žˆ์Œ
    }
  });
}

bigData๋Š” ์—ฌ์ „ํžˆ โ€œ๋ˆ„๊ฐ€ ๋‚˜๋ฅผ ์“ฐ๊ณ  ์žˆ์–ด์š”!โ€๋ผ๊ณ  ์ฐฉ๊ฐ์‹œํ‚ด

โ†’ GC๋Š” ์ ˆ๋Œ€ ์ด๊ฑธ ์ •๋ฆฌ ๋ชป ํ•จ โ†’ โŒ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ ๋ฐœ์ƒ


โœ… 6. ํด๋กœ์ €์™€ ์ฐธ์กฐ ์นด์šดํŠธ ๋ฌธ์ œ

๐Ÿ“Œ ํด๋กœ์ €๋ž€?

function outer() {
  let secret = "๋น„๋ฐ€";
  return function inner() {
    console.log(secret);
  };
}

๐Ÿ’ฅ ํด๋กœ์ €๊ฐ€ ๋ฌธ์ œ๋ฅผ ์ผ์œผํ‚ค๋Š” ๊ฒฝ์šฐ:


โœ… 7. ์–ด๋–ป๊ฒŒ ํ•˜๋ฉด GC๊ฐ€ ์ž˜ ์ž‘๋™ํ•˜๊ฒŒ ๋„์™€์ค„๊นŒ?

๋ฌธ์ œ ํ•ด๊ฒฐ๋ฒ•
ํด๋กœ์ €๊ฐ€ ํฐ ๋ฐ์ดํ„ฐ๋ฅผ ์ฐธ์กฐ ์‘๋‹ต์ด ๋๋‚˜๋ฉด ๋ณ€์ˆ˜ null ์ฒ˜๋ฆฌ
Ajax ์š”์ฒญ ์‹คํŒจ ์‹œ ์‘๋‹ต ๋Œ€๊ธฐ ๋ฉ”๋ชจ๋ฆฌ ์ •๋ฆฌ ์•ˆ ๋จ AbortController๋กœ ์ทจ์†Œ ์ฒ˜๋ฆฌ
DOM ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ์ฐธ์กฐ ๋‚จ์Œ removeEventListener()๋กœ ์ œ๊ฑฐ
setInterval์ด ๊ณ„์† ์‹คํ–‰ clearInterval()๋กœ ์ •๋ฆฌ

โœ… 8. ๊ณ ๊ธ‰ ๊ฐœ๋… ์š”์•ฝ (์ธํ„ฐ๋ทฐ์šฉ ํ•œ ์ค„ ์ •๋ฆฌ)


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

โ“ Q. Ajax๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด์„œ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ์ด์œ ๋ฅผ GC ๊ด€์ ์—์„œ ์„ค๋ช…ํ•˜์‹œ์˜ค.

โœ… A.


โœ… ์š”์•ฝ ํ•œ ์ปท ์นด๋“œ

๊ฐœ๋… ์‰ฌ์šด ์„ค๋ช…
GC ์•ˆ ์“ฐ๋Š” ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์ž๋™์œผ๋กœ ์ •๋ฆฌ
Mark-and-Sweep ์“ฐ๋Š” ๊ฑด ํ‘œ์‹œํ•˜๊ณ , ์•ˆ ์“ฐ๋Š” ๊ฑด ์ง€์šฐ๋Š” ๋ฐฉ์‹
๋„๋‹ฌ ๊ฐ€๋Šฅ์„ฑ ๋ณ€์ˆ˜/๊ฐ์ฒด์— ๋”ฐ๋ผ๊ฐˆ ์ˆ˜ ์žˆ์œผ๋ฉด ์‚ญ์ œ ์•ˆ ํ•จ
Ajax ์ฝœ๋ฐฑ ๋ˆ„์ˆ˜ ์ฝœ๋ฐฑ ์•ˆ์— ํฐ ๋ฐ์ดํ„ฐ๋ฅผ ์ฐธ์กฐํ•˜๋ฉด GC๊ฐ€ ์‚ญ์ œ ๋ชป ํ•จ
ํ•ด๊ฒฐ null ์ฒ˜๋ฆฌ, AbortController, ๋ฆฌ์Šค๋„ˆ ํ•ด์ œ ๋“ฑ

โœ… ๋‹ค์Œ ์˜ˆ๊ณ :

2-3๋‹จ๊ณ„: ์‹ค๋ฌด ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ ์˜ˆ์ œ ๋ถ„์„ + Chrome DevTools ๋ฉ”๋ชจ๋ฆฌ ํ”„๋กœํŒŒ์ผ๋ง ์‹ค์Šต

โœ… 2-3๋‹จ๊ณ„: ์‹ค๋ฌด ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ ์˜ˆ์ œ ๋ถ„์„ + Chrome DevTools ๋ฉ”๋ชจ๋ฆฌ ๋ถ„์„๋ฒ•

๐Ÿ’ฅ Ajax ์š”์ฒญ์„ ๋งŽ์ด ๋ณด๋‚ด๋ฉด ์™œ ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ๋А๋ ค์งˆ๊นŒ?

๐Ÿ‘จ๐Ÿปโ€๐Ÿซ ๊ทธ๊ฑธ ์ฐพ์•„๋‚ด๋Š” ์‹ค๋ฌด ๋””๋ฒ„๊น… ์Šคํ‚ฌ์„ ๋งˆ์Šคํ„ฐํ•˜๋Š” ๋‹จ๊ณ„์ž…๋‹ˆ๋‹ค.


โœ… 1. ์ƒํ™ฉ ์‹œ๋‚˜๋ฆฌ์˜ค: โ€œUI๊ฐ€ ์ ์  ๋А๋ ค์ ธ์š”โ€

๐Ÿ‘จ๐Ÿปโ€๐Ÿ’ป ๋ฌธ์ œ ์„ค๋ช…

for (let i = 0; i < 1000; i++) {
  $.ajax({
    url: "some_api.jsp",
    success: function(data) {
      const div = document.createElement("div");
      div.innerHTML = data;
      document.body.appendChild(div);
    }
  });
}

๐Ÿ’ฅ ์œ„ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜๋ฉดโ€ฆ


โœ… 2. ์™œ ๊ทธ๋Ÿด๊นŒ? ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜์˜ ํ”ํ•œ ์›์ธ๋“ค

์›์ธ ์„ค๋ช…
๐Ÿ“Œ DOM์ด ๊ณ„์† ์ถ”๊ฐ€๋จ appendChild()๋กœ ๊ณ„์† ํ™”๋ฉด ์š”์†Œ๊ฐ€ ์Œ“์ž„
๐Ÿ“Œ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋„ ๊ฐ™์ด ์ƒ๊น€ ์‘๋‹ต HTML์— onclick, onchange๊ฐ€ ๋“ค์–ด ์žˆ์œผ๋ฉด ์ฐธ์กฐ๋„ ๊ฐ™์ด ์Œ“์ž„
๐Ÿ“Œ Ajax ์ฝœ๋ฐฑ ์•ˆ์—์„œ ํด๋กœ์ €๋กœ ์™ธ๋ถ€ ๋ณ€์ˆ˜ ์‚ฌ์šฉ GC๊ฐ€ ํ•ด๋‹น ์ฝœ๋ฐฑ์„ ํ•ด์ œํ•˜์ง€ ๋ชปํ•จ
๐Ÿ“Œ ์‘๋‹ต์„ ์บ์‹ฑ ์—†์ด ๊ณ„์† ์Œ“์Œ ์‘๋‹ต ๋ฐ์ดํ„ฐ๊ฐ€ ์‚ฌ๋ผ์ง€์ง€ ์•Š์Œ

โœ… 3. ์ฆ์ƒ ์ •๋ฆฌ

์ฆ์ƒ ์„ค๋ช…
CPU ์‚ฌ์šฉ๋Ÿ‰ ์ฆ๊ฐ€ ๊ณ„์† DOM ์ถ”๊ฐ€ โ†’ ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ๋ Œ๋”๋ง์— ๊ณผ๋ถ€ํ•˜
๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰ ์ง€์† ์ฆ๊ฐ€ GC๊ฐ€ ํ•ด์ œ ๋ชปํ•˜๋Š” ๊ฐ์ฒด๊ฐ€ ๋‚จ์Œ
UI ๋ฐ˜์‘ ์ €ํ•˜ ์ด๋ฒคํŠธ/DOM์ด ๋งŽ์•„์งˆ์ˆ˜๋ก ํด๋ฆญ ๋ฐ˜์‘, ๋ Œ๋”๋ง ์†๋„ ์ €ํ•˜

โœ… 4. ํ•ด๊ฒฐ์€? ๋จผ์ € โ€œ์–ด๋””๊ฐ€ ๋ฌธ์ œ์ธ์ง€ ์ฐพ์•„์•ผโ€ ํ•ฉ๋‹ˆ๋‹ค

๊ทธ๋Ÿด ๋•Œ ์“ฐ๋Š” ๋„๊ตฌ๊ฐ€ ๋ฐ”๋กœ ๐Ÿ‘‰ Chrome DevTools์˜ Memory ํƒญ


โœ… 5. Chrome DevTools - Memory ํƒญ ์‚ฌ์šฉ๋ฒ• (์ค‘ํ•™์ƒ๋„ ์ดํ•ด ๊ฐ€๋Šฅ)

๐Ÿ“Œ ์‚ฌ์šฉ ๋ฐฉ๋ฒ• ์š”์•ฝ

  1. F12 ๋ˆ„๋ฅด๊ธฐ (๊ฐœ๋ฐœ์ž ๋„๊ตฌ ์—ด๊ธฐ)
  2. ์ƒ๋‹จ ํƒญ์—์„œ Memory ์„ ํƒ
  3. ์ขŒ์ธก์—์„œ Heap snapshot ์„ ํƒ ํ›„ โ†’ ๐Ÿ“ธ Take snapshot ํด๋ฆญ

๐Ÿงช ๊ฒฐ๊ณผ ํ•ด์„ ํฌ์ธํŠธ

์šฉ์–ด ๋œป ์‰ฝ๊ฒŒ ๋งํ•˜๋ฉด
JS Heap ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๊ฐ€ ์‚ฌ์šฉํ•˜๋Š” ๋ฉ”๋ชจ๋ฆฌ ๊ณต๊ฐ„ ๋‚ด ์ž‘์—…๊ณต๊ฐ„
Detached DOM Tree ๋” ์ด์ƒ ํ™”๋ฉด์—” ์—†์ง€๋งŒ, ๋ฉ”๋ชจ๋ฆฌ์—” ๋‚จ์€ ์š”์†Œ โ€œ์‚ญ์ œ๋œ ์ค„ ์•Œ์•˜๋Š”๋ฐ ์•„์ง ์‚ด์•„์žˆ๋Š” ํƒœ๊ทธโ€
Object Count ํŠน์ • ๊ฐ์ฒด์˜ ๊ฐœ์ˆ˜ ์˜ˆ: <div>๊ฐ€ 1000๊ฐœ์”ฉ ์Œ“์ž„
Retainers ์ด ๊ฐ์ฒด๋ฅผ ๋ˆ„๊ฐ€ ๋ถ™์žก๊ณ  ์žˆ๋Š”๊ฐ€ ํด๋กœ์ €, ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ๋“ฑ ์ฐธ์กฐ ์ถ”์ 

๐Ÿ’ฅ ์‹ค๋ฌด ๋ˆ„์ˆ˜ ์˜ˆ์ œ ์ฐพ์•„๋‚ด๊ธฐ

  1. Snapshot์„ ํ•˜๋‚˜ ์ฐ๋Š”๋‹ค (์‹œ์ž‘ ์ „)
  2. ๋ˆ„์ ๋˜๋Š” Ajax ์‹คํ–‰ (for๋ฌธ ๋“ฑ์œผ๋กœ 1000๋ฒˆ)
  3. ๋‹ค์‹œ Snapshot ์ฐ๊ธฐ
  4. ๐Ÿ“Š ๋ณ€ํ™” ๋น„๊ต

โ†’ Detached DOM์ด ๋งŽ๊ณ  ์ค„์ง€ ์•Š์œผ๋ฉด ๋ˆ„์ˆ˜

โ†’ Array, Function, Object ์ˆ˜๊ฐ€ ๊ณ„์† ์ฆ๊ฐ€ํ•˜๋ฉด ์ฐธ์กฐ ๋ˆ„์ˆ˜


โœ… 6. ์‹ค๋ฌด ๋””๋ฒ„๊น… ๊ฟ€ํŒ

๐Ÿ’ก ์ž์ฃผ ๋ณด๋Š” ๋ˆ„์ˆ˜ ํ•ญ๋ชฉ๋“ค

ํ•ญ๋ชฉ ํ•ด์„
Detached DOM Tree Ajax๋กœ ๋งŒ๋“  ์š”์†Œ๊ฐ€ ์‚ฌ๋ผ์ง€์ง€ ์•Š์Œ
Array(1000) ํฐ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ด์€ ๋ฐฐ์—ด์ด ์ฐธ์กฐ๋กœ ์‚ด์•„ ์žˆ์Œ
Closure ์ฝœ๋ฐฑ ๋‚ด๋ถ€์—์„œ ์™ธ๋ถ€ ๋ณ€์ˆ˜๋ฅผ ๊ธฐ์–ต ์ค‘
Timer setInterval()์ด clear๋˜์ง€ ์•Š์Œ
Listener ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ์ œ๊ฑฐ๋˜์ง€ ์•Š์Œ

โœ… 7. ๋ˆ„์ˆ˜๋ฅผ ์˜ˆ๋ฐฉํ•˜๋Š” ์‹ค์ „ ํŒจํ„ด

โœ”๏ธ ์ •๋ฆฌ ๋ฃจํ‹ด

const handler = function() {
  // ์ด๋ฒคํŠธ ๋™์ž‘
};
element.addEventListener("click", handler);

// ๋‚˜์ค‘์— ์ œ๊ฑฐ
element.removeEventListener("click", handler);

โœ”๏ธ ์‘๋‹ต ์ดํ›„ ์ฐธ์กฐ ์ œ๊ฑฐ

let bigArray = [...];

$.ajax({
  url: "some.jsp",
  success: function() {
    // ์ž‘์—… ํ›„ ์ฐธ์กฐ ์ œ๊ฑฐ
    bigArray = null;
  }
});

โœ… 8. ์š”์•ฝ ์ •๋ฆฌ

ํ•ญ๋ชฉ ์„ค๋ช…
๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ GC๊ฐ€ ์ œ๊ฑฐํ•˜์ง€ ๋ชปํ•œ ๋ฉ”๋ชจ๋ฆฌ ์ฐŒ๊บผ๊ธฐ
Ajax ๋ˆ„์ˆ˜ ์›์ธ DOM ์ถ”๊ฐ€, ํด๋กœ์ € ์ฐธ์กฐ, ์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ ๋ฐฉ์น˜
ํ•ด๊ฒฐ ์ฐธ์กฐ ์ œ๊ฑฐ, ์ด๋ฒคํŠธ ํ•ด์ œ, innerHTML ๋Œ€์‹  createElement ์‚ฌ์šฉ
DevTools Memory ํƒญ ๋ˆ„์ˆ˜ ์ถ”์ ์— ์ตœ์ ํ™”๋œ ๋ถ„์„ ๋„๊ตฌ
Snapshot ๋น„๊ต ๋ฉ”๋ชจ๋ฆฌ ์ฆ๊ฐ€ ์ถ”์ด ํ™•์ธ ๊ฐ€๋Šฅ
Detached DOM ํ™”๋ฉด์— ์—†๋Š”๋ฐ ๋ฉ”๋ชจ๋ฆฌ์— ๋‚จ์€ ์š”์†Œ โ†’ ๋ˆ„์ˆ˜ ๋Œ€ํ‘œ ์ฃผ์ž

โœ… ๋ฉด์ ‘ ์งˆ๋ฌธ ์˜ˆ์‹œ

โ“ Q. 1000๊ฐœ์˜ Ajax ์š”์ฒญ ์ดํ›„ ๋ธŒ๋ผ์šฐ์ € UI๊ฐ€ ๋А๋ ค์กŒ์Šต๋‹ˆ๋‹ค. ๋ฉ”๋ชจ๋ฆฌ ๋ถ„์„์„ ํ†ตํ•ด ์–ด๋–ค ๋ฌธ์ œ๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‚˜์š”?

โœ… A.