- Published on
비동기 프로그래밍
비동기 프로그래밍
동기 처리와 비동기 처리
- 함수를 호출하면 함수 코드가 평가되어 함수 실행 컨텍스트가
생성됨 - 생성된
함수 실행 컨텍스트는 실행 컨텍스트 스택(= 콜 스택)에푸시되고 함수 코드가 실행됨 - 함수 코드의 실행이
종료되면함수 실행 컨텍스트는 실행 컨텍스트 스택에팝되어 제거됨
싱글 스레드
- 자바스크립트 엔진은
단 하나의 실행 컨텍스트 스택을 가짐(⭐⭐) - 동시에 2개 이상의 함수를 동시에 실행할 수 없으므로 실행 중인
실행 컨텍스트를 제외한 모든 실행 컨텍스트는 실행대기 중인 태스크들임 - 싱글 스레드 방식으로 동작하므로 처리에 시간이 걸리는 태스크를 실행하는 경우에는
블로킹이 발생함

- 현재 실행 중인 태스크가 종료할 때까지 다음에 실행될 태스크가 대기하는 방식을
동기 처리라고 함- 순서대로 하나씩 처리하므로
실행 순서가 보장된다는 장점이 있지만, 앞선 태스크가 종료할 때까지 이후 태스크들이블로킹됨
- 순서대로 하나씩 처리하므로
setTimeout을 이용한 비동기 처리
function foo() {
console.log('foo');
}
function bar() {
console.log('bar');
}
// 타이머 함수 setTimeout은 일정 시간이 경과한 이후에 콜백 함수 foo를 호출
// 타이머 함수 setTimeout은 bar 함수를 블로킹 하지 않음
setTimeout(foo, 3 * 1000);
bar();
// bar 호출 -> (3초 경과 후) foo 호출
setTimeout함수는 태스크를 블로킹하지 않고 곧바로 실행함- 현재 실행 중인 태스크가 종료되지 않은 상태라 해도 다음 태스크를 곧바로 실행하는 방식을
비동기 처리라고 함
- 현재 실행 중인 태스크가 종료되지 않은 상태라 해도 다음 태스크를 곧바로 실행하는 방식을

타이머 함수인
setTimeout과setInterval, HTTP 요청, 이벤트 핸들러는 비동기 처리 방식으로 동작함
이벤트 루프와 태스크 큐
- 자바스크립트 엔진이 싱글 스레드로 동작하지만 브라우저 동작하는 것을 보면 많은 태스크가 동시에 처리되는 것처럼 느껴지는데, 이런
동시성을 지원하는 것이이벤트 루프

- 이벤트 루프와 브라우저 환경은 위의 그림처럼 표현할 수 있음
- 구글의 V8 자바스크립트 엔진을 비롯한 대부분의
자바스크립트 엔진은 크게 2개 영역으로 구분할 수 있음
자바스크립트 엔진 영역
태스크가 요청되면
콜 스택을 통해 요청된 작업을 순차적으로 실행함
콜 스택(Call Stack)- 소스코드 평가 과정에서 생성된
실행 컨텍스트가추가되고제거되는 스택 자료구조를콜 스택이라 함
- 소스코드 평가 과정에서 생성된
힙(Heap)- 객체가 저장되는
메모리 공간으로서 콜 스택의 요소인 실행 컨텍스트는 힙에저장된 객체를 참조함- 객체는 원시 값과 달리
크기가 정해져 있지 않음
- 객체는 원시 값과 달리
- 메모리 공간의 크기를
런타임에 결정(동적 할당)해야 함- 객체가 저장되는 메모리 공간인 힙은 구조화되어 있지 않음
- 객체가 저장되는
브라우저 환경
소스코드의 평가와 실행을 제외한
모든 처리는 자바스크립트 엔진을 구동하는 환경인브라우저또는Node.js가 담당
태스크 큐(task queue/event queue/callback queue)setTimeout이나setInterval과 같은 비동기 함수의 콜백 함수 또는 이벤트 핸들러가 일시적으로 보관되는 영역
이벤트 루프(event loop)- 콜 스택에 현재 실행 중인 실행 컨텍스트가 있는지, 태스크 큐에 대기 중인 함수(콜백 함수, 이벤트 핸들러 등)가 있는지 반복해서 확인
- 콜 스택이 비어 있어 있거나 태스크 큐에 대기중인 함수가 있다면
이벤트 루프는 순차적으로 태스크 큐에 대기 중인 함수를콜 스택으로 이동시킴
- 콜 스택이 비어 있어 있거나 태스크 큐에 대기중인 함수가 있다면
- 콜 스택에 현재 실행 중인 실행 컨텍스트가 있는지, 태스크 큐에 대기 중인 함수(콜백 함수, 이벤트 핸들러 등)가 있는지 반복해서 확인
실행 순서
function foo() {
console.log('foo');
}
function bar() {
console.log('bar');
}
setTimeout(foo, 0); // 0초(실제는 4ms) 후에 foo 함수가 호출됨
bar();
- 전역 코드가
평가되어 전역 실행 컨텍스트가 생성되고콜 스택에 푸시됨 - 전역 코드가
실행되어setTimeout함수 호출setTimeout함수의 함수 실행 컨텍스트가 생성되고 콜 스택에 푸시되어현재 실행 중인 실행 컨텍스트가 됨
setTimeout함수가 실행되면 콜백 함수를 호출 스케줄링하고 종료되어 콜 스택에서 팝됨- 타이머 설정과 타이머가 만료되면 콜백 함수를
태스크 큐에 푸시하는 것은브라우저의 역할
- 타이머 설정과 타이머가 만료되면 콜백 함수를
브라우저가 수행하는 4-1과자바스크립트 엔진이 수행하는 4-2는병행처리됨브라우저- 타이머를 설정하고 타이머의 만료를 기다리고 만료된 후 콜백 함수 foo가 태스크 큐에 푸시됨
- 4ms 후에 콜백 함수 foo가 태스크 큐에 푸시되어 대기하게 됨
자바스크립트 엔진bar 함수가 호출되어 bar 함수의 함수 실행 컨텍스트가 생성되고 콜 스택에 푸시되어 현재실행 중인 실행 컨텍스트가 됨bar 함수가 종료되어 콜 스택에서 팝되는데, 이때 브라우저가 설정한 타이머가 4ms 경과했다면foo 함수는 태스크 큐에서 대기중인 상태
- 전역 코드 실행 종료 후
전역 실행 컨텍스트가 콜 스택에서 팝됨 이벤트 루프에 의해 콜 스택이비어 있음이 감지되고 태스크 큐에서 대기 중인 콜백 함수 foo의 함수 실행 컨텍스트가 생성되고 콜 스택에 푸시되어 현재 실행 중인 실행 컨텍스트가 됨자바스크립트 엔진은싱글 스레드로 동작브라우저는멀티 스레드로 동작
Referenced
- 이응모, 『모던 자바스크립트 Deep Dive』, 위키북스(2022.4.25), 809 ~ 815p