The JavaScript Event Loop: Explained - Lee-hyuna/33-js-concepts-kr GitHub Wiki

The JavaScript Event Loop: Explained (์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์ด๋ฒคํŠธ ๋ฃจํ”„ : ์„ค๋ช…)

์ด ๊ฒŒ์‹œ๋ฌผ์€ ๋ฌด์—‡์— ๊ด€ํ•œ ๊ฒƒ์ž…๋‹ˆ๊นŒ?

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋Š” ์›น ๋ธŒ๋ผ์šฐ์ €์˜ ์Šคํฌ๋ฆฝํŠธ ์–ธ์–ด๋กœ ๊ฑฐ์˜ ๊ณ ์œ ์„ฑ์— ๊ฐ€๊นŒ์›Œ์ง์— ๋”ฐ๋ผ, ์ด๋ฒคํŠธ ๊ธฐ๋ฐ˜ ์ƒํ˜ธ์ž‘์šฉ ๋ชจ๋ธ์— ๋Œ€ํ•œ ๊ธฐ๋ณธ ์ดํ•ด์™€ Ruby, Python ๋ฐ Java์™€ ๊ฐ™์€ ์–ธ์–ด์—์„œ ์ผ๋ฐ˜์ ์œผ๋กœ ๋ฐœ๊ฒฌ๋˜๋Š” ์š”์ฒญ ์‘๋‹ต ๋ชจ๋ธ๊ณผ ์ฐจ์ด์ ์„ ์ดํ•ดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ์ž๋ฆฌ๋Š” ๋ˆ„๊ตฌ๋ฅผ ์œ„ํ•œ ๊ฒƒ์ธ๊ฐ€?

์ด ๊ฒŒ์‹œ๋ฌผ์€ ํด๋ผ์ด์–ธํŠธ ๋˜๋Š” ์„œ๋ฒ„์—์„œ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ ์ž‘์—…ํ•˜๊ณ ์žˆ๋Š” ์›น ๊ฐœ๋ฐœ์ž๋ฅผ ๋Œ€์ƒ์œผ๋กœํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฒคํŠธ ๋ฃจํ”„์— ์ด๋ฏธ ์ต์ˆ™ํ•˜๋‹ค๋ฉด ์ด ๊ฒŒ์‹œ๋ฌผ์— ๋งŽ์€ ๋ถ€๋ถ„์ด ์ต์ˆ™ ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ ‡์ง€ ์•Š์€ ์‚ฌ๋žŒ๋“ค์„ ์œ„ํ•ด, ๋‹น์‹ ์ด ์ผ์ƒ์ ์œผ๋กœ ์ฝ๊ณ , ์“ฐ๋Š” ์ฝ”๋“œ์— ๋Œ€ํ•ด ๋” ๋งŽ์€ ์ด์œ ๋ฅผ ์ œ๊ธฐ ํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ธฐ๋ณธ์ ์ธ ์ดํ•ด๋ฅผ ์ œ๊ณตํ•˜๊ธฐ๋ฅผ ํฌ๋งํ•ฉ๋‹ˆ๋‹ค.

Non-blocking I/O

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—์„œ ๊ฑฐ์˜ ๋ชจ๋“  I / O๋Š” ์ฐจ๋‹จ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.(non-blocking) ์—ฌ๊ธฐ์—๋Š” HTTP ์š”์ฒญ, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ž‘์—… ๋ฐ ๋””์Šคํฌ ์ฝ๊ธฐ ๋ฐ ์“ฐ๊ธฐ๊ฐ€ ํฌํ•จ๋ฉ๋‹ˆ๋‹ค. ์‹คํ–‰์˜ single-threaded๋Š” ๋Ÿฐํƒ€์ž„์— ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋„๋ก ์š”์ฒญํ•˜๊ณ  ์ฝœ๋ฐฑ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•œ ๋‹ค์Œ ๋‹ค๋ฅธ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋„๋ก ์ด๋™ํ•ฉ๋‹ˆ๋‹ค. ์ž‘์—…์ด ์™„๋ฃŒ๋˜๋ฉด ์ œ๊ณต๋œ ์ฝœ๋ฐฑ ๊ธฐ๋Šฅ๊ณผ ํ•จ๊ป˜ ๋ฉ”์‹œ์ง€๊ฐ€ ๋Œ€๊ธฐ์—ด์— ํฌํ•จ๋ฉ๋‹ˆ๋‹ค. ์•ž์œผ๋กœ ์–ด๋–ค ์‹œ์ ์—์„œ ๋ฉ”์‹œ์ง€๋Š” ๋Œ€๊ธฐ์—ด์—์„œ ์ œ์™ธ๋˜๊ณ  ์ฝœ๋ฐฑ์ด ์‹œ์ž‘๋ฉ๋‹ˆ๋‹ค.

