자바스크립트는 싱글 스레드 언어입니다. 그런데도 수많은 네트워크 요청과 파일 I/O를 막힘없이 처리할 수 있는 이유는 바로 비동기 처리 메커니즘 덕분입니다. 이번 포스팅에서는 콜백(Callback)부터 시작해 Promise, 그리고 현대적인 Async/Await까지 비동기 처리의 발전 과정을 코드와 함께 살펴보겠습니다.
1단계: Callback - 가장 기본적인 비동기 처리
콜백은 함수를 다른 함수의 인자로 전달해 나중에 실행하는 패턴입니다. 이해하기는 쉽지만, 중첩이 깊어지면 '콜백 지옥(Callback Hell)'이 발생합니다.
// 콜백 지옥 예시
getUser(userId, function(user) {
getOrders(user.id, function(orders) {
getOrderDetail(orders[0].id, function(detail) {
// 점점 깊어지는 들여쓰기...
console.log(detail);
});
});
});
2단계: Promise - 콜백 지옥 탈출
Promise는 비동기 작업의 완료 또는 실패를 나타내는 객체입니다. .then()과 .catch()를 체이닝해 가독성을 크게 높일 수 있습니다.
// Promise 체이닝
getUser(userId)
.then(user => getOrders(user.id))
.then(orders => getOrderDetail(orders[0].id))
.then(detail => console.log(detail))
.catch(err => console.error('오류 발생:', err));
3단계: Async/Await - 동기 코드처럼 쓰는 비동기
Async/Await는 Promise를 기반으로 하되, 마치 동기 코드처럼 읽히는 문법을 제공합니다. ES2017(ES8)에 도입되었으며 현재 가장 널리 사용되는 비동기 패턴입니다.
// Async/Await - 가장 깔끔한 방식
async function fetchOrderDetail(userId) {
try {
const user = await getUser(userId);
const orders = await getOrders(user.id);
const detail = await getOrderDetail(orders[0].id);
console.log(detail);
} catch (err) {
console.error('오류 발생:', err);
}
}
세 가지 방식을 이해하면 레거시 코드 리팩토링부터 최신 코드 작성까지 유연하게 대응할 수 있습니다.
Tip💡 여러 비동기 작업을 병렬로 처리할 때는 Promise.all()을 활용하세요. await를 반복문 안에서 사용하면 순차 실행이 되므로 성능에 주의하세요.
'JavaScript' 카테고리의 다른 글
| [JavaScript] 탐색 메서드 (0) | 2024.04.05 |
|---|---|
| [JavaScript] 명시적 형변환 (0) | 2024.04.04 |