ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Asynchronous JavaScript (1) - 싱글 스레드, blocking(블로킹) 현상
    JavaScript 2021. 8. 16. 23:30

     

     

    🌱 공부 주제: 싱글 스레드, 동기적 프로그래밍, 동기적 프로그래밍에서 발생하는 문제

    📝 공부를 하게 된 동기: 자바스크립트랑 관련있고 async await 검색하다가 단번에 이해가 안되서 

    ✅ 공부 자료: MDN - General asynchronous programming concepts, MDN - Asynchronous JavaScript, JAVASCRIPT.INFO - Introduction: callbacks

     

    Introduction: callbacks

     

    javascript.info

     

     

    1. 스레드(Thread)란?

    • 프로그램이 작업을 완료하는데 사용할 수 있는 단일 프로세스
    • 하나의 스레드는 '순차적으로' '한 번에 하나의 작업만' 수행한다.작업 A -> 작업 B -> 작업 C

    위와 같이 한 번에 하나씩, 순차적으로 실행된다.
    즉, 앞의 작업이 완료 되어야 다음 작업을 실행할 수 있다.

     

     

    2. '자바스크립트는 전통적으로 싱글 스레드이다.'

    그래서 아무리 여러 개의 CPU를 컴퓨터가 가지고 있어도 main thread라고 불리는 단일 thread에서만 작업을 실행할 수 있다.
    (정리: main-thread에서 코드를 순서대로, 한 번에 한 가지 작업만 처리)

     

    이렇게 싱글 스레드인 자바스크립트에 동기적 코드만 작성하면 문제가 발생한다.

    *동기적 코드의 장점: 설계가 단순. A가 처리되어야 B를 작업하고 B가 처리되면 C를 작업하는 식. A의 리턴값을 B나 C에서 써도 문제가 되지 않음. 순차적으로 처리하기 때문에 A의 리턴값은 무조건 할당된 상태가 보장되기 때문.

    *동기적 코드의 단점: A의 처리시간이 길게 된다면 그만큼 B의 작업은 미뤄짐. 이때 브라우저가 먹통이 된것처럼 보이는데 이를 블로킹이라 함. 

     

    3. 동기적 프로그래밍의 문제 예시

    예시1. blocking 현상
    웹앱이 특정 코드를 실행하는데 시간이 오래 걸리면 제어권을 브라우저에게 돌려주지 않는 일이 발생할 수 있다. 이때 브라우저는 마치 정지된 것처럼 보이는데, 이것을 블로킹 현상이라고 한다.

    MDN에서 제공한 예시는 아래와 같다.

    하나의 버튼에 클릭 이벤트리스너를 지정하여 시간이 오래 걸리는 처리를 하도록하였습니다. (날짜를 천만번 계산하고 마지막에 콘솔에 날짜를 출력합니다.) 그리고 처리가 끝나면 페이지에 간단한 문장을 한 줄 출력합니다. :

     

     

     

    앞에서도 말했듯이 자바스크립트 코드는 위에서 아래로 차례대로 실행된다. 위쪽 코드 작업이 끝나야 아래쪽 코드가 실행된다. 그렇다보니 위쪽에 쓰여진 작업을 실행하는데 시간이 오~~~래 걸리면 아래쪽 코드는 작동하지 못하고 그냥 기다리고만 있다.

    이러한 문제를 해결하기 위해 자바스크립트에 도입한 툴 중 하나가 Web workers이다. worker라는 별도의 스레드를 만들어서, 시간이 오래걸리는 작업은 worker가 처리하게 한다. 그러면 위에서 걱정했던 blocking 현상을 해결할 수 있는 것이다!

     

    //index.js
    
    const btn = document.querySelector('button');
    const worker = new Worker('worker.js');
    btn.addEventListener('click', () => {
    worker.postMessage('Go!');
    let pElem = document.createElement('p');
    pElem.textContent = 'This is a newly-added paragraph.';
    document.body.appendChild(pElem);
    });
    worker.onmessage = function(e) {
    console.log(e.data);
    }
    // worker.js
    
    onmessage = function() {
      let myDate;
      for(let i = 0; i < 10000000; i++) {
        let date = new Date();
        myDate = date
      }
    
      postMessage(myDate);
    }

    Web worker를 사용하지 않아을 때는, 날짜를 천만 번 계산하고나서 페이지에 문장이 출력되었다. 하지만 Web worker를 사용하면 날짜를 계산하기 전에 문장을 페이지에 출력한다. 즉, 더이상 아랫줄 코드의 진행을 차단하지 않는 것이다!!!


    이 Web worker 꽤 유용하지만 역시나.. 한계가 있다.

    1. DOM에 접근할 수 없다.
      단순히 숫자 계산은 가능했지만, UI를 업데이트 하는 작업은 불가능하다.
    2. worker 안에서 실행되는 코드는 차단되지는 않지만 동기적으로 실행된다. 이렇게 되면 함수를 사용할 때 문제가 생긴다. 여기서 Task D가 Task B와 Task C의 결과를 모두 사용한다고 가정해보자.
      Task B와 Task C가 동시에! 아주 빠르게! 결과를 반환하면 매우 이상적일 것이다. 하지만 당연히 현실은 그렇지 않다. Task D가 실행될 때, Task B나 Task C 둘 중 어느 값이라도 아직 준비가 되지 않은 경우, 에러가 발생한다.
    3. Main thread: Task A --> Task B --> |Task D|
      Worker thread: Task C -----------> | |




    그러면 어떻게 이런 문제들을 해결하면서도 비동기적으로 작업을 처리할 수 있을까?
    => callback and promise !!!

     

    *비동기적  코드의 장점 : A작업이 완료되기까지 기다리고만 있지 않고 D작업 F작업 등 다른 작업을 시작한다. 전체 퍼포먼스 속도가 증가.

    A작업이 완료되기 전, A값의 결과가 다른 작업에 필요한 경우 할당되지 않는 치명적 오류. 이를 해결하는 다른 추가작업이 필요하다.

    *비동기적 코드의 단점 : 그래서 설계가 어렵다. 이렇게 개념공부를 해야한다.

    'JavaScript' 카테고리의 다른 글

    React. 쉬운 시작. 마인드 셋.  (0) 2024.04.27
    javascript 변수  (0) 2023.01.27
    로그인 구현  (0) 2021.08.15
    OR 연산자의 피연산자가 alert 라면?  (0) 2021.08.15
    비교 연산자  (0) 2021.08.12

    댓글

Designed by Tistory.