์ด ์ƒํ˜ธ์ž‘์šฉ ๋ชจ๋ธ์€ ์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค("mouchown" ๋ฐ "click"๊ณผ ๊ฐ™์€ ์ด๋ฒคํŠธ๊ฐ€ ์–ธ์ œ๋“ ์ง€ ํŠธ๋ฆฌ๊ฑฐ๋  ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ)์ž‘์—…์— ์ด๋ฏธ ์ต์ˆ™ํ•œ ๊ฐœ๋ฐœ์ž์—๊ฒŒ๋Š” ์นœ์ˆ™ ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ์„œ๋ฒ„์ธก ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ์ผ๋ฐ˜์ ์œผ๋กœ ๋ฐœ๊ฒฌ๋˜๋Š” ๋™๊ธฐ์‹ ์š”์ฒญ ์‘๋‹ต ๋ชจ๋ธ๊ณผ๋Š” ๋‹ค๋ฆ…๋‹ˆ๋‹ค.

HTTP ์š”์ฒญ์„ www.google.com์— ์ ์šฉํ•˜๊ณ  ์‘๋‹ต์„ ์ฝ˜์†”์— ์ถœ๋ ฅํ•˜๋Š” ๋‘ ๋น„ํŠธ์˜ ์ฝ”๋“œ๋ฅผ ๋น„๊ตํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์ฒซ๋ฒˆ์งธ, Ruby, Faraday:

  response = Faraday.get 'http://www.google.com'
  puts response
  puts 'Done!'

์‹คํ–‰ ๊ฒฝ๋กœ๋Š” ์‰ฝ๊ฒŒ ๋”ฐ๋ผ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  1. get ๋ฉ”์†Œ๋“œ๊ฐ€ ์‹คํ–‰๋˜๊ณ  ์‘๋‹ต ์Šค๋ ˆ๋“œ๊ฐ€ ์ˆ˜์‹  ๋  ๋•Œ๊นŒ์ง€ ์‹คํ–‰ ์Šค๋ ˆ๋“œ๊ฐ€ ๋Œ€๊ธฐํ•ฉ๋‹ˆ๋‹ค.
  2. response์€ Google์—์„œ ์ˆ˜์‹ ๋˜์–ด ๋ณ€์ˆ˜๊ฐ€ ์ €์žฅ๋œ ํ˜ธ์ถœ์ž์—๊ฒŒ ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค.
  3. ๋ณ€์ˆ˜์˜ ๊ฐ’ (์ด ๊ฒฝ์šฐ response)์€ console์— ์ถœ๋ ฅ๋ฉ๋‹ˆ๋‹ค.
  4. "Done!"๊ฐ’์ด ์ฝ˜์†”์— ์ถœ๋ ฅ๋ฉ๋‹ˆ๋‹ค.

Node.js ๋ฐ ์š”์ฒญ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—์„œ๋„ ๋™์ผํ•œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

  request('http://www.google.com', function(error, response, body) {
    console.log(body);
  });

  console.log('Done!');

์•ฝ๊ฐ„์˜ ๋‹ค๋ฅธ ๋ชจ์–‘๊ณผ ๋งค์šฐ ๋‹ค๋ฅธํ–‰๋™:

  1. ์š”์ฒญ ํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰๋˜์–ด ์ต๋ช… ํ•จ์ˆ˜๋ฅผ ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋กœ ์ „๋‹ฌํ•˜์—ฌ ํ–ฅํ›„ ์–ธ์  ๊ฐ€ response์„ ์‚ฌ์šฉํ•  ์ˆ˜์žˆ์„ ๋•Œ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.
  2. "Done!"์ด ์ฆ‰์‹œ console์— ์ถœ๋ ฅ๋ฉ๋‹ˆ๋‹ค.
  3. ์–ธ์  ๊ฐ€๋Š” response์ด ๋Œ์•„์˜ค๊ณ  ์ฝœ๋ฐฑ์ด ์‹คํ–‰๋˜์–ด body๋ฅผ console๋กœ ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค.

