이런 불편함을 해소하기 위해,
비동기적(asynchronous)으로 작동하는 런타임이 개발되었다. 아래와 같은 작업에 유용하다.
세 가지 문법 중 하나로 비동기 흐름을 구현할 수 있다.
callback, promise, async/await
resolve
, reject
의 의미와, then
, catch
와의 관계를 이해할 수 있다.Promise.all
의 사용법을 이해할 수 있다.async
/await
keyword에 대해 이해하고, 작동 원리를 이해할 수 있다.fs
모듈의 사용법을 이해할 수 있다.전화: 동기적, blocking (작업이 멈추고 전화를 받아야 한다)
문자: 비동기적, non-blocking (하던 작업을 멈추지 않고 나중에 문자를 확인할 수 있다)
💡 함수의 실행을 작성자가 control 할 수 있도록 한다는 것이 비동기적으로 작동하도록 한다는 것과 같다고 볼 수 있다.jquery의 ajax 통신과 같이 원하는 데이터를 서버에서 받아오는 방식의 앱을 개발할 때 유용하다. 비동기없이 데이터를 가지고 온다고 했을 때, 데이터가 수집되기 전까지 아무것도 하지 못하는 오류가 발생할 수 있기 때문이다.
어떤 함수의 인자로 들어오는 콜백 함수는 결국 어떤 함수 내에서만 실행이 된다.
비동기 API가 있다고 하자. 해당 API에 콜백함수를 넣어 준다. 해당 비동기 API 앞뒤로 다른 함수가 실행되고 있다고 한다면, 해당 다른 함수가 먼저 실행이 되고 비동기 API 내의 콜백함수가 실행된다. 이로써 비동기적인 구현을 할 수 있다.
// sync
console.log(1);
var data = fs.readFileSync('data.txt', 'utf8');
console.log(data);
// 실행 순서 => 1, 'data.txt' 파일 내 내용
// async
console.log(2);
var data = fs.readFile('data.txt', 'utf8', function (err, data) {
console.log(3);
console.log(data);
})
console.log(4);
// 실행 순서 => 2, 4, 3, 'data.txt' 파일 내 내용
// (node 비동기 모듈 앞뒤에 있는 함수가 실행이 끝나기 전까지 모듈을 실행하지 않는다.)
JS 엔진의 구성은 Memory Heap, Call Stack, Web APIs, Callback Queue 등으로 이뤄져있다.
<출처: https://poiemaweb.com/js-event>
아래 코드를 실행한다고 하자.
console.log('first')
setTimeout(function () {
console.log('second')
}, 1000);
console.log('third')
1) console.log(‘first’)가 Call stack에 추가된다.
2) console.log(‘first’)가 화면에 출력된 뒤, Call stack에서 제거된다.
3) setTimeout API가 Call stack에 추가된다. 그리고 Web APIs에 옮겨지고, Call stack에서 제거된다.
4) console.log('third')가 Call stack에 추가된다. (Web APIs에 옮겨진 setTimeout은 1초 뒤 callback으로 전달한 익명함수 "(function () {console.log('second')}"가 Callback Queue에 추가된다)
5) console.log(‘third’)가 화면에 출력된 뒤, Call stack에서 제거된다.
6) Event Loop로 Call stack이 비어있는지 계속 확인하다 console.log(‘third’)가 제거되면 Callback Queue에 담겨있던 익명함수를 Call stack에 담고 함수를 실행한다 (console.log('second'))
7) console.log('second')가 화면에 출력된 뒤, Call stack에서 제거된다.