자바스크립트 비동기 처리 - 콜백 함수와 콜백 헬, 프로미스 (Promise) async와 await 비동기 데이터 처리 (fetch, Axios 등)

8. 자바스크립트 비동기 처리

자바스크립트는 기본적으로 싱글 스레드로 동작하는 언어입니다. 즉, 한 번에 하나의 작업만 처리할 수 있는 구조입니다. 하지만 실제 웹 애플리케이션에서는 네트워크 요청, 파일 읽기, 타이머 설정 등 시간이 오래 걸리는 작업을 자주 만나게 됩니다. 이때 비동기 처리가 필요하며, 자바스크립트에서는 콜백 함수, 프로미스(Promise), async/await 등을 이용해 비동기 작업을 처리합니다. 이 장에서는 자바스크립트의 비동기 처리 방법을 자세히 다룹니다.

자바스크립트 비동기 처리


8.1 콜백 함수와 콜백 헬

8.1.1 콜백 함수

콜백 함수는 다른 함수의 인수로 전달되어, 특정 작업이 완료된 후 호출되는 함수입니다. 비동기 작업에서 자주 사용되며, 작업이 끝난 후 결과를 처리하기 위해 사용됩니다.


예시: 콜백 함수

javascript
function 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)

콜백 함수는 간단한 비동기 작업에는 유용하지만, 여러 비동기 작업이 중첩되면 코드가 매우 복잡해질 수 있습니다. 이 현상을 콜백 헬이라고 하며, 코드의 가독성이 크게 떨어집니다.


예시: 콜백 헬

javascript
setTimeout(() => { 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 프로미스의 상태

프로미스는 세 가지 상태를 가집니다:

  1. 대기(pending): 비동기 작업이 아직 완료되지 않은 상태.
  2. 이행(fulfilled): 비동기 작업이 성공적으로 완료된 상태.
  3. 거부(rejected): 비동기 작업이 실패한 상태.

8.2.2 프로미스 생성

Promise 객체를 사용하여 비동기 작업을 처리할 수 있습니다. Promise는 두 개의 콜백 함수(이행할 때 호출되는 resolve와 거부할 때 호출되는 reject)를 인수로 받습니다.


예시: 프로미스 생성

javascript
const 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); });

위 코드에서 myPromiseresolvereject를 이용해 성공 또는 실패를 처리합니다. then() 메서드는 성공 시 실행될 코드를, catch() 메서드는 실패 시 실행될 코드를 처리합니다.


8.2.3 프로미스 체이닝 (Chaining)

여러 비동기 작업을 순차적으로 처리할 때, 프로미스를 이용한 체이닝을 사용할 수 있습니다. 이는 콜백 지옥 문제를 해결하는 좋은 방법입니다.


예시: 프로미스 체이닝

javascript
const 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

asyncawait는 프로미스를 더 간단하고 직관적으로 사용할 수 있게 해주는 ES2017(ES8)의 문법입니다. async/await을 사용하면 비동기 코드를 동기적인 코드처럼 작성할 수 있어 가독성이 크게 향상됩니다.


8.3.1 async 함수

async 키워드를 함수 앞에 붙이면 그 함수는 항상 프로미스를 반환합니다. 이 함수 내부에서 await을 사용할 수 있습니다.

javascript
async function fetchData() { return "Data fetched"; } fetchData().then((data) => { console.log(data); // Data fetched });

8.3.2 await 키워드

await 키워드는 프로미스가 이행될 때까지 기다린 후 그 결과를 반환합니다. await은 오직 async 함수 내부에서만 사용할 수 있습니다.


예시: async와 await 사용

javascript
const 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 구문을 사용하여 에러를 처리할 수 있습니다.

javascript
const 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 APIAxios 라이브러리가 있습니다.


8.4.1 fetch API

fetch는 자바스크립트의 내장 함수로, HTTP 요청을 보내고 그 응답을 처리하는 데 사용됩니다. fetch는 프로미스를 반환하며, 이를 통해 비동기적으로 데이터를 처리할 수 있습니다.


예시: fetch API 사용

javascript
fetch("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 요청 보내기

javascript
fetch("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 설치

bash
npm install axios


예시: Axios 사용

javascript
const 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 요청을 보내는 방법은 매우 간단합니다.

javascript
axios.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 APIAxios는 서버와의 통신에서 비동기적으로 데이터를 처리하는 데 매우 유용한 도구입니다.

댓글 쓰기

0 댓글