[JS] 비동기 프로그래밍
2024-01-06

동기 처리와 비동기 처리

함수가 호출되면 함수 코드가 평가되고 함수 실행 컨텍스트가 생성된다. 이 떄 생성된 함수 실행 컨텍스트는 콜 스택에 푸시되고 함수가 실행된다. 실행이 끝나면 함수 실행 컨텍스트가 콜 스택에서 팝되어 제거되고, 다음 함수가 있으면 다음 함수 실행 컨텍스트가 푸시되어 똑같은 과정을 반복하게 된다.

자바스크립트 엔진은 하나의 콜 스택(실행 컨텍스트 스택)을 가진다. 때문에 자바스크립트로 어떤 태스크를 수행할 때 앞 순서의 태스크의 실행 컨텍스트가 콜 스택에서 팝되어야만 다음 순서의 태스크를 수행할 수 있다. 한번에 하나의 일 밖에 할 수 없다는 의미이다.

한 번에 하나의 태스크만 처리할 수 있는 것을 **싱글 스레드(single thread)**라고 하는데, 이 특징으로 인해 처리되는데 시간이 걸리는 태스크를 실행할 떄 뒷에 있는 태스크가 실행되지 못하는 블로킹(blocking) 현상이 발생한다.

이처럼 앞에 있는 태스크가 종료될 때까지 다음 번 태스크가 대기하는 방식을 **동기(synchronous)**라고 한다.

동기 처리 방식은 태스크의 실행 순서가 보장된다는 장점이 있지만, 앞 태스크가 종료될 때까지 다음 태스크가 블로킹된다는 단점이 있다.

동기와는 다르게 현재 실행중인 태스크가 종료되었는지와는 상관없이 다음 태스크를 실행하는 방식을 **비동기(asynchronous)**라고 한다. 비동기는 동기와는 반대로 실행중인 태스크가 종료되기 전에 다음 태스크가 실행되어 블로킹(non blocking)이 발생하지 않는다는 장점이 있지만 태스크의 실행순서가 보장되지 않는다는 단점이 있다.

이벤트 루프와 태스크 큐

자바스크립트의 특징 중의 하나는 싱글 스레드로 동작한다는 것이다. 하지만 브라우저에서의 동작을 보면 태스크들이 동시에 실행되는 것처럼 보인다. 이는 브라우저가 자바스크립트의 싱글 스레드를 보완해주고 있기 때문이다.

이벤트 루프와 브라우저 환경

자바스크립트 엔진은 크게 힙과 콜 스택으로 나뉜다. 힙에는 콜 스택에서 참조할 실제 객체들이 저장되고, 콜 스택에는 함수 실행 컨텍스트가 쌓인다.

브라우저에는 태스크 큐와 이벤트 루프가 있다. 태스크 큐에는 비동기 함수의 콜백 함수 또는 이벤트 핸들러가 일시적으로 보관된다. 이벤트 루프는 현재 콜 스택에 실행 중인 실행 컨텍스트가 있는지, 태스크 큐에 대기중인 함수들이 있는지를 계속 확인한다. 그러다 콜 스택이 비어있고, 태스크 큐에 대기중인 함수가 있으면 대기중인 함수를 순차적으로 콜 스택으로 이동시킨다. 콜 스택으로 이동한 함수는 콜 스택에 의해 실행된다.

비동기 동작 함수가 브라우저 측에 넘어가서 실행되는 동안 자바스크립트 엔진은 콜 스택에 다음 태스크를 쌓고 순차적으로 처리한다. 때문에 브라우저의 동작을 보았을 때 태스크들이 동시에 실행되는 것으로 보이는 것이다.

다시 말해, 자바스크립트는 싱글 스레드이지만, 멀티스레드인 브라우저에서 동작하기 때문에 멀티스레드처럼 동작할 수 있는 것이다.

  • 책 모던 자바스크립트 딥 다이브