JavaScript 비동기 처리 완벽 가이드 (Async, Await, Promise)
웹 개발을 하다 보면 가장 많이 마주치는 개념 중 하나가 바로 비동기 처리입니다. 네트워크 요청, 파일 읽기, 타이머 처리 등 시간 소요가 큰 작업을 효율적으로 처리하기 위해 비동기 프로그래밍은 필수입니다. 이 글에서는 자바스크립트 비동기 처리의 기초부터 콜백 함수 → Promise → Async/Await로 이어지는 현대적 접근 방식까지 단계별로 명확히 설명하겠습니다.
비동기 처리란 무엇인가?
기본적으로 자바스크립트는 싱글 스레드 언어입니다. 즉, 한 번에 한 작업만 수행할 수 있습니다.
하지만 시간이 오래 걸리는 작업(네트워크 요청 등)을 메인 스레드에서 기다리게 하면 브라우저가 멈추는 것처럼 보일 수 있습니다.
이를 방지하기 위해 자바스크립트는 비동기 처리를 지원합니다. 비동기 처리를 통해 긴 작업이 끝날 때까지 기다리지 않고 다음 작업을 바로 처리할 수 있습니다.
콜백 함수 (Callback Function)
가장 오래된 비동기 처리 방식입니다. 함수의 인자로 다른 함수를 전달하고, 해당 작업이 끝났을 때 호출됩니다.
function fetchData(callback) {
setTimeout(() => {
console.log("데이터를 가져왔습니다.");
callback();
}, 1000);
}
fetchData(() => {
console.log("다음 작업을 처리합니다.");
});
단점: 콜백 중첩 현상(콜백 지옥) 발생 → 코드 가독성 저하
Promise
콜백 지옥을 해결하기 위해 등장한 표준 객체입니다.
성공(resolve)과 실패(reject)를 명시적으로 구분하여 더 깔끔하게 비동기 흐름을 관리합니다.
function fetchData() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("데이터를 가져왔습니다.");
}, 1000);
});
}
fetchData()
.then(result => {
console.log(result);
})
.catch(error => {
console.error(error);
});
Async/Await
ES2017(ES8)부터 지원되는 최신 비동기 처리 방식입니다.
Promise를 더 직관적이고 동기 코드처럼 사용할 수 있게 해줍니다.
async function fetchData() {
return new Promise((resolve) => {
setTimeout(() => {
resolve("데이터를 가져왔습니다.");
}, 1000);
});
}
async function main() {
try {
const result = await fetchData();
console.log(result);
} catch (error) {
console.error(error);
}
}
main();
비동기 병렬 처리: Promise.all
여러 비동기 작업을 동시에 실행하고, 모든 작업이 끝날 때까지 기다리는 방법입니다.
async function fetchData1() {
return new Promise((resolve) => setTimeout(() => resolve("데이터1"), 1000));
}
async function fetchData2() {
return new Promise((resolve) => setTimeout(() => resolve("데이터2"), 1500));
}
async function main() {
const [data1, data2] = await Promise.all([fetchData1(), fetchData2()]);
console.log(data1);
console.log(data2);
}
main();
정리
- 콜백 함수: 가장 기본, 하지만 복잡해지면 콜백 지옥 발생
- Promise: 체인 방식, 명확한 성공/실패 처리 가능
- Async/Await: 가장 직관적, 동기 코드처럼 사용 가능
관련 공식 문서
이 글이 Javascript 비동기 처리의 이해와 활용에 도움이 되셨다면 좋아요와 댓글 부탁드립니다.