The Event Loop

๋น„๋™๊ธฐ ์ž‘์—…์ด ์™„๋ฃŒ๋˜๊ณ  ์ฝœ๋ฐฑ์ด ์‹œ์ž‘๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฌ๋Š” ๋™์•ˆ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๋Ÿฐํƒ€์ž„์—์„œ ๋‹ค๋ฅธ ์ž‘์—…์„ ์ˆ˜ํ–‰ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ์ด๋Ÿฌํ•œ ์ฝœ๋ฐฑ์€ ์–ด๋””์— ์žˆ์œผ๋ฉฐ ์–ด๋–ค ์ˆœ์„œ๋กœ ์‹คํ–‰๋ฉ๋‹ˆ๊นŒ? ๋ฌด์—‡ ๋•Œ๋ฌธ์— ๊ทธ๋“ค์„ ๋ถˆ๋ ค์ง‘๋‹ˆ๊นŒ?

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๋Ÿฐํƒ€์ž„์—๋Š” ์ฒ˜๋ฆฌ ํ•  ๋ฉ”์‹œ์ง€ ๋ชฉ๋ก๊ณผ ๊ด€๋ จ ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ์ €์žฅํ•˜๋Š” ๋ฉ”์‹œ์ง€ ๋Œ€๊ธฐ์—ด์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๋ฉ”์‹œ์ง€๋Š” ์ฝœ๋ฐฑ ๊ธฐ๋Šฅ์ด ์ œ๊ณต๋˜๋ฉด ์™ธ๋ถ€ ์ด๋ฒคํŠธ (๋งˆ์šฐ์Šค๋ฅผ ํด๋ฆญํ•˜๊ฑฐ๋‚˜ HTTP ์š”์ฒญ์— ๋Œ€ํ•œ ์‘๋‹ต์„๋ฐ›๋Š” ๊ฒƒ๊ณผ ๊ฐ™์€)์— ๋Œ€ํ•œ ์‘๋‹ต์œผ๋กœ ๋Œ€๊ธฐํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ์‚ฌ์šฉ์ž๊ฐ€ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๊ณ  ์ฝœ๋ฐฑ ํ•จ์ˆ˜๊ฐ€ ์ œ๊ณต๋˜์ง€ ์•Š์€ ๊ฒฝ์šฐ ์•„๋ฌด๋Ÿฐ ๋ฉ”์‹œ์ง€๋„ ๋Œ€๊ธฐ์—ด์— ์ถ”๊ฐ€๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๋ฃจํ”„์—์„œ ๋Œ€๊ธฐ์—ด์€ ๋‹ค์Œ ๋ฉ”์‹œ์ง€ ( ๊ฐ polling์„ "tick"์ด๋ผ๊ณ  ํ•จ)์— ๋Œ€ํ•ด polling๋˜๊ณ  ๋ฉ”์‹œ์ง€๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ํ•ด๋‹น ๋ฉ”์‹œ์ง€์— ๋Œ€ํ•œ ์ฝœ๋ฐฑ์ด ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

์ด ์ฝœ๋ฐฑ ํ•จ์ˆ˜์˜ ํ˜ธ์ถœ์€ ํ˜ธ์ถœ ์Šคํƒ์˜ ์ดˆ๊ธฐ ํ”„๋ ˆ์ž„์œผ๋กœ ์‚ฌ์šฉ๋˜๋ฉฐ JavaScript๊ฐ€ single-threaded์ด๋ฏ€๋กœ ์Šคํƒ์˜ ๋ชจ๋“  ํ˜ธ์ถœ์ด ๋ฐ˜ํ™˜ ๋  ๋•Œ๊นŒ์ง€ ์ถ”๊ฐ€ ๋ฉ”์‹œ์ง€ polling ๋ฐ ์ฒ˜๋ฆฌ๊ฐ€ ์ค‘๋‹จ๋ฉ๋‹ˆ๋‹ค. ํ›„์†(๋™๊ธฐ)ํ•จ์ˆ˜ ํ˜ธ์ถœ์€ ์ƒˆ๋กœ์šด ํ˜ธ์ถœ ํ”„๋ ˆ์ž„์„ ์Šคํƒ์— ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค (์˜ˆ : function init์€ function changeColor๋ฅผ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค).

  function init() {
    var link = document.getElementById("foo");

    link.addEventListener("click", function changeColor() {
      this.style.color = "burlywood";
    });
  }
  init();

