πŸ±μžλ°”μŠ€ν¬λ¦½νŠΈ 비동기

2019. 03. 16

sat10am

Seungwoo Hong

😎 μžλ°”μŠ€ν¬λ¦½νŠΈμ˜ 비동기

: Part 1

🏁 μ‹œμž‘ λΆ€ν„°

😎 μžλ°”μŠ€ν¬λ¦½νŠΈλŠ” μ‹±κΈ€μŠ€λ ˆλ“œ!

😎 μžλ°”μŠ€ν¬λ¦½νŠΈλŠ” μ‹±κΈ€μŠ€λ ˆλ“œ!

μ‹±κΈ€ μŠ€λ ˆλ“œ == μŠ€νƒμ΄ ν•˜λ‚˜ == ν•œ λ²ˆμ— ν•˜λ‚˜μ˜ 일만 ν•œλ‹€.

    
    function add(x, y) {
        return x + y;
    } 
    
    function printAddedNumber() {
        let sum = add(1, 2);
    
        console.log(sum);
    }
    
    
    printAddedNumber();

✌️ Example code

πŸ“š Call stack

step 을 ν•˜λ‚˜ ν•˜λ‚˜λ₯Ό Stack frame이라 ν•œλ‹€.

πŸƒβ€β™€οΈ Run to completion

μ‹€ν–‰ 되고 μžˆλŠ” μž‘μ—…μ΄ μžˆλ‹€λ©΄ λ‹€λ₯Έ μž‘μ—…μ€ 쀑간에 끼어듀 수 μ—†λ‹€.

그런데 μŠ€νƒ 처리 μ‹œκ°„μ΄ 였래 걸리면?

😩 κ·Έλƒ₯ λŒ€κΈ°γ… γ… 

😩 μ•„λ‹ˆ 그럼 λ™μ‹œμ„±μ„ 지원 μ•ˆν•΄?

πŸ‘ The solution

Asynchronous Callback !!

(비동기 콜백)

🐝 Runtime

    
    console.log('foo');
    
    setTimeout(function() {
        console.log('bar')
    }, 10 * 1000);
    
    console.log('baz');

✌️ Example code

πŸ€– Role

Call Stack - ν•¨μˆ˜κ°€ 호좜 되면 상단에 Push, μ’…λ£Œλ˜λ©΄ pop

Heap - λ©”λͺ¨λ¦¬ 할당이 μΌμ–΄λ‚˜λŠ” κ³³

Task queue - 전달 받은 μ½œλ°±ν•¨μˆ˜λ₯Ό μ €μž₯ν•˜λŠ” 큐(FIFO)

Event loop - Call stack을 κ°μ‹œ, λΉ„μ–΄ 있으면 콜백 전달

πŸŽƒ Event loop

    
    while(queue.waitForMessage()){
      queue.processNextMessage();
    }

Β  waitForMessage() 의 역할은 λ‹€μŒκ³Ό κ°™λ‹€

Β  1. ν…ŒμŠ€ν¬κ°€ λ“€μ–΄ μ˜¬λ•ŒκΉŒμ§€ κΈ°λ‹€λ¦¬λŠ” 역할을 ν•œλ‹€.

Β  2. μ‹€ν–‰ 쀑인 ν…ŒμŠ€ν¬ 큐가 μžˆλŠ”μ§€ κ°μ‹œ

Β 

이벀트 νλŠ” μœ„μ™€ 같은 역할을 반볡 μˆ˜ν–‰ ν•˜μ—¬ ν…ŒμŠ€ν¬λ₯Ό μŠ€νƒμ— μ „λ‹¬ν•œλ‹€.

πŸŽƒ Event loop

    
    function delay() {
        for (var i = 0; i < 100000; i++);
    }
    function foo() {
        delay();
        console.log('foo!');
    }
    function bar() {
        delay();
        console.log('bar!');
    }
    function baz() {
        delay();
        console.log('baz!');
    }
    
    setTimeout(foo, 10);
    setTimeout(bar, 10);
    setTimeout(baz, 10);

Β - μžλ°”μŠ€ν¬λ¦½νŠΈλŠ” μ‹±κΈ€ μŠ€λ ˆλ“œμ΄λ‹€.

