JavaScript에서 비동기 작업을 다룰 때 사용할 수 있는 세 가지 주요 기술이 있습니다: 콜백(callbacks), 프로미스(promises), 그리고 async/await입니다. 각각은 자신만의 장점과 단점을 가지고 있으며, 이를 이해하는 것은 요구 사항에 맞는 올바른 기술을 선택하는 데 도움이 됩니다.
function getData(callback) {
setTimeout(() => {
const data = 'Some data';
callback(data);
}, 1000);
}
getData((data) => {
console.log(data);
});
콜백은 다른 함수에 인수로 전달된 함수로, 외부 함수 내에서 어떤 종류의 루틴이나 액션을 완료하기 위해 호출됩니다.
장점:
- 기본 시나리오에 대해 이해하고 사용하기 쉽습니다.
- 여러 비동기 작업을 병렬로 처리할 수 있습니다.
단점:
- "콜백 지옥" 또는 "둔덕의 피라미드(Pyramid of Doom)"로 이어질 수 있어, 콜백이 콜백 내에 중첩되어 코드의 가독성과 유지 관리가 어려워집니다.
- 오류 처리가 번거롭고 직관적이지 않을 수 있습니다.
function getData() {
return new Promise((resolve, reject) => {
setTimeout(() => {
const data = 'Some data';
resolve(data);
}, 1000);
});
}
getData()
.then((data) => {
console.log(data);
})
.catch((error) => {
console.log(error);
});
프로미스는 비동기 작업의 최종 완료 또는 실패를 나타내는 객체입니다. ES6에서 도입된 이후 JavaScript의 핵심 부분이 되었습니다.
장점:
- 체인 연산(then/catch/finally)을 통해 콜백 지옥을 피할 수 있습니다.
.catch()
를 통한 오류 처리가 용이합니다.- 복잡한 비동기 작업에 대해 더 깨끗하고 관리하기 쉬운 코드 구조를 제공합니다.
단점:
- 매우 복잡한 비동기 흐름에 대해 여전히
.then()
호출의 복잡한 체인을 초래할 수 있습니다.
프로그래밍에서 콜백 함수(callback functions)가 여러 겹 중첩되어 사용될 때 발생하는 현상을 비유적으로 설명하는 용어입니다. 주로 JavaScript와 같은 비동기 프로그래밍에서 흔히 볼 수 있습니다. 이 현상은 코드의 가독성과 유지보수성을 크게 저해할 수 있습니다.
예를 들어, 하나의 비동기 작업이 완료된 후 다른 비동기 작업을 시작하고, 그 작업이 완료된 후 또 다른 작업을 시작하는 식으로 콜백 함수를 계속해서 중첩하게 되면, 코드는 오른쪽으로 계속해서 들여쓰기가 되면서 "피라미드" 또는 "계단" 모양을 이루게 됩니다. 이로 인해 코드가 매우 복잡해지고 이해하기 어려워지며, 오류를 찾고 수정하기도 어려워집니다.
doSomething(param1, function(err, result) { if (err) handleError(err); doSomethingElse(result, function(err, newResult) { if (err) handleError(err); doYetAnotherThing(newResult, function(err, finalResult) { if (err) handleError(err); console.log('Got the final result: ', finalResult); }); }); });위 코드 예제에서 볼 수 있듯이, 각 콜백 내에서 또 다른 콜백을 호출하게 되면 코드는 점점 더 깊은 레벨의 중첩으로 이어지게 되고, 이는 "둔덕의 피라미드"라고 불리는 구조를 만들게 됩니다. 이러한 문제를 해결하기 위해 ES6에서는 프로미스(Promises)를 도입했고, ES8에서는 async/await 구문을 도입해 비동기 코드를 더 쉽게 작성하고 관리할 수 있게 되었습니다.
async function getData() {
return new Promise((resolve, reject) => {
setTimeout(() => {
const data = 'Some data';
resolve(data);
}, 1000);
});
}
async function main() {
const data = await getData();
console.log(data);
}
main();
Async/await는 ES8에서 도입되었으며, 프로미스 위에 구축된 문법적 설탕입니다. 동기 코드와 같이 보이고 동작하는 비동기 코드를 작성할 수 있게 해주어, 이해하고 유지 관리하기 쉬워질 수 있습니다.
장점:
- 비동기 코드를 동기 코드처럼 보이고 동작하게 함으로써 가독성을 향상시킵니다.
- try/catch 블록을 사용한 프로미스 그룹 및 오류 처리를 단순화합니다.
- 프로미스 주위의 보일러플레이트 코드를 줄여줍니다.
단점:
- 비동기 코드를 동기 코드처럼 보이게 하여, 이벤트 루프가 어떻게 작동하는지에 대한 잘못된 이해를 초래할 수 있습니다.
- 프로미스를 기반으로 구축되었기 때문에 문제를 효과적으로 디버깅하려면 프로미스에 대한 이해가 필요합니다.
- 최신 브라우저와 Node.js 환경에서만 지원됩니다.
보일러플레이트(boilerplate)
소프트웨어 개발 분야에서, 프로젝트를 시작할 때마다 반복적으로 사용되는 코드나 문서의 표준 템플릿을 말합니다. 이 용어는 인쇄 및 출판 분야에서 유래되었는데, 여기서는 변경되지 않고 재사용되는 인쇄판을 가리키는 데 사용되었습니다.
callback, Promises, 그리고 async/await 중에서 선택하는 것은 특정 요구 사항과 다루고 있는 비동기 작업의 복잡성에 따라 달라집니다. 간단한 일회성 비동기 작업에는 콜백이 충분할 수 있습니다. 하지만, 여러 비동기 작업을 보다 읽기 쉽고 관리하기 쉬운 방식으로 관리해야 하는 더 복잡한 시나리오의 경우, 일반적으로 Promises와 async/await이 선호됩니다. 특
https://medium.com/@lelianto.eko/callback-vs-promise-vs-async-await-in-javascri-f29a63d57f72