์ด ์˜ˆ์ œ์—์„œ ์‚ฌ์šฉ์ž๊ฐ€ 'foo'์š”์†Œ๋ฅผ ํด๋ฆญํ•˜๊ณ  "onclick"์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ๋ฉ”์‹œ์ง€(์ฝœ๋ฐฑ, changeColor)๊ฐ€ ๋Œ€๊ธฐ์—ด์— ํฌํ•จ๋ฉ๋‹ˆ๋‹ค. ๋ฉ”์‹œ์ง€๊ฐ€ ๋Œ€๊ธฐ์—ด์—์„œ ์ œ์™ธ๋˜๋ฉด ์ฝœ๋ฐฑ ํ•จ์ˆ˜ changeColor๊ฐ€ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค. changeColor๊ฐ€ return๋˜๋ฉด (๋˜๋Š” ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด) ์ด๋ฒคํŠธ ๋ฃจํ”„๊ฐ€ ๊ณ„์†๋ฉ๋‹ˆ๋‹ค. 'foo'์š”์†Œ์— ๋Œ€ํ•œ onclick ์ฝœ๋ฐฑ์œผ๋กœ ์ง€์ •๋œ changeColor ํ•จ์ˆ˜๊ฐ€ ์žˆ์œผ๋ฉด ํ•ด๋‹น ์š”์†Œ๋ฅผ ๊ณ„์† ํด๋ฆญํ•˜๋ฉด ๋” ๋งŽ์€ ๋ฉ”์‹œ์ง€(์—ฐ๊ด€๋œ ์ฝœ๋ฐฑ changeColor)๊ฐ€ ๋Œ€๊ธฐ์—ด์— ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.

Queuing Additional Messages

์ฝ”๋“œ์— ํ˜ธ์ถœ ๋œ ํ•จ์ˆ˜๊ฐ€ ๋น„๋™๊ธฐ์‹ (setTimeout๊ณผ ๊ฐ™์€)์ด๋ฉด ์ œ๊ณต๋œ ์ฝœ๋ฐฑ์€ ์ด๋ฒคํŠธ ๋ฃจํ”„์˜ ํ–ฅํ›„ ํ‹ฑ์—์„œ ๋‹ค๋ฅธ ๋Œ€๊ธฐ์—ด ๋ฉ”์‹œ์ง€์˜ ์ผ๋ถ€๋กœ ๊ถ๊ทน์ ์œผ๋กœ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค๋ฉด :

  function f() {
    console.log("foo");
    setTimeout(g, 0);
    console.log("baz");
    h();
  }

  function g() {
    console.log("bar");
  }

  function h() {
    console.log("blix");
  }

  f();