Β - λ™μ‹œμ„±μ„ κ΅¬ν˜„ν•˜κΈ° μœ„ν•΄ μ½œλ°±μ„ μ‚¬μš©

Β - μžλ°”μŠ€ν¬λ¦½νŠΈ 엔진은 Heap, Stack, Event loop, Task Queueκ°€ 쑴재

Β - λ™μž‘ μˆœμ„œ

Β  Β  1. κΈ°λ³Έ ν•¨μˆ˜λŠ” μŠ€νƒμ— μŒ“μ΄κ³  μ’…λ£Œ 되면 μŠ€νƒμ„ λΉ μ Έλ‚˜μ˜¨λ‹€.

Β  Β  2. 비동기 μ½œλ°±μ€ μŠ€νƒμ— μž μ‹œ μŒ“μΈλ‹€. 그리고 λ°”λ‘œ λΉ μ Έλ‚˜μ™€ λ°μŠ€ν¬νμ— μΆ”κ°€ λœλ‹€.

Β  Β  3. 콜백 ν•¨μˆ˜κ°€ μ‹€ν–‰ 될 μ‹œμ μ΄ 되면 이벀트 λ£¨ν”„λŠ” call stack이 λΉ„μ–΄ μžˆλŠ” κ±Έ 확인 ν•˜κ³  읡λͺ…ν•¨μˆ˜λ₯ΌΒ  Β  Β  Β  Β  Β  Β  μ§‘μ–΄λ„£κ³  읡λͺ… ν•¨μˆ˜λŠ” μ‹€ν–‰ ν›„ call stack을 λΉ μ Έλ‚˜μ˜¨λ‹€. (이벀트 λ£¨ν”„μ˜ μž‘μ—…μ„ tick이라고 뢀름)

🐹 Summary

Β πŸ‘Ύ Callback function

콜백 ν•¨μˆ˜λž€ ν•¨μˆ˜μ˜ 인자둜 전달 λ˜μ–΄ μ΄λ²€νŠΈκ°€ λ°œμƒ 되면

ν•„μš”μ— 따라 μ¦‰μ‹œ μ‹€ν–‰ 될 μˆ˜λ„ λ‚˜μ€‘μ— μ‹€ν–‰ 될 μˆ˜λ„ μžˆλŠ” ν•¨μˆ˜

🐢 비동기 vs 동기

동기 - μ‹œκ°„ 흐름 순으둜 μž‘μ—…μ΄Β  μ§„ν–‰ 되며 μ§„ν–‰ 쀑인 μž‘μ—…μ΄ μ™„λ£Œ λ λ•Œ κΉŒμ§€

Β  Β  Β  Β  Β  λ‹€λ₯Έ μž‘μ—… 이 쀑간에 선점 ν•˜μ§€ λͺ»ν•œλ‹€.

Β 

비동기 - μž‘μ—…μ΄ μ™„λ£Œ λ˜μ§€ μ•Šμ€ μƒνƒœμ—μ„œ ν•΄λ‹Ή μž‘μ—…μ„ λ‹€λ₯Έ μ΄μ—κ²Œ μœ„μž„ν•˜κ³  λ‹€μŒ

Β  Β  Β  Β  Β  Β  Β μž‘μ—…μ„ μ§„ν–‰ ν•œλ‹€.  그리고 μœ„μž„ν•œ μž‘μ—…μ΄ μ™„λ£Œ 되면 μž‘μ—…μ„ 결과물을 κ°€μ Έμ˜¨λ‹€.

πŸ‘½ 동기 콜백

콜백 ν•¨μˆ˜λž€ ν•¨μˆ˜μ˜ 인자둜 전달 λ˜μ–΄ μ΄λ²€νŠΈκ°€ λ°œμƒ 되면

μ¦‰μ‹œ μ‹€ν–‰λ˜λŠ” ν•¨μˆ˜

πŸ‘½ 동기 콜백

    
    function greeting(name) {
        console.log(`hello ${name}`);
    }
    
    function processUserName(name, callback) {
        callback(name);
    }

    console.log('hi');
    processUserName('hong', greeting)
    console.log('again hi');

😼 비동기 콜백

콜백 ν•¨μˆ˜λž€ ν•¨μˆ˜μ˜ 인자둜 전달 λ˜μ–΄ μ΄λ²€νŠΈκ°€ λ°œμƒ 되면

