Javascript) 비동기 프로그래밍이란?

shelly·2022년 4월 11일
0

참고 서적

  • 모던 자바스크립트 딥다이브
    자바스크립트의 원리를 알기에 아주 좋은 서적이다.
    아래의 작성된 내용은 해당 도서에서 읽은 내용을 나의 언어(?)로 바꾸어 작성한 것이다.
    책에는 더욱 디테일하고 친절하게 설명되어 있으니, 자바스크립트의 기초를 공부하고 있다면 강력 추천한다!

비동기 프로그래밍이란?

진행중인 연산이 끝날 때 까지 기다리지 않고, 다른 작업을 수행하도록 하는 프로그래밍을 뜻한다.
동시에 여러 연산을 수행하기 위해선, 멀티 스레드가 필요하다.

우리는 웹 브라우저를 동적으로 보여주기 위해 자바스크립트를 사용한다.
웹은 DOM의 위치를 변경시키면서 여러 연산을 동시에 수행한다.
그렇다면 자바스크립트를 실행하는 자바스크립트 엔진은 멀티 스레드인 것일까?

그렇지 않다. 자바스크립트 엔진은 싱글 스레드이다.

자바스크립트 엔진은 싱글스레드로 동기 실행한다.

자바스크립트 엔진이 함수를 실행하는 과정

브라우저는 자바스크립트를 실행하기 위해 자바스크립트 엔진을 사용한다.
자바스크립트 엔진이 일하는 방식을 알아보자!

foo();
bar();

  1. 자바스크립트가 실행되면 빈 콜스택에 전역 컨텍스트가 생성한 후 콜스택에 push 한다.

  2. foo 함수를 실행하기 위해 foo 컨텍스트를 생성한 후 콜스택에 push 한다.

  3. foo 실행

  4. foo 함수가 종료되면 foo 컨텍스트를 콜스택에서 pop 한다.

  5. bar 함수를 실행하기 위해 bar 컨텍스트를 생성한 후 콜스택에 push 한다.

  6. bar 실행

  7. bar 함수가 종료되면 bar 컨텍스트를 콜스택에서 pop 한다.

  8. 자바스크립트 전체 코드가 종료되기 때문에 전역 컨텍스트를 콜스택에서 pop 한다.

위와 같은 방식을 동기 실행이라고 한다.

동기 실행

동기 실행의 경우, 하나의 함수가 종료된 이후에 다른 함수를 실행할 수 있다.
만약 foo의 연산이 30초가 걸리는 함수라고 가정할 경우, bar함수는 최소 30초 이후에 실행된다.
이런 현상을 blocking이 발생했다고 말한다.

때문에 전체적인 실행 시간이 길어진다는 단점이 있다.
반면 실행 순서가 보장된다는 장점도 있다!

setTimeout은 비동기로 동작하던데?!

비동기 실행

javascript에서 지원해주는 함수 setTimeout이 실행되는 과정을 살펴보자.

setTimeout(foo, 30000)
bar()

위의 코드를 실행해보면, setTimeout 함수는 30초가 지나기 전에 bar 함수를 실행한다.
그리고, 30초가 지난 이후에 foo 함수를 실행한다.
즉, 비동기로 동작한다.
setTimeout과 동일하게, setInterval, HTTP요청 등은 비동기로 동작하는 것을 확인할 수 있다.

그런데, 자바스크립트 엔진은 싱글 스레드이다. 어떻게 비동기로 동작할 수 있는 것일까?

자바스크립트 엔진은 싱글스레드지만, 브라우저는 멀티스레드이다.

포인트는, 브라우저는 멀티 스레드로 동작할 수 있다는 것이다.

setTimeout(foo, 30000)
bar()

이 함수가 실행되는 과정을 아래의 사진과 함께 살펴보자!

  1. 전역 컨텍스트가 콜스택에 push 된다.

  2. setTimeout 컨텍스트가 콜스택에 push 된다.

  3. setTimeout은 브라우저의 WebAPI를 사용하여 30초 후에 foo함수를 실행시킬 수 있도록 스케쥴링하고 종료된다.
    이후 과정 4-7에 상관없이, 다음 동작이 이루어진.

    • timer는 30초 이후에 foo 컨텍스트를 태스크 큐에 추가한다.
  4. setTimeout 컨텍스트는 종료되었기 때문에 콜스택에서 제거된다.

  5. bar 컨텍스트가 콜스택에 push 된다.

  6. bar 컨텍스트가 종료된 후, bar 컨텍스트는 콜스택에서 pop 된다.

  7. 전역 컨텍스트가 콜스택에서 pop된다. 즉, 콜스택이 빈 상태가 된다.

  8. 이벤트 루프는 콜스택이 비었으며, 태스크 큐에 foo 컨텍스트가 대기중임을 확인한다. 이벤트 루프는 foo 컨텍스트를 콜스택에 push 한다.

  9. foo 컨텍스트가 종료되면 콜 스택에서 pop 된다.

이벤트 루프가 하는 일
콜스택태스크 큐의 상태를 확인한다. 만약, 콜 스택이 비어있고 태스크 큐에 대기중인 컨텍스트가 있다면 태스크 큐에 가장 먼저 적재된 컨텍스트를 콜스택에 push 한다. (FIFO)

요약하자면, setTimeout함수의 역할을 정확히 말하자면 브라우저가 제공하는 Web API에 스케쥴링을 하는 것이다.
실제로 setTimeout함수가 30초를 기다렸다가 foo 함수를 실행시키는 것이 아니다.
따라서 스케쥴링을 완료하면 setTimeout함수는 종료되기 때문에 자바스크립트 엔진의 콜스택에서 제거되고, bar 함수가 실행되는 것이다.

앞서 말했던 듯이, 자바스크립트 엔진은 싱글 스레드로 동기로 동작하고 있다. 하지만 브라우저는 멀티 스레드이기 때문에, 자바스크립트엔진에 도움을 주며 비동기로 동작할 수 있도록 도와준다. 따라서 우리는 비동기로 동작하는 웹을 경험할 수 있다.

0개의 댓글