Miyeon

비동기 프로그래밍

2021-12-19JS

앞으로 나올 단어

실행 컨텍스트 스택 = 콜 스택
싱글 스레드

함수가 호출되면 자바스크립트 엔진은 무슨 일을 할까?

함수가 호출 된다
함수 코드 평가에서 함수 실행 컨텍스트가 생성된다.
이때 생성된 함수 실행 컨텍스트가 콜 스택에 푸시되고 함수가 실행된다.
함수 실행이 종료되면 함수 실행 컨텍스트는 콜 스택에서 POP되어 제거 된다.

예시로 살펴보자

foo();
bar();

전역 코드가 평가됨
전역 실행 컨텍스트가 콜 스택에 푸쉬됨
foo함수 실행 컨텍스트가 콜 스택에 푸쉬됨
foo함수 실행이 종료되어 콜 스택에서 제거됨
bar함수 실행 컨텍스트가 콜 스택에 푸쉬됨
bar함수 실행 컨텍스트가 종료되어 콜 스택에서 제거됨
전역 실행 컨텍스트가 콜 스택에서 제거됨

콜 스택에 푸쉬는 무엇을 의미할까

함수 실행의 시작되었다는 걸 의미한다.

왜 함수가 호출된 순서대로 순차적으로 실행되는가?

함수가 호출된 순서대로 콜 스택에 푸쉬되기 때문이다.
함수 실행 순서와 콜 스택 순서가 같다

그래서 자바스크립트를 싱글 스레드라고 하는가?

자바스크립트 엔진은 단 하나의 콜스택을 가지기 때문에 한 번에 하나의 테스크만 실행할 수 있다. 다시 말해서 콜 스택의 최상위 요소만 실행되고, 나머지는 모두 실행 대기 중인 테스크일 뿐이다. 순차적으로 실행되기 때문에 처리에 시간이 걸리는 태스크를 실행하면 블로킹(작업 중단)이 발생한다.

동기 처리

현재 실행중인 테스크가 종료할 때 까지 다음에 실행 될 테스크가 대기하는 방식을 말한다.
테스크를 순서대로 처리하므로 실행 순서가 보장되지만 앞선 테스크가 종료할 때까지 이후 테스크들이 블로킹되는 단점이 있다.

비동기 처리

현재 실행 중인 태스크가 종료되지 않은 상태라 해도 다음 태스크를 곧바로 실행하는 방식이다.
setTimeout, setInterval, HTTP 요청, 이벤트핸들러를 처리하는 방식이다.
블로킹이 발생하지 않는다는 장점이 있지만 테스크 실행 순서가 보장되지 않는다는 단점도 존재한다.

실행 순서 보장하는 방법

  • 콜백 -> 콜백헬 발생

    • 가독성 나쁨
    • 예러의 예외 처리가 곤란함
    • 여러 개의 비동기 처리를 한 번에 처리하는데 한계가 있음
  • 그래서 프로미스가 등장함

브라우저에서는 여러 작업이 동시에 발생하던데요?

어떻게 브라우저에서는 HTML요소가 애니메이션 효과를 통해 움직이면서 이벤트를 처리할 수 있을까? 자바스크립트는 싱글스레드이지만 브라우저는 멀티스레드여서 가능하다.
브라우저에는 테스크 큐와, 자바스크립트의 동시성을 지원하는 이벤트 루프가 존재한다.

자바스크립트 엔진 (소스 코드 평가와 실행 담당)

    • 객체가 저장되는 메모리 공간
    • 실행 컨텍스트는 힙에 저장된 객체를 참조한다
  • 콜 스택

브라우저 (호출 스케줄링을 위한 타이밍 설정, 콜백함수 등록 담당)

  • 태스크 큐

    • 비동기 함수의 콜백 함수, 이벤트 핸들러가 일시적으로 보관되는 영역
  • 이벤트 루프

    • 콜 스택에 현재 실행중인 실행 컨텍스트가 있는지, 테스크 큐에 대기 중인 함수(콜백 함수, 이벤트 핸들러)가 있는지 반복해서 확인함
    • 콜 스택이 비어져 있고 테스크 큐에 대기중인 함수가 있으면 이벤트 루프는 FIFO(순차적)으로 태스크 큐에 대기 중인 함수를 콜 스택으로 이동시킴.

요약하자면

비동기 콜백 함수는 테스크 큐에 푸쉬되어 대기하다가 콜 스택이 비게 되면(전역 코드 및 호출된 함수도 모두 종료되면) 그때 콜 스택에 푸쉬되어 실행된다.