언어의 비동기에 관해 — javascript, nodejs
지난번에 Python, Golang에 관해 비동기 글을 작성해 보았습니다.
→ https://medium.com/iovsomnium/언어의-비동기에-관해-go-python-44ea144adefc
그러다 보니 python에서 사용되는 비동기의 방식중
cpython으로 구현된 방식이 nodejs의 libuv를 사용한다라는 것을 알고
필수적으로
javascript의 비동기도 알아겠다라는 생각이 들어 글을 작성합니다.
자바 스크립트의 가장 기본적인 비동기 처리 방식은 callback 입니다.
특정 작업이 완료된 후에 실행될 함수를 인자로 전달하는 방식입니다.
예를 들어, setTimeout
함수나 AJAX 요청에서 콜백 함수를 사용합니다.
function printAfterDelay() {
console.log('Before setTimeout');
setTimeout(function() {
console.log('Inside the callback');
}, 2000);
console.log('After setTimeout');
}
printAfterDelay();
그러나 이런 callback을 통한 비동기 처리는 작업 사항이 많아질때 문제가 발생합니다.
이를 “callback 지옥”이라고 부릅니다.
이러한 문제를 해결하기 위해 promise가 도입되었습니다.
promise는 비동기 작업의 최종 완료 또는 실패 결과를 나타내는 객체로, then
과 catch
메소드를 이용해 비동기 작업의 성공, 실패 처리를 체이닝 방식으로 구현할 수 있습니다.
위의 printAfterDelay
함수를 promise를 사용하여 다시 작성하면 다음과 같습니다:
function printAfterDelay() {
console.log('Before promise');
const delay = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('Inside the callback');
}, 2000);
});
delay.then((message) => {
console.log(message);
});
console.log('After promise');
}
printAfterDelay();
어느정도 문제가 해결되었으니 이젠 코드의 가독성을 논할 차례입니다.
async/await 는 ES2017에 도입된 문법으로,
비동기 코드를 마치 동기 코드처럼 깔끔하게 작성할 수 있게 해줍니다.
함수 앞에 async
키워드를 붙이고, 비동기 작업 앞에 await
키워드를 붙여 사용합니다.
위의 printAfterDelay
함수를 async/await를 사용하여 다시 작성하면
다음과 같습니다:
async function printAfterDelay() {
console.log('Before async/await');
const delay = (message, time) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(message);
}, time);
});
};
const message = await delay('Inside the callback', 2000);
console.log(message);
console.log('After async/await');
}
printAfterDelay();
이러한 비동기 처리 메커니즘은 내부적으로 자바스크립트 엔진의 이벤트 루프와 함께 동작합니다.
이벤트 루프는 콜 스택이 비어있을 때 태스크 큐에서 작업을 가져와 실행하는 역할을 합니다.
이를 통해 자바스크립트는 싱글 스레드 언어임에도 불구하고 동시에 여러 작업을 처리하는 것처럼 보이게 할 수 있습니다.
마지막으로 처음에 언급했던 node js libuv에 관해서 말해보고자 합니다.
libuv는 Node.js와 같은 특정 런타임 또는 라이브러리에서 사용되는 시스템 레벨의 라이브러리입니다. 개발자가 직접 libuv를 사용하기보다는, libuv를 사용하여 구현된 Node.js의 API를 사용하여 비동기 작업을 처리합니다.
const http = require('http');
const server = http.createServer((req, res) => {
res.end('Hello, World!');
});
server.listen(3000);
마치 이렇게요
이렇게 기본적으로 javascript에서 비동기를 사용하는 방식과
python에서도 구현된 libuv를 사용해 구현된 http api등을 다뤄봤습니다.