개요

2024-03-15일 저녁에 공통 프로젝트 팀원들과 회식을 하면서 비동기 처리 관련 글을 포스팅 했던 얘기가 나왔었는데, 여기서 내가 글을 썼음에도 여러가지 부족한 점들이 느껴져서 조금만 더 정리해본다. 그 중 자바스크립트 에서 비동기 처리를 어떻게 하는것인가에 대해서 얘기하다 어물쩡 거려가지고 좀 부끄러웠다. 어떻게 진행되는지 한번 보자.

동기와 비동기

동기

동기(Synchronous)는 순차적인 흐름을 가진다. 하나의 작업이 실행되는 동안, 뒤의 다른 작업들은 그대로 멈춘 채 자신의 차례가 오기까지를 기다린다.

이 일련의 과정 중에서 동기식 프로그램의 특징을 알 수 있다. 손님이 주문을 요청하면, 점원은 그 요청에 대한 처리를 거처 응답을 내놓는다. 손님은 응답이 돌아오기까지 카운터를 떠나지 않고 기다린 뒤, 응답을 받고 나서야 다음 행동을 할 수 있다.

한번에 하나의 태스크를 수행하는 것은 싱글 스레드에서 코드가 동작할 경우이다. 요청에 대한 처리를 할 수 있는 주체가 하나만 존재하기 때문에, 위와 같이 순차적인 흐름을 가질 수 밖에 없다.

비동기

비동기(Asynchronous)는 반대로, 어떠한 요청을 보내면 해당 요청의 응답에 관계없이 바로 다음 동작이 실행된다. 즉, 실행중인 작업이 끝나기를 기다리지 않고 바로 다음 작업으로 넘어갈 수 있다.

점원들의 작업은 비동기식으로 처리되고 있다. 점장은 점원1에게 요청을 보낸 후, 응답을 받지 않은 상태에서 점원2에게 다른 요청을 보낸다. 둘 다 완료 보고라는 응답이 돌아오지 않았지만 점장은 신경쓰지 않고 다음 작업으로 넘어갈 수 있다.

멀티 스레드 방식에서는 요청을 처리할 수 있는 작업 단위가 여러 개이기 때문에, 하나의 태스크가 끝나기를 기다리지 않아도 다음 실행을 할 수 있게된다.

자바스크립트 엔진이란?

자바스크립트의 코드를 해석하고 분석하고 실행하는 인터프리터, 즉 해석기이다. 주로 웹 브라우저에서 사용된다. (자바스크립트 엔진은 브라우저 안에 내장되어 있다.) 엔진에 의해 해석하기 때문에 컴파일 과정일 불필요하다. 웹 브라우저에서 곧바로 해석하고 실행한다.

브라우저별 엔진 종류

  • V8 : 자바스크립트 대표 엔진이다. 구글에서 개발했으며, 크롬과 노드js에서 사용한다.
  • 웹킷 : 애플에서 개발한 오픈소스 엔진이고, 사파리에서 사용한다.
  • 스파이더 몽키, 차크라 등등

자바스크립트 엔진 구조

자바스크립트 엔진은 크게 메모리 힙과 콜 스택으로 나눌 수 있다. 이벤트 루프, 콜백 큐와 같은 엔진 외부 요소들과 함께 코드를 실행한다.

메모리 힙과 콜스택

메모리 힙

객체, 함수, 참조 타입과 같은 데이터를 저장하는 공간.

콜 스택

코드를 실행할 때 코드 안의 실행 순서를 기록하고 순서대로 코드가 실행될 수 있도록 도와주는 스택이다. 자세히 말하자면 함수를 호출 시 함수 실행 컨텍스트가 스택에 쌓이면서 순서대로 실행된다.

<aside> 💡 실행 컨텍스트란? 브라우저가 HTML 문서를 해석할 때, <script> 태그로 감싸진 자바스크립트 코드 또는 onClick과 같은 속성을 가진 태그를 만나면 이것을 자바스크립트에 보낸다. 그리고 자바스크립트 엔진이 브라우저가 넘겨준 코드를 변환하고 실행시키기 위해 특별한 환경을 구성하는데, 이것을 실행 컨텍스트 라고한다.

</aside>

자바스크립트는 어떻게 비동기 실행이 가능할까

자바스크립트 코드가 비동기 실행으로 보여지게 만들어 주는 것은 바로 브라우저이다. 브라우저는 자바스크립트 엔진 외에도 태스크 큐, 이벤트 루프, Web API를 가지고 있다.

  • 태스크 큐 : 비동기 함수의 콜백 함수가 임시 보관되는 공간
  • 이벤트 루프 : 자바스크립트 엔진의 콜스택이 비어있는지, 태스크 큐에 대기 중인 함수가 있는지 확인
  • Web API : 브라우저 환경에서 제공하는 API
    • ex) setTimeout, DOM API, AJAX통신, Canvas, WEBGL, 오디오 또는 비디오 API

비동기 실행에서 브라우저의 역할

자바스크립트 엔진은 싱글 스레드로 동작하지만, 브라우저 엔진은 멀티 스레드로 동작한다. 멀티 스레드로 동작하는 브라우저가 제공하는 Web API를 함께 사용하여 비동기 동작을 구현할 수 있는 것 이다.

자바스크립트 엔진이 코드를 읽어 실행하는 과정

  1. 자바스크립트 엔진이 실행 컨텍스트를 차례대로 콜스택에 쌓는다.
  2. 쌓인 코드들이 순서에 따라 콜스택을 빠져나가며 실행된다.
  3. 코드 중 비동기 함수, 즉 setTimeout 또는 setInterval, 이벤트 핸들러와 같은 Web API 함수를 만나면 자바스크립트 엔진이 이들을 Web API로 보낸다.
  4. Web API는 전달받은 함수의 콜백 함수를 꺼내어 태스크 큐로 보낸다. 이때 딜레이 인자가 잇는 경우는 딜레이 시간만큼 Web API에서 대기하게 된다.
  5. 콜스택에 있던 함수들의 실행이 모두 완료되어 빈 공간이 되면, 이벤트 루프가 태스크 큐에서 대기중인 콜백함수 하나를 콜스택에 넣어 바로 실행시킨다.
  6. 다시 콜스택이 비면 이벤트 루프가 태스크큐가 빌때까지 위의 동작을 반복

결론

자바스크립트엔진은 싱글 스레드가 맞다. 그리고 멀티 스레드로 동작하는 브라우저의 도움이 있기에 비동기 통신을 효율적으로 처리할 수 있는것이다. 회식 하면서 갑자기 헷갈렸던 부분은 “자바스크립트 엔진은 어떻게 싱글 스레드이면서 이벤트 루프를 돌며 WEB API가 실행한 결과를 받아오나” 였는데, 브라우저가 이벤트 루프를 관리하기 때문에 그랬던 것으로 정리할 수 있겠다.

+ Recent posts