본문 바로가기
👩‍💻 Programming/JavaScript

[모던 자바스크립트 Deep Dive] 비동기 프로그래밍

by codingBear 2022. 11. 20.
728x90
반응형

 이번 글은 모던 자바크스립트 Deep Dive의 42장 '비동기 프로그래밍' 및 초보자를 위한 Node.js 200제의 122장 '비동기(Async)와 동기(Sync)를 요약정리한 글입니다.


🤔 비동기란?

👉 쉽게 말하자면 return값이 없는 실행

 

🤔 왜 비동기로 코드를 짜는가?

👉 프로그램은 return값을 받으려고 응답이 올 때까지 기다리는데 이러면 실행 시간이 늘어나 성능 저하됨.

 

💡 비동기 작동 방식

👉 예를 들어 100명의 비서에게 동시에 각 번호별 페이지를 호출해서 저장하라고 하자. 비서는 각자 맡은 일을 처리할 테고 평균 처리 시간이 1초, 최장 처리 시간이 2초라고 한다면 총 실행 시간은 2초이다. 즉 여러 개의 작업을 순차적이 아니라 同時적으로 처리하는 것!


🤔 동기 처리와 비동기 처리

  1. 함수 호출 시 함수 평가되고 함수 실행 컨텍스트 생성
  2. 생성된 함수 실행 컨테그스트는 실행 컨텍스트 스택(콜 스택)에 푸시되고 함수 실행
  3. 함수 실행 종료되면 함수 실행 컨텍스트는 실행 컨텍스트 스택에서 팝(pop)되어 제거

 

👉 자바스크립트 엔진의 실행 컨텍스트 스택은 단 하나임.

👉 즉 동시에 2개 이상의 함수를 실행할 수 없는 싱글 스레드(single thread) 방식으로 동작함. 이 때문에 블로킹(blocking, 작업중단)이 발생함.

👉 실행 컨텍스트 스택으로 함수의 실행 순서를 관리함.

 

👉 위 예제처럼 현재 실행 중인 함수가 종료할 때까지 다음 실행될 태스크가 대기하는 방식을 동기(synchronous) 처리라고 함.

 

🔨 위 예제를 타이머 함수인 setTimeout을 사용하여 수정하면 다음과 같다.

👉 위 예제에서 setTimeout 이후의 함수 bar는 블로킹되지 않고 실행됨. 이처럼 현재 실행 중인 함수가 종료되지 않아도 다음 태스크가 곧바로 실행되는 방식을 비동기(asynchronous) 처리라고 함.

 

✨ 동기 처리와 비동기 처리의 장단점을 정리하면 다음과 같다.

항목 동기 비동기
장점 실행순서 보장 O 블로킹 발생 X
단점 블로킹 발생 O 실행순서 보장 X

 

👉 비동기 처리 방식으로 동작하는 대표적인 예는 타이머 함수(setTimeout, setInterval 등), HTTP 요청, 이벤트 핸들러 등이 있음.


🤔 이벤트 루프와 태스크 큐

👉 싱글스레드인 자바스크립트에서 동시성(concurrency)를 지원하는 것이 브라우저에 내장된 기능 중 하나인 이벤트 루프(event loop)임.

 

👉 자바스크립트 엔진은 크게 2개의 영역으로 구분할 수 있다.

 

  • 콜 스택(call stack)
    • 실행컨텍스트가 추가되고 제거되는 영역. 자바스크립트 엔진은 단 하나의 콜 스택만을 사용.
  • 힙(heap)
    • 객체가 저장되는 메모리 공간. 실행 컨텍스트는 힙에 저장된 객체를 참조.
    • 객체의 메모리 크기는 원시 값과는 달리 정해져 있지 않으므로 동적 할당되어 구조화되어 있지 않다는 게 특징임.

 

👉 콜 스택과 힙으로 구성되어 있는 자바스크립트 엔진은 태스크가 요청되면 콜 스택을 통해 요청된 작업을 순차적으로 실행할 뿐이다.

👉 비동기 처리에서 소스코드의 평가와 실행을 제외한 모든 처리는 자바스키립트 엔진을 구동하는 환경인 브라우저 또는 Node.js가 담당.

👉 예를 들어 setTimeout의 콜백 함수를 평가하고 실행하는 것은 자바스크립트 엔진이 담당하지만 타이머 설정과 콜백 함수의 등록은 브라우저 또는 Node.js가 담당. 이를 위해 브라우저 환경은 태스크 큐이벤트 루프를 제공함.

 

  • 태스크 큐(task queue/event queue/callback queue)
    • 비동기 함수의 콜백 함수 또는 이벤트 핸들러가 일시적으로 보관되는 영역.
    • 프로미스의 후속처리 메서드의 콜백 함수가 보관되는 마이크로태스크 큐도 존재.
  • 이벤트 루프(event loop)
    • 콜 스택에 실행 중인 실행 컨텍스트가 있는지, 태스크 큐에 대기 중인 함수가 있는지 반복해서 확인하여 다음 실행될 태스크를 순차적(FIFO)으로 콜 스택으로 이동시킴.

 

🤔 다음 예제의 foo 함수와 bar 함수 중 먼저 실행될 함수는 어느 쪽일까?

 

👉 위 예제에서 비동기 함수인 setTimeout의 콜백 함수 foo는 태스크 큐에 푸시되어 대기하다가 콜 스택이 비게 되면, 즉 전역 코드 및 실행 중인 함수가 모두 종료하면 그제서야 콜 스택에 푸시되어 실행됨.


😲 결론

👉 자바스크립트가 싱글 스레드 방식으로 동작한다고 했을 때 이는 자바스크립트 엔진이 싱글 스레드 방식으로 동작한다고 하는 것임에 주의하자. 즉 자바스크립트 엔진싱글 스레드로 동작하지만 브라우저멀티 스레드로 동작하여 자바스크립트에서 비동기 코드를 구현할 수 있는 것이다.

👉 브라우저는 자바스크립트 엔진 외에도 렌더링 엔진Web API를 제공

👉 Web API는 브라우저에서 제공하는 API로 DOM API, 타이머 함수, HTTP 요청(Ajax)와 같은 비동기 처리를 포함함.

👉 앞선 예제에서 살펴봤듯 브라우저의 Web API인 setTimeout 함수가 호출되면 자바스크립트 엔진의 콜 스택에 푸시되어 실행됨. 하지만 setTimeout함수의 두 가지 기능인 타이머 설정과 타이머 만료 시 콜백 함수를 태스크 큐에 등록하는 처리는 브라우저가 담당함. 이처럼 자바스크림트 엔진과 브라우저가 협력하여 비동기 함수인 setTimeout을 실행하는 것이다.

728x90
반응형

댓글