
비동기(asynchronous) 처리는 프로그램이 특정 작업을 수행하는 동안 다른 작업을 동시에 실행할 수 있도록 하는 방식이다. 이는 동기(synchronous) 방식과 대비되는 개념으로, 동기 방식은 하나의 작업이 끝나야만 다음 작업을 수행할 수 있다.
비동기 처리는 특히 I/O 작업(파일 읽기/쓰기, 네트워크 요청, 데이터베이스 접근 등) 에서 중요하다. 비동기를 활용하면 성능을 향상시키고 블로킹(blocking) 없이 빠르게 응답할 수 있다.
자바스크립트에서 비동기 처리를 구현하는 주요 방법은 다음과 같다.
콜백 함수는 특정 작업이 완료된 후 실행되는 함수다.
function fetchData(callback) {
setTimeout(() => {
console.log("데이터 가져오기 완료");
callback();
}, 2000);
}
function processData() {
console.log("데이터 처리 시작");
}
fetchData(processData);
하지만, 콜백을 중첩해서 사용하면 콜백 지옥(Callback Hell) 이 발생할 수 있어 가독성이 떨어진다.
Promise는 비동기 작업의 성공 또는 실패를 나타내는 객체다.
function fetchData() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("데이터 가져오기 완료");
}, 2000);
});
}
fetchData()
.then(response => {
console.log(response);
return "데이터 처리 시작";
})
.then(console.log)
.catch(error => console.error("에러 발생:", error));
Promise를 사용하면 가독성이 개선되지만, .then() 체이닝이 길어지면 코드가 복잡해질 수 있다.
async와 await는 Promise를 기반으로 비동기 코드를 더욱 직관적으로 작성할 수 있도록 도와준다.
async function fetchData() {
return new Promise((resolve) => {
setTimeout(() => {
resolve("데이터 가져오기 완료");
}, 2000);
});
}
async function processData() {
console.log("데이터 요청 중...");
const data = await fetchData();
console.log(data);
console.log("데이터 처리 완료");
}
processData();
await 키워드는 Promise가 해결될 때까지 기다리므로, then() 체이닝보다 가독성이 높아진다. 단, await는 async 함수 내부에서만 사용할 수 있다.
async / await 사용 시에는 try...catch 문을 활용하여 예외 처리를 해야 한다.
async function fetchDataWithError() {
return new Promise((_, reject) => {
setTimeout(() => {
reject("데이터 가져오기 실패");
}, 2000);
});
}
async function processDataSafely() {
try {
console.log("데이터 요청 중...");
const data = await fetchDataWithError();
console.log(data);
} catch (error) {
console.error("에러 발생:", error);
}
}
processDataSafely();
여러 개의 비동기 작업을 병렬로 실행하려면 Promise.all()을 사용할 수 있다.
async function fetchData1() {
return new Promise(resolve => setTimeout(() => resolve("데이터1 완료"), 2000));
}
async function fetchData2() {
return new Promise(resolve => setTimeout(() => resolve("데이터2 완료"), 3000));
}
async function processAllData() {
console.log("모든 데이터 요청 시작");
const [data1, data2] = await Promise.all([fetchData1(), fetchData2()]);
console.log(data1, data2);
}
processAllData();
이렇게 하면 fetchData1()과 fetchData2()가 동시에 실행되므로 더 빠르게 결과를 얻을 수 있다.
async / await는 가장 직관적이고 가독성이 좋은 방법이며, try...catch로 에러를 처리해야 한다.Promise.all()을 활용한다.