setTimeout์˜ non-blocking ์†์„ฑ์œผ๋กœ ์ธํ•ด ํ•ด๋‹น ์ฝœ๋ฐฑ์€ ์ตœ์†Œ 0 ๋ฐ€๋ฆฌ ์ดˆ๋ฅผ ์‹œ์ž‘ํ•˜๋ฉฐ ์ด ๋ฉ”์‹œ์ง€์˜ ์ผ๋ถ€๋กœ ์ฒ˜๋ฆฌ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
์ด ์˜ˆ์ œ์—์„œ setTimeout์€ ์ฝœ๋ฐฑ ํ•จ์ˆ˜ g์™€ 0 ๋ฐ€๋ฆฌ ์ดˆ์˜ ํƒ€์ž„ ์•„์›ƒ์„ ์ „๋‹ฌํ•˜์—ฌ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค. ์ง€์ •๋œ ์‹œ๊ฐ„์ด ๊ฒฝ๊ณผํ•˜๋ฉด (์ด ๊ฒฝ์šฐ ๊ฑฐ์˜ ์ฆ‰์‹œ) ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋กœ g๋ฅผ ํฌํ•จํ•˜๋Š” ๋ณ„๋„์˜ ๋ฉ”์‹œ์ง€๊ฐ€ ๋Œ€๊ธฐ์—ด์— ํฌํ•จ๋ฉ๋‹ˆ๋‹ค. console ๊ฒฐ๊ณผ๋Š” "foo", "baz", "blix" ๊ทธ๋ฆฌ๊ณ  ์ด๋ฒคํŠธ ๋ฃจํ”„์˜ ๋‹ค์Œ ํ‹ฑ์ธ "bar"์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๋™์ผํ•œ ํ˜ธ์ถœ ํ”„๋ ˆ์ž„์—์„œ ๋‘ ๋ฒˆ์งธ ์ธ์ˆ˜์— ๋Œ€ํ•ด ๋™์ผํ•œ ๊ฐ’์„ ์ „๋‹ฌํ•˜๋Š” setTimeout์— ๋‘ ๋ฒˆ์˜ ํ˜ธ์ถœ์ด ์ˆ˜ํ–‰๋˜๋ฉด ํ•ด๋‹น ํ˜ธ์ถœ์˜ ์ˆœ์„œ๋Œ€๋กœ ๋Œ€๊ธฐ์—ด์— ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

Web Workers

Web Workers๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋ณ„๋„์˜ ์‹คํ–‰ ์Šค๋ ˆ๋“œ๋กœ ๋ถ„์‚ฐํ•˜์—ฌ ๋ฉ”์ธ ์Šค๋ ˆ๋“œ๋ฅผ ์ž์œ ๋กญ๊ฒŒํ•˜์—ฌ ๋‹ค๋ฅธ ์ž‘์—…์„ ์ˆ˜ํ–‰ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Worker๋Š” ๋ณ„๋„์˜ ๋ฉ”์‹œ์ง€ ๋Œ€๊ธฐ์—ด, ์ด๋ฒคํŠธ ๋ฃจํ”„ ๋ฐ ์ด๋ฅผ ์ธ์Šคํ„ด์Šคํ™” ํ•œ ์›๋ž˜ ์Šค๋ ˆ๋“œ์™€ ๋ณ„๊ฐœ์˜ ๋ฉ”๋ชจ๋ฆฌ ๊ณต๊ฐ„์„ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค. Worker์™€ ์ฃผ ์Šค๋ ˆ๋“œ ๊ฐ„์˜ ์˜์‚ฌ ์†Œํ†ต์€ ๋ฉ”์‹œ์ง€ ์ „๋‹ฌ์„ ํ†ตํ•ด ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค. ์ด๋Š” ๊ธฐ์กด์— ๋ฐœ์ƒํ–ˆ๋˜ ์ฝ”๋“œ ์˜ˆ์ œ์™€ ๋งค์šฐ ํก์‚ฌํ•ฉ๋‹ˆ๋‹ค.

์ฒซ์งธ, our worker:

  // our worker, which does some CPU-intensive operation
  var reportResult = function(e) {
    pi = SomeLib.computePiToSpecifiedDecimals(e.data);
    postMessage(pi);
  };

  onmessage = reportResult;

๊ทธ๋Ÿฐ ๋‹ค์Œ HTML์˜ ์Šคํฌ๋ฆฝํŠธ ํƒœ๊ทธ์— ์žˆ๋Š” ์ฝ”๋“œ์˜ ์ฃผ์š” ๋ฌถ์Œ :

  // our main code, in a <script>-tag in our HTML page
  var piWorker = new Worker("pi_calculator.js");
  var logResult = function(e) {
    console.log("PI: " + e.data);
  };

  piWorker.addEventListener("message", logResult, false);
  piWorker.postMessage(100000);