λ‚˜μ€‘μ— μ‹€ν–‰ 될 μˆ˜λ„ μžˆλŠ” ν•¨μˆ˜

😼 비동기 콜백

    
    console.log('hi');
    setTimeout(function() {
        console.log('see you later')
    }, 1000)
    console.log('again hi');

😼 비동기 콜백 사둀

Β - Web API

Β - AJAX

Β - DOM

πŸ‘Ώ μ½œλ°±ν•¨μˆ˜μ˜ ν•œκ³„

Β - Callback hell

Β - μ˜ˆμ™Έ 처리

πŸ‘Ώ Callback hell

5κΉŒμ§€ 1μ΄ˆλ§ˆλ‹€ 1μ”© λ”ν•˜κ³  μ‹Άλ‹€.

setTimeout(function() {
  let sum = 1;
  console.log(sum, "초");

  setTimeout(function() {
    sum += 1;
    console.log(sum, "초");

    setTimeout(function() {
      sum += 1;
      console.log(sum, "초");

      setTimeout(function() {
        sum += 1;
        console.log(sum, "초");

        setTimeout(function() {
          sum += 1;

          console.log("sum:", sum);
        }, 1000);
      }, 1000);
    }, 1000);
  }, 1000);
}, 1000);

πŸ‘Ώ Callback hell ν•΄κ²°

let sum = 1;

function start() {
  console.log(sum, "초");
  setTimeout(firstPlus, 1000);
}

function firstPlus() {
  sum += 1;
  console.log(sum, "초");

  setTimeout(secondPlus, 1000);
}

function secondPlus() {
  sum += 1;
  console.log(sum, "초");

  setTimeout(thirdPlus, 1000);
}

function thirdPlus() {
  sum += 1;
  console.log(sum, "초");

  setTimeout(fourthPlus, 1000);
}

function fourthPlus() {
  sum += 1;
  console.log("sum:", sum);
}

setTimeout(start, 1000);

πŸ‘Ώ μ˜ˆμ™Έμ²˜λ¦¬

Β 

❗️ 였λ₯˜λ₯Ό 감지λ₯Ό λͺ»ν•˜λ‹€λ‹ˆ..

    
    try {
        setTimeout(function() {
            throw 'error'; 
        }, 10)
    } catch(e) {
         console.log(e);   
         console.log('μ—λŸ¬ μž‘μ•˜λ‹€');
    }

πŸ‘Ώ μ˜ˆμ™Έ 처리 였λ₯˜ ν•΄κ²°1

Β 

비동기 ν•¨μˆ˜ μ•ˆμ—μ„œ μ˜ˆμ™Έμ²˜λ¦¬

    
    setTimeout(function() {
        try {
            throw 'error'; 
            
        } catch(e) {
             console.log(e);   
             console.log('μ—λŸ¬ μž‘μ•˜λ‹€');
        }
    }, 10);

πŸ‘Ώ μ˜ˆμ™Έ 처리 였λ₯˜ ν•΄κ²°2

    
    function errorHandler(process) {
      return function() {
        try{
          return process.apply(this, arguments);
          console.log(arguments);
    
        } catch(e) {
          console.log(e);
          console.log('μ—λŸ¬μ—μ„œ 볡ꡬ됐닀.');
        }
      };
    }
    
    setTimeout(errorHandler(function() {
      throw 'μ—λŸ¬κ°€ λ°œμƒν–ˆλ‹€!';
    }), 1000);
    

🐹 Summary

Β - 콜백 ν•¨μˆ˜λž€ ν•¨μˆ˜μ˜ 인자둜 전달 λ˜μ–΄ μ΄λ²€νŠΈκ°€ λ°œμƒ 되면

Β  Β  λ‚˜μ€‘μ— μ‹€ν–‰ 될 μˆ˜λ„ μžˆλŠ” ν•¨μˆ˜

Β - 동기 콜백과 비동기 콜백이 μžˆλ‹€.

Β - DOM, AJAX, Web APIμ—μ„œ μœ μš©ν•˜κ²Œ μ‚¬μš©λœλ‹€.

Β - 콜백 μ§€μ˜₯κ³Ό μ˜ˆμ™Έ 처리 였λ₯˜ λ¬Έμ œκ°€ μžˆλ‹€

Β