모던 자바스크립트 Deep Dive 42장 비동기 프로그래밍

차차·2024년 1월 22일
post-thumbnail

비동기 처리

함수를 호출하면 발생하는 일

  1. 함수 코드가 평가되어 함수 실행 컨텍스트가 생성됨
  2. 생성된 함수 실행 컨텍스트는 실행 컨텍스트 스택(=콜스택)에 푸시되고, 함수 코드 실행
  3. 함수 코드의 실행이 종료하면 함수 실행 컨텍스트는 실행 컨텍스트 스택에서 팝되어 제거

자바스크립트 엔진은 한 번에 하나의 태스크만 실행하는 싱글 스레드 방식으로 동작함
=동시에 두 개 이상의 함수를 실행할 수 없고
=처리에 시간이 걸리는 태스크를 실행하는 경우 블로킹(작업 중단)이 발생함

동기 처리 방식 예시

// sleep 함수는 일정 시간(delay)이 경과한 이후에 콜백 함수(func)를 호출한다.
function sleep(func, delay) {
  // Date.now()는 현재 시간을 숫자(ms)로 반환한다.("30.2.1. Date.now" 참고)
  const delayUntil = Date.now() + delay;

  // 현재 시간(Date.now())에 delay를 더한 delayUntil이 현재 시간보다 작으면 계속 반복한다.
  while (Date.now() < delayUntil);
  // 일정 시간(delay)이 경과한 이후에 콜백 함수(func)를 호출한다.
  func();
}

function foo() {
  console.log('foo');
}

function bar() {
  console.log('bar');
}

// sleep 함수는 3초 이상 실행된다..
sleep(foo, 3 * 1000);
// bar 함수는 sleep 함수의 실행이 종료된 이후에 호출되므로 3초 이상 블로킹된다.
bar();
// (3초 경과 후) foo 호출 -> bar 호출

이 예제에서 sleep 함수는 3초 후에 foo 함수를 호출
따라 bar 함수는 3초동안 호출되지 못하고 블로킹됨
이처럼 현재 실행 중인 태스크가 종료할 때까지 다음에 실행될 태스크가 대기하는 방식이 동기 처리

비동기 처리 방식 예시
같은 상황을 비동기 방식으로 처리하는 예제

function foo() {
  console.log('foo');
}

function bar() {
  console.log('bar');
}

setTimeout(foo, 3*1000);
bar();

//출력결과:
//bar
//(3초 후) foo

앞의 예시와 동일하게 일정 시간 경과 이후 콜백함수를 호출하지만
setTimeout함수 이후의 bar 함수의 실행을 블로킹하지 않음
이처럼 현재 실행 중인 태스크가 종료 되지 않은 상태라 해도 다음 태스크를 바로 실행하는 방식이 비동기 처리

비동기 처리를 수행하는 함수는 콜백 패턴을 사용하는데, 여기서 발생하는 여러 단점을 보완하고자 '프로미스 Promise'가 사용됨

타이머 함수인 setTimeout과 setInterval, HTTP요정, 이벤트 핸들러는 비동기처리 방식으로 동작하는데 비동기처리는 이벤트 루프와 태스크 큐와 깊은 관련이 있음

이벤트 루프와 태스크 큐

자바스크립트는 싱글 스레드로 동작하지만, 브라우저의 동작을 살펴보면 여러 태스크가 동시에 동작하는 것처럼 느껴짐.

이러한 자바스크립트의 동시성을 지원하는 것이 바로 이벤트 루프

이벤트 루프는 브라우저에 내장되어 있는 기능 중 하나

대부분의 자바스크립트 엔진은 크게 콜 스택과 힙으로 구분할 수 있음

  • 콜 스택 call stack
    소스코드 평가 과정에서 생성된 실행 컨택스트가 추가되고 제거되는 스택 자료구조인 실행 컨택스트 스택
  • 힙 heep
    객체가 저장되는 메모리 공간으로, 실행 컨텍스트는 힙에 저장된 객체를 참조함

자바스크립트 엔진은 태스크가 요청되면 콜 스택을 통해 요청된 작업을 순차적으로 실행만을 담당함
비동기 처리에서 소스코드의 평가와 실행을 제외한(자바스크립트 엔진의 역할)
모든 처리는 자바스크립트 엔진을 구동하는 환경인 브라우저 또는 Node.js가 담당

이를 위해서 브라우저 환경은 태스크 큐와 이벤트 루프를 제공

  • 태스크 큐 task queue
    비동기 함수의 콜백 함수 또는 이벤트 핸들러가 일시적으로 보관되는 영역
  • 이벤트 루프 event loop
    콜 스택에 현재 실행 중인 실행 컨텍스트가 있는지, 태스크 큐에 대기 중인 함수(콜백 함수, 이벤트 핸들러 등)가 있는지 반복해서 확인
    만약 콜 스택이 비어있고 태스크 큐에 대기 중인 함수가 있다면 이벤트 루프는 순차적(선입선출 FIFO)으로 태스크 큐에 대기 주인 함수를 콜 스택으로 이동시킴

쉽게 말해, 비동기 함수의 콜백 함수는 태스크 큐에 푸시되어 대기하다가 콜 스택이 비게 되면(=전역 코드 및 명시적으로 호출된 함수의 종료) 이벤트 루프를 통해 콜 스택에 푸시 되어 실행됨

주의할 것이, 브라우저에 내장된 자바스크립트 엔진은 싱글 스레드 방식으로 동작하고 브라우저는 멀티 스레드로 동작!

profile
노트북이 좋아

0개의 댓글