비동기 처리

이재윤·2021년 9월 6일
0

JavaScript

목록 보기
8/10
post-thumbnail

💻 동기 처리 vs 비동기 처리

🔍 동기 처리

함수가 호출된 순서대로 함수 실행 컨텍스트가 함수 실행 컨텍스트 스택에 푸쉬되어 순차적으로 실행되는 방식입니다.

  • 장점
    태스크들을 순서대로 하나씩 처리하기 때문에 실행순서가 보장이 됩니다.
  • 단점
    앞선 테스크가 종료할 때 까지 이후 태스크들이 블로킹 되는 단점이 있습니다.

일정 시간 후에 콜백함수를 실행하는 함수를 예로 들어보겠습니다.

function sleep(func, delay) {
  const delayUtil = Date.now() + delay;
  while (Date.now() < delayUtil);
  
  func();
}

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

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

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

3초 후에 foo함수가 호출 되며, 그 후 bar함수가 호출되는 방식입니다. bar함수는 foo함수가 실행 종료(컨텍스트 스택에서 제거)될 때 까지 실행되지 않습니다.

🔍 비동기 처리

현재 실행중인 태스크가 종료되지 않았더라도, 다음 태스크를 바로 실행하는 방식입니다.

  • 장점
    현재 실행중인 태스크가 종료되지 않더라도 다음 태스크를 실행하므로 블로킹이 발생하지 않습니다.
  • 단점
    실행 순서를 보장받지 못합니다.

위의 동기방식으로 동작하는 코드를 setTimeout을 이용하여 비동기로 바꿔보겠습니다.

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

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

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

3초후에 foo함수가 실행되는것은 동일하지만, foo함수가 종료되기전에 bar함수가 먼저 호출이 됩니다.

💻 이벤트 루프와 태스크 큐

자바스크립트 엔진은 하나의 컨텍스트 스택(콜 스택)을 가지고 있으므로, 한번에 하나의 태스크만 실행할 수 있습니다. 이를 싱글 스레드라 합니다.
하지만 브라우저의 경우 여러 작업을 동시에 처리하는 것처럼 느껴집니다. 이를 가능하게 하는 것이 이벤트 루프 입니다.

브라우저 환경을 도식화 해보면 아래와 같습니다.

  • 콜스택
    실행 컨텍스트 스택과 같습니다. 소스 코드 평가과정에서 생성된 컨텍스트가 푸쉬되며, 실행종료된 컨텍스트는 제거됩니다. 자바스크립트는 싱글스레드 이므로 최상위 실행 컨텍스트가 제거되기 전까지 다른 태스크는 실행되지 않습니다.


  • 객체가 저장되는 메모리 공간입니다. 실행 컨텍스트는 힙에 저장된 객체를 참조합니다.

  • 태스크 큐
    setTimeout, setInterval과 같은 비동기 함수의 콜백 함수나 이벤트 핸들러가 일시적으로 보관되는 영역입니다.

  • 이벤트 루프
    콜스택과 태스크 큐를 계속확인하며, 현재 실행중인 컨텍스트가 있는지, 대기중인 함수가 있는지를 검사합니다.
    만약 콜스택이 비었고, 태스크 큐에 대기중인 함수가 존재한다면 이벤트 루프는 순차적으로 함수를 콜스택으로 이동시켜 실행합니다.

위 그림에서 알 수 있듯이 비동기 처리에서 코드의 평가와 실행을 제외한 부분은 브라우저가 담당함을 알 수 있습니다.

💻 비동기 함수 실행 순서

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

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

setTimeout(foo, 0);
bar();
  1. 전역 코드가 평가되어 전역 컨텍스트가 생성되며 콜스택에 푸쉬됩니다.
  2. 전역 코드가 실행되어 setTimeout이 호출됩니다. 이때 setTimeout의 실행 컨텍스트가 생성되며 콜스택에 푸쉬됩니다.
  3. setTimeout이 실행되면 Web API의 타이머가 설정되며 스케줄링이 완료되면 콜스택에서 제거됩니다. 타이머가 만료될때 콜백함수를 태스크큐에 넣는 것은 브라우저가 하게됩니다.
  4. 아래의 두 단계는 병렬처리됩니다.
    • 타이머가 만료되면 브라우저는 콜백함수 foo를 태스크 큐에 푸쉬합니다.
    • bar함수가 호출되며, 실행 컨텍스트가 생성 푸쉬됩니다.
  5. bar함수가 종료되어 콜스택에서 제거되며 전역 컨텍스트도 제거됩니다. 이때 이벤트 루프는 콜스택이 비었음을 감지하게되고 태스크 큐에 있는 콜백함수를 콜스택에 푸쉬합니다.
  6. foo함수가 종료되어 콜스택에서 제거가 됩니다.

❗ 위의 코드의 경우 delay시간이 0이지만 4ms이하인 경우 최소 지연시간은 4ms로 설정이 됩니다. 또한 delay시간은 최소 보장시간이기 때문에 정확히 지연시간 후에 실행된다는 보장이 없습니다.

0개의 댓글