rustandbone Developer

모던 JS deep dive 2회차 챕터 42 비동기 프로그래밍

모던 JS deep dive 2회차

42. 비동기 프로그래밍

42.1 동기 처리와 비동기 처리

자바스크립트 엔진은 단 하나의 실행 컨텍스트 스택을 가짐. 함수를 실행할 수 있는 창구가 단 하나인 것. 실행 중인 것을 제외한 모든 실행 컨텍스트는 모두 실행 대기 중인 태스크들.

한 번에 하나의 태스크만 실행할 수 있는 싱글 스레드 방식으로 동작.
처리에 시간이 걸리는 태스크를 실행하면 블로킹(blocking, 작업 중단)이 발생.

동기(synchronous) : 현재 실행 중인 태스크가 종료할 때까지 다음에 실행될 태스크가 대기하는 방식. 실행 순서는 보장되지만, 앞선 태스크가 종료할 때까지 이후 태스크들이 블로킹됨.

비동기 : 현재 실행 중인 태스크가 종료되지 않는 상태라도 다음 태스크를 곧바로 실행하는 방식. 실행 순서는 보장되지 않지만, 블로킹이 발생되지 않음. 타이머 함수인 setTimeout, setInterval과 HTTP 요청, 이벤트 핸들러는 비동기 처리 방식으로 동작

42.2 이벤트 루프와 태스크 큐

자바스크립트는 싱글 스레드로 동작. 그러나 브라우저 동작을 보면 많은 태스크가 동시에 처리되는 것처럼 느껴짐

이벤트 루프(event loop) : 브라우저에 내장된 기능으로 자바스크립트의 동시성을 지원하는 것

  • 자바스크립트 엔진 영역
  • 콜 스택
    • 실행 컨텍스트 스택
    • 생성된 실행 컨텍스트가 추가되고 제거되는 스택 자료구조를 의미.
    • 함수를 호출하면 함수 실행 컨텍스트가 순차적으로 콜 스택에 푸시되어 순차적으로 실행됨.
    • 객체가 저장되는 메모리 공간. 콜 스택의 요소인 실행 컨텍스트는 힙에 저장된 객체를 참조함.
    • 메모리에 값을 저장하려면 공간 크기를 결정해야 하는데, 객체는 크기가 정해져 있지 않으므로 런타임에 결정(동적 할당). 객체가 저장되는 메모리 공간인 힙은 구조화 되어 있지 않다는 특징이 있음 => 비구조화

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

  • 브라우저 환경 제공
  • 테스트 큐(task queue / event queue / callback queue)
    • 비동기 함수의 콜백 함수(setTimeout, setInterval) 또는 이벤트 핸들러가 일시적으로 보관되는 영역
  • 이벤트 루프(event loop)
    • 콜 스택에 현재 실행 중인 실행 컨텍스트가 있는지, 태스크 큐에 대기 중인 함수(콜백 함수, 이벤트 핸들러 등) 유무를 반복해서 확인.
    • 콜 스택이 비어 있고 태스크 큐에 대기 중인 함수가 있다면 이벤트 루프는 순차적으로 태스크 큐에 대기 중인 함수를 순차적(FIFO)으로 콜 스택으로 이동시킴. 이때 콜 스택으로 이동한 함수는 실행됨
    • 태스크 큐에 일시 보관된 함수들은 비공기 처리 방식으로 동작함

비동기 함수는 태스크 큐에 푸시되어 대기하다가 콜 스택이 비게 되면, 전역 코드 및 명시적으로 호출된 함수가 모두 종료하면 콜 스택에 푸시되어 실행됨.

자바스크립트 엔진은 싱글 스레드로 동작하지만 브라우저는 멀티 스레드로 동작.

브라우저는 자바스크립트 엔진 외에도 렌더링 엔진과 Web API를 제공함. Web API는 ECMAScript 사양에 정의된 함수가 아니라 브라우저에서 제공하는 API(DOM API, 타이머 함수, HTTP 요청 포함).

setTimeout 함수가 호출되면 자바스크립트 엔진의 콜 스택에 푸시되어 실행됨. setTimeout 함수의 두 가지 기능인 타이머 설정과 타이머가 만료하면 콜백 함수를 태스크 큐에 등록하는 처리는 자바스크립트 엔진이 아닌 브라우저가 실행.