์ด ์˜ˆ์ œ์—์„œ ์ฃผ ์Šค๋ ˆ๋“œ๋Š” Worker๋ฅผ ์ƒ์„ฑํ•˜๊ณ  logResult ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ "message"์ด๋ฒคํŠธ์— ๋“ฑ๋กํ•ฉ๋‹ˆ๋‹ค. Worker์—์„œ reportResult ํ•จ์ˆ˜๋Š” ์ž์ฒด "message"์ด๋ฒคํŠธ์— ๋“ฑ๋ก๋ฉ๋‹ˆ๋‹ค. Worker ์Šค๋ ˆ๋“œ๊ฐ€ ์ฃผ ์Šค๋ ˆ๋“œ์—์„œ ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐ›์œผ๋ฉด ์ž‘์—…์ž๋Š” ๋ฉ”์‹œ์ง€์™€ ํ•ด๋‹น reportResult ์ฝœ๋ฐฑ์„ ๋Œ€๊ธฐ์—ด์— ๋„ฃ์Šต๋‹ˆ๋‹ค. ๋Œ€๊ธฐ์—ด์—์„œ ๋น ์ ธ ๋‚˜์˜ค๋ฉด (logResult ์ฝœ๋ฐฑ๊ณผ ํ•จ๊ป˜) ์ƒˆ ๋ฉ”์‹œ์ง€๊ฐ€ ๋Œ€๊ธฐ์—ด์— ํฌํ•จ๋˜๋Š” ๊ธฐ๋ณธ ์Šค๋ ˆ๋“œ๋กœ ๋ฉ”์‹œ์ง€๊ฐ€ ๋‹ค์‹œ ๊ฒŒ์‹œ๋ฉ๋‹ˆ๋‹ค. ์ด ๋ฐฉ๋ฒ•์œผ๋กœ ๊ฐœ๋ฐœ์ž๋Š” CPU ์ง‘์•ฝ์ ์ธ ์ž‘์—…์„ ๋ณ„๋„์˜ ์Šค๋ ˆ๋“œ๋กœ ์œ„์ž„ํ•˜์—ฌ ๋ฉ”์‹œ์ง€ ์ฒ˜๋ฆฌ ๋ฐ ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ๋ฅผ ๊ณ„์†ํ•˜๊ธฐ ์œ„ํ•ด ์ฃผ ์Šค๋ ˆ๋“œ๋ฅผ ํ•ด์ œ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํด๋กœ์ €์— ๋Œ€ํ•œ ์ฐธ๊ณ  ์‚ฌํ•ญ

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ ํด๋กœ์ €๋Š” ์ฝœ๋ฐฑ์˜ ์‹คํ–‰์ด ์™„์ „ํžˆ ์ƒˆ๋กœ์šด ์ฝœ ์Šคํƒ์„ ์ƒ์„ฑํ•˜๋”๋ผ๋„ ์ƒ์„ฑ ๋œ ํ™˜๊ฒฝ์— ๋Œ€ํ•œ ์•ก์„ธ์Šค๋ฅผ ์œ ์ง€ํ•˜๋ฉด์„œ ์‹คํ–‰ํ•  ๋•Œ ์ฝœ๋ฐฑ์„ ๋“ฑ๋ก ํ•  ์ˆ˜์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค. ํŠนํžˆ ์ฝœ๋ฐฑ์ด ์ƒ์„ฑ ๋œ ๋ฉ”์‹œ์ง€์™€ ๋‹ค๋ฅธ ๋ฉ”์‹œ์ง€์˜ ์ผ๋ถ€๋กœ ์ฝœ๋ฐฑ์ด ํ˜ธ์ถœ๋œ๋‹ค๋Š” ์‚ฌ์‹ค์„ ์•Œ๊ณ  ์žˆ์–ด์•ผํ•ฉ๋‹ˆ๋‹ค. ๋‹ค์Œ ์˜ˆ์ œ๋ฅผ ๊ณ ๋ คํ•˜์‹ญ์‹œ์˜ค.

  function changeHeaderDeferred() {
    var header = document.getElementById("header");
    
    setTimeout(function changeHeader() {
      header.style.color = "red";

      return false;
    }, 100);

    return false;
  }

  changeHeaderDeferred();

