Javascript Event Loop & Promise

2021. 8. 22. 19:58
반응형

 

 

자바스크립트의 비동기적 작업 수행을 돕는 Event Loop

 

이벤트 루프가 무엇인지 알아보기에 앞서 알아볼 것. 우선 자바스크립트의 엔진은 Memory Heap과 Call Stack으로 이루어져 있다.

Memory Heap(메모리힙)
변수, 함수 저장, 호출 등의 작업이 발생하는 공간.
Memory heap이라는 창고 안에 박스들(변수, 함수 등)이 쌓여있는 것으로 이해할 수 있다.


Call Stack(콜 스택)
메모리 상에 존재하며, 코드가 실행될 때 읽어내려가며 수행할 작업들을 쌓아나가는 공간이다.
위에서 살펴본 메모리힙에서 작업에 필요한 것들을 찾아 수행한다. 선입후출의 룰을 따른다.

자바스크립트는 하나의 call stack만을 가지는 단일 스레드(single thread) 프로그래밍 언어다(즉, 하나하나, 차례차례 실행한다).

하지만 비동기적으로 동작한다(어떤 작업을 요청했을 때 그 작업이 종료될때 까지 기다리지 않고 다른 작업을 하고 있다가, 요청했던 작업이 종료되면 그에 대한 추가 작업을 수행). 이게 어떻게 가능한 걸까?

 

앞서 이야기한 것처럼 자바스크립트 언어 자체가 비동기 동작을 지원하는 것은 아니지만,

웹 브라우저와 같은 멀티 쓰레드 환경에서 자바스크립트가 실행될 때 브라우저 등이 비동기로 동작하는 핵심요소를 제공하는 것이다.

 

 

1. Call Stack : 수행해야 할 함수들을 차곡차곡 담고, 웹 브라우저가 제공하는 Web API를 호출한다. 

2. Web APIs : Call Stack Queue로 callback 함수들을 넘긴다.

3. Callback queue : 앞에서 넘겨받은 callback 함수를 저장한다.

4. Event Loop : Call Stack과 Callback Queue를 감시하고 있다가, call stack이 비어있을 때 callback queue의 작업을 call stack으로 옮긴다.

정리하면 단일 thread 언어인 자바스크립트는 한 번에 하나씩밖에 실행할 수 없지만,

Web APIs, Callback queue, Event Loop가 멀티쓰레드처럼 동작하도록 돕는 역할을 한다.

 


Event Loop는 어떻게 동작하는가?

 

태스크는 항상 이벤트 루프를 통해 순차적으로 실행된다. Event loop는 기본적으로 다음과 같이 동작한다.

 

  • call stack에 쌓여있는 함수가 없다면
    1. call stack queue에서 대기하고 있던 콜백 함수를 call stack으로 넘긴다
    2. 넘겨받은 콜백 함수가 실행된 후, call stack에서 제거된다.

 

  • call stack에 쌓여있는 함수가 있다면
    : 가장 오래된 작업부터 실행

 


Promise란?

 

위에서 살펴본 콜백(callback)을 사용하여 비동기 처리를 하는 것은, 에러나 예외 처리 등이 어렵고, 또 중첩될 경우 복잡도가 증가한다는 단점을 가진다.

 

이러한 단점을 해결하기 위해 프로미스를 사용한다. promise란 "지금은 없으니 이따가 줄게"라는 약속으로, 비동기 작업에서 성공과 실패를 분리하여 메서드를 수행한다.

 

Promise 객체는 다음 중 하나의 상태를 가진다.

pending (아직 약속을 수행 중인 상태 - fulfilled 또는 rejected 되기 전)

fulfilled (약속이 이행된 상태)

rejected (약속이 어떠한 이유로 지켜지지 못한 상태)

settled (약속이 지켜졌든/지켜지지 않았든 일단 결론이 난 상태)

 

기본 틀
프로미스 체이닝 (여러 개의 프로미스를 연결해서 사용)

 

위와 같이 사용할 수 있다

 


async / await 방식

 

async와 await는 promise 객체를 보다 쉽게 다룰 수 있도록 비교적 최근 고안된 문법이다.

 

함수명 앞에 async 키워드를 붙여 async function ... 형식으로 사용하며,

await는 async 안에서만 사용할 수 있는 키워드이다.

 

await는 promise가 처리될 때까지 함수 실행을 기다리게 만든다는 의미이다.

await를 사용하여 기다리는 동안(=작업이 처리되는 동안) 엔진이 다른 일을 할 수 있기 때문에 리소스가 낭비되지 않는다.

 

async 함수는 리턴 값으로 항상 resolved promise를 반환한다.

async를 붙인 함수와 아닌 함수의 return값 차이

 

 

 

async / await 방식은 promise / then을 사용하는 것보다 간결하고 가독성이 뛰어나며,

비동기 코드가 보여지는 방식을 동기 코드와 유사하게 만들어준다는 장점을 가진다. 

 

promise 방식을 사용했을 때
async 방식을 사용했을 때

 

 

 

반응형

BELATED ARTICLES

more