자바스크립트 비동기 처리 - 콜백 함수와 콜백 헬, 프로미스 (Promise) async와 await 비동기 데이터 처리 (fetch, Axios 등)
8. 자바스크립트 비동기 처리
자바스크립트는 기본적으로 싱글 스레드로 동작하는 언어입니다. 즉, 한 번에 하나의 작업만 처리할 수 있는 구조입니다. 하지만 실제 웹 애플리케이션에서는 네트워크 요청, 파일 읽기, 타이머 설정 등 시간이 오래 걸리는 작업을 자주 만나게 됩니다. 이때 비동기 처리가 필요하며, 자바스크립트에서는 콜백 함수, 프로미스(Promise), async/await 등을 이용해 비동기 작업을 처리합니다. 이 장에서는 자바스크립트의 비동기 처리 방법을 자세히 다룹니다.
8.1 콜백 함수와 콜백 헬
8.1.1 콜백 함수
콜백 함수는 다른 함수의 인수로 전달되어, 특정 작업이 완료된 후 호출되는 함수입니다. 비동기 작업에서 자주 사용되며, 작업이 끝난 후 결과를 처리하기 위해 사용됩니다.
예시: 콜백 함수
javascriptfunction fetchData(callback) {
setTimeout(() => {
console.log("Data fetched");
callback("Here is the data");
}, 1000);
}
fetchData((data) => {
console.log(data);
});
위 코드에서는 fetchData
함수가 1초 후 데이터를 가져온 다음 콜백 함수로 그 데이터를 전달합니다. callback
함수는 데이터를 받아 처리합니다.
8.1.2 콜백 헬 (Callback Hell)
콜백 함수는 간단한 비동기 작업에는 유용하지만, 여러 비동기 작업이 중첩되면 코드가 매우 복잡해질 수 있습니다. 이 현상을 콜백 헬이라고 하며, 코드의 가독성이 크게 떨어집니다.
예시: 콜백 헬
javascriptsetTimeout(() => {
console.log("Step 1");
setTimeout(() => {
console.log("Step 2");
setTimeout(() => {
console.log("Step 3");
}, 1000);
}, 1000);
}, 1000);
위 코드는 3단계의 비동기 작업을 중첩된 콜백 함수로 처리합니다. 이처럼 여러 단계로 중첩될 경우 코드가 읽기 어렵고 유지보수가 힘들어집니다. 이 문제를 해결하기 위해 프로미스(Promise)와 async/await가 도입되었습니다.
8.2 프로미스 (Promise)
프로미스(Promise)는 자바스크립트에서 비동기 작업을 처리하기 위해 제공되는 객체입니다. 프로미스는 비동기 작업이 성공했을 때의 결과와 실패했을 때의 이유를 처리할 수 있습니다. 콜백 함수보다 가독성이 좋고, 비동기 작업을 더 깔끔하게 관리할 수 있습니다.
8.2.1 프로미스의 상태
프로미스는 세 가지 상태를 가집니다:
- 대기(pending): 비동기 작업이 아직 완료되지 않은 상태.
- 이행(fulfilled): 비동기 작업이 성공적으로 완료된 상태.
- 거부(rejected): 비동기 작업이 실패한 상태.
8.2.2 프로미스 생성
Promise
객체를 사용하여 비동기 작업을 처리할 수 있습니다. Promise
는 두 개의 콜백 함수(이행할 때 호출되는 resolve
와 거부할 때 호출되는 reject
)를 인수로 받습니다.
예시: 프로미스 생성
javascriptconst myPromise = new Promise((resolve, reject) => {
const success = true;
if (success) {
resolve("Data fetched successfully!");
} else {
reject("Error fetching data.");
}
});
myPromise
.then((message) => {
console.log(message);
})
.catch((error) => {
console.error(error);
});
위 코드에서 myPromise
는 resolve
와 reject
를 이용해 성공 또는 실패를 처리합니다. then()
메서드는 성공 시 실행될 코드를, catch()
메서드는 실패 시 실행될 코드를 처리합니다.
8.2.3 프로미스 체이닝 (Chaining)
여러 비동기 작업을 순차적으로 처리할 때, 프로미스를 이용한 체이닝을 사용할 수 있습니다. 이는 콜백 지옥 문제를 해결하는 좋은 방법입니다.
예시: 프로미스 체이닝
javascriptconst fetchData = () => {
return new Promise((resolve) => {
setTimeout(() => {
resolve("Data 1 fetched");
}, 1000);
});
};
const processData = (data) => {
return new Promise((resolve) => {
setTimeout(() => {
resolve(`${data} processed`);
}, 1000);
});
};
fetchData()
.then((data) => {
console.log(data); // Data 1 fetched
return processData(data);
})
.then((processedData) => {
console.log(processedData); // Data 1 fetched processed
})
.catch((error) => {
console.error(error);
});
위 예제에서 fetchData()
와 processData()
는 순차적으로 실행되며, 각각의 결과는 체이닝을 통해 전달됩니다.
8.3 async와 await
async와 await는 프로미스를 더 간단하고 직관적으로 사용할 수 있게 해주는 ES2017(ES8)의 문법입니다. async/await
을 사용하면 비동기 코드를 동기적인 코드처럼 작성할 수 있어 가독성이 크게 향상됩니다.
8.3.1 async 함수
async
키워드를 함수 앞에 붙이면 그 함수는 항상 프로미스를 반환합니다. 이 함수 내부에서 await
을 사용할 수 있습니다.
javascriptasync function fetchData() {
return "Data fetched";
}
fetchData().then((data) => {
console.log(data); // Data fetched
});
8.3.2 await 키워드
await
키워드는 프로미스가 이행될 때까지 기다린 후 그 결과를 반환합니다. await
은 오직 async
함수 내부에서만 사용할 수 있습니다.
예시: async와 await 사용
javascriptconst fetchData = () => {
return new Promise((resolve) => {
setTimeout(() => {
resolve("Data fetched");
}, 1000);
});
};
async function process() {
const data = await fetchData();
console.log(data); // Data fetched
}
process();
위 코드에서 await fetchData()
는 fetchData()
가 프로미스를 반환하고 그 프로미스가 이행될 때까지 기다립니다. 이로 인해 비동기 작업을 마치 동기적인 코드처럼 쉽게 처리할 수 있습니다.
8.3.3 try...catch로 에러 처리
async/await
에서는 try...catch
구문을 사용하여 에러를 처리할 수 있습니다.
javascriptconst fetchData = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject("Error fetching data.");
}, 1000);
});
};
async function process() {
try {
const data = await fetchData();
console.log(data);
} catch (error) {
console.error(error); // Error fetching data.
}
}
process();
위 코드에서는 try...catch
구문을 사용하여 await
으로 기다리던 프로미스가 실패할 경우 에러를 처리합니다.
8.4 비동기 데이터 처리 (fetch, Axios 등)
웹 애플리케이션에서는 비동기적으로 데이터를 서버에서 받아오거나 서버로 전송해야 하는 경우가 많습니다. 자바스크립트에서 이러한 HTTP 요청을 처리하는 데 자주 사용되는 방법으로는 fetch
API와 Axios 라이브러리가 있습니다.
8.4.1 fetch API
fetch
는 자바스크립트의 내장 함수로, HTTP 요청을 보내고 그 응답을 처리하는 데 사용됩니다. fetch
는 프로미스를 반환하며, 이를 통해 비동기적으로 데이터를 처리할 수 있습니다.
예시: fetch API 사용
javascriptfetch("https://api.example.com/data")
.then((response) => {
return response.json(); // JSON 응답을 객체로 변환
})
.then((data) => {
console.log(data);
})
.catch((error) => {
console.error("Error fetching data:", error);
});
fetch
는 기본적으로 GET 요청을 보내며, 응답은 response.json()
을 통해 JSON 데이터를 자바스크립트 객체로 변환할 수 있습니다.
8.4.2 POST 요청 보내기 (fetch API)
fetch
를 사용하여 POST 요청을 보낼 수도 있습니다. fetch
의 두 번째 인수로 설정 객체를 전달하여 요청 메서드와 헤더, 본문 데이터를 지정할 수 있습니다.
예시: POST 요청 보내기
javascriptfetch("https://api.example.com/data", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({ name: "Alice", age: 25 })
})
.then((response) => response.json())
.then((data) => {
console.log("Data received:", data);
})
.catch((error) => {
console.error("Error:", error);
});
위 코드에서 method
는 POST로 지정되었으며, body
에 전송할 데이터를 JSON 형식으로 변환하여 보냈습니다.
8.4.3 Axios 라이브러리
Axios는 HTTP 요청을 처리하는 데 널리 사용되는 자바스크립트 라이브러리로, fetch
보다 더 많은 기능을 제공합니다. Axios는 기본적으로 프로미스를 반환하며, 요청과 응답에서 자동으로 JSON 데이터를 처리합니다.
Axios 설치
bashnpm install axios
예시: Axios 사용
javascriptconst axios = require("axios");
axios.get("https://api.example.com/data")
.then((response) => {
console.log(response.data);
})
.catch((error) => {
console.error("Error:", error);
});
8.4.4 POST 요청 보내기 (Axios)
Axios로 POST 요청을 보내는 방법은 매우 간단합니다.
javascriptaxios.post("https://api.example.com/data", {
name: "Alice",
age: 25
})
.then((response) => {
console.log("Data received:", response.data);
})
.catch((error) => {
console.error("Error:", error);
});
Axios는 설정이 간단하고 fetch
보다 직관적인 문법을 제공하기 때문에 많은 프로젝트에서 선호됩니다.
비동기 처리는 자바스크립트 애플리케이션에서 중요한 역할을 합니다. 콜백 함수는 간단한 비동기 작업에는 유용하지만, 콜백 지옥 문제를 해결하기 위해 프로미스와 async/await이 도입되었습니다. 이러한 비동기 처리 방식은 서버에서 데이터를 받아오거나 사용자와의 상호작용을 처리할 때 자주 사용됩니다. 또한 fetch
API와 Axios는 서버와의 통신에서 비동기적으로 데이터를 처리하는 데 매우 유용한 도구입니다.
댓글 쓰기
0 댓글