์ด ์˜ˆ์ œ์—์„œ๋Š” ๋ณ€์ˆ˜ header๋ฅผ ํฌํ•จํ•˜๋Š” changeHeaderDeferred ํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. setTimeoutํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋˜์–ด ํ–ฅํ›„ ๋ฉ”์‹œ์ง€ ๋Œ€๊ธฐ์—ด์— ์•ฝ 100๋ฐ€๋ฆฌ ์ดˆ(0.1์ดˆ)์˜ ๋ฉ”์‹œ์ง€๊ฐ€ ์ถ”๊ฐ€๋ฉ๋‹ˆ๋‹ค(changeHeader ์ฝœ๋ฐฑ ํฌํ•จ). ๊ทธ๋Ÿฐ ๋‹ค์Œ changeHeaderDeferred ํ•จ์ˆ˜๋Š” false๋ฅผ ๋ฐ˜ํ™˜ํ•˜์—ฌ ์ฒซ ๋ฒˆ์งธ ๋ฉ”์‹œ์ง€์˜ ์ฒ˜๋ฆฌ๋ฅผ ๋๋‚ด์ง€๋งŒ header๋ณ€์ˆ˜๋Š” ์—ฌ์ „ํžˆ ํด๋กœ์ €๋ฅผ ํ†ตํ•ด ์ฐธ์กฐ๋˜๋ฉฐ garbage collection์— ์ˆ˜์ง‘๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋‘ ๋ฒˆ์งธ ๋ฉ”์‹œ์ง€๊ฐ€ ์ฒ˜๋ฆฌ ๋  ๋•Œ (changeHeader ํ•จ์ˆ˜) ์™ธ๋ถ€ ํ•จ์ˆ˜์˜ ๋ฒ”์œ„์— ์„ ์–ธ ๋œ header ๋ณ€์ˆ˜์— ๋Œ€ํ•œ ์•ก์„ธ์Šค๋ฅผ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค. ๋‘ ๋ฒˆ์งธ ๋ฉ”์‹œ์ง€ (changeHeader ํ•จ์ˆ˜)๊ฐ€ ์ฒ˜๋ฆฌ๋˜๋ฉด ํ—ค๋” ๋ณ€์ˆ˜๊ฐ€ garbage collection์— ์ˆ˜์ง‘ ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Takeaways

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ ์ด๋ฒคํŠธ ์ค‘์‹ฌ ์ƒํ˜ธ ์ž‘์šฉ ๋ชจ๋ธ์€ ๋งŽ์€ ํ”„๋กœ๊ทธ๋ž˜๋จธ๋“ค์ด ์ต์ˆ™ํ•œ ์š”์ฒญ ์‘๋‹ต ๋ชจ๋ธ๊ณผ ๋‹ค๋ฆ…๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๋ณด๋‹ค์‹œํ”ผ ๋กœ์ผ“ ๊ณผํ•™??์€ ์•„๋‹™๋‹ˆ๋‹ค. ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋Š” ๊ฐ„๋‹จํ•œ ๋ฉ”์„ธ์ง€ ๋Œ€๊ธฐ์—ด ๋ฐ ์ด๋ฒคํŠธ ๋ฃจํ”„๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐœ๋ฐœ์ž๊ฐ€ ๋น„๋™๊ธฐ์‹ ์ฝœ๋ฐฑ์„ ์ค‘์‹ฌ์œผ๋กœ ์‹œ์Šคํ…œ์„ ๊ตฌ์ถ•ํ•จ์œผ๋กœ์จ ์™ธ๋ถ€ ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฌ๋Š” ๋™์•ˆ ๋™์‹œ ์ž‘์—…์„ ์ฒ˜๋ฆฌํ•˜๋„๋ก ๋Ÿฐํƒ€์ž„์„ ๋น„์šธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๊ทธ๋Ÿฌ๋‚˜ ์ด๊ฒƒ์€ ๋™์‹œ์„ฑ์— ๋Œ€ํ•œ ํ•˜๋‚˜์˜ ์ ‘๊ทผ ๋ฐฉ์‹์— ์ง€๋‚˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
์ด ๊ฒŒ์‹œํŒ์˜ ๋‘ ๋ฒˆ์งธ ๋ถ€๋ถ„์—์„œ๋Š” ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ ๋™์‹œ์„ฑ ๋ชจ๋ธ์„ MRI Ruby(with threads and the GIL), EventMachine(Ruby), Java(threads)์—์„œ ๋ณผ ์ˆ˜ ์žˆ๋Š” ๊ฒƒ๊ณผ ๋น„๊ตํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

Additional Reading

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