JavaScript에서 비동기 작업을 처리할 때 가장 강력하고 직관적인 도구 중 하나가 Promise입니다. 과거에는 콜백(callback) 방식으로 비동기 처리를 많이 했지만, 콜백 헬(callback hell) 문제로 인해 코드가 복잡해지는 단점이 있었습니다. Promise는 이런 문제를 해결하기 위해 등장한 개념으로, 비동기 작업을 더욱 쉽게 처리할 수 있게 해 줍니다.
자바스크립트의 비동기 Promise: 이해와 활용
목차
Promise란?
Promise는 "미래에 완료될" 작업을 나타내는 객체입니다. 현재는 완료되지 않았지만, 언젠가 완료되거나 실패할 작업을 나타내며, 그 결과에 따라 적절한 처리를 할 수 있습니다. Promise는 주로 비동기 작업에서 데이터를 받아오거나, 파일을 읽고 쓰는 등의 상황에서 사용됩니다.
Promise의 3가지 상태
- Pending(대기 중): 비동기 작업이 아직 완료되지 않은 상태
- Fulfilled(이행됨): 비동기 작업이 성공적으로 완료된 상태, 비동기 작업의 성공 결과를 결괏값으로 갖게 됨
- Rejected(거부됨): 비동기 작업이 실패한 상태, 비동기 작업에서 발생한 오류를 결과값으로 갖게 됨
Promise의 사용 방법
Promise는 new Promise()로 생성할 수 있으며, 함수 내부에 resolve와 reject 콜백을 사용하여 작업의 성공과 실패를 처리합니다.
const myPromise = new Promise((resolve, reject) => {
let success = true; // 작업의 성공 여부
if (success) {
resolve("작업이 성공했습니다!"); // 작업이 성공한 경우
} else {
reject("작업이 실패했습니다."); // 작업이 실패한 경우
}
});
myPromise
.then(result => {
console.log(result); // 성공 시 메시지 출력
})
.catch(error => {
console.log(error); // 실패 시 에러 메시지 출력
});
위 코드에서 myPromise는 비동기 작업을 시뮬레이션합니다. 작업이 성공하면 resolve()가 호출되고, 실패하면 reject()가 호출됩니다. 이후 .then()과 .catch()를 사용해 결과를 처리합니다.
Promise 체이닝(Chaining)
Promise의 큰 장점 중 하나는 여러 비동기 작업을 순차적으로 실행할 때 체이닝을 이용할 수 있다는 점입니다. 각 .then() 블록은 이전 작업이 성공적으로 완료된 후 실행되며, 에러 처리는 .catch()에서 처리됩니다. 프라미스 체이닝이 가능한 이유는 promise.then을 호출하면 프라미스가 반환되기 때문입니다. 반환된 프라미스엔 당연히 .then을 호출할 수 있습니다.
fetchData()
.then(data => {
return processData(data);
})
.then(processedData => {
return saveData(processedData);
})
.then(() => {
console.log("모든 작업이 성공적으로 완료되었습니다.");
})
.catch(error => {
console.log("에러가 발생했습니다.", error);
})
위 예시에서 fetchData(), processData(), saveData()는 각각 비동기 작업을 처리하며, 각 작업이 성공적으로 완료될 때마다 다음 작업이 순차적으로 실행됩니다.
Promise 병렬 처리
비동기 작업을 병렬로 실행해야 할 때는 Promise.all()을 사용할 수 있습니다. 이는 여러 Promise를 동시에 실행하고, 모든 작업이 완료될 때까지 기다린 후 그 결과를 한 번에 반환합니다.
const promise1 = fetchDataFromAPI1();
const promise2 = fetchDataFromAPI2();
const promise3 = fetchDataFromAPI3();
Promise.all([promise1, promise2, promise3])
.then(results => {
console.log("모든 데이터를 성공적으로 가져왔습니다.", results);
})
.catch(error => {
console.log("에러가 발생했습니다.", error);
})
Promise.all()은 배열로 전달된 모든 Promise가 완료될 때까지 기다렸다가 결과를 반환합니다. 하나라도 실패하면 전체가 실패한 것으로 간주되어 에러가 발생합니다.
async와 await
async와 await는 Promise를 더욱 간결하고 직관적으로 작성할 수 있도록 도와주는 문법입니다. 비동기 작업을 마치 동기 작업처럼 작성할 수 있어 가독성이 좋아집니다. async 함수는 항상 Promise를 리턴하기 때문에 리턴된 Promise 객체의 값을 가져오려면 항상 await을 사용해야 합니다.
// 일반 함수
async function getData() {
const response = await fetch('fecthUrl');
const data = await response.json();
return data;
}
const fetchData = await getData();
// 화살표 함수
const getData = async () => {
const response = await fetch('fecthUrl');
const data = await response.json();
return data;
}
const fetchData = await getData();
위 코드에서 await 키워드는 Promise가 완료될 때까지(fulfilled 또는 rejected) 기다린 후 결과를 반환합니다.
- Fulfilled 상태면 Promise 객체의 결과를 리턴
- Rejected 상태면 Promise 객체의 오류를 throw
오류 처리
try & catch를 이용한 오류 처리
async function getData() {
try {
const response = await fetch('fetchUrl');
const data = await response.json();
console.log('데이터를 받아오는데 성공했습니다.', data);
} catch(error) {
console.log('에러가 발생했습니다.', error);
}
}
위 코드에서 실행되는 코드를 try로 감싸고, catch 안에서 에러를 처리하고 있습니다. try로 감싼 코드에서 에러가 발생되면 catch의 error 변수로 에러가 전달되고 catch문 안에서 에러가 처리됩니다. 만약 에러가 발생하더라도 꼭 실행해야 하는 코드가 있다면 finally를 사용하면 됩니다.
try & catch & finally를 이용한 오류 처리
async function getData() {
try {
const response = await fetch('fetchUrl');
const data = await response.json();
console.log('데이터를 받아오는데 성공했습니다.', data);
} catch(error) {
console.log('에러가 발생했습니다.', error);
return;
} finally {
console.log('try & catch의 결과와 상관없이 실행');
}
}
위 코드를 보면 catch에서 에러 처리 후 return을 해 함수가 종료돼야 하지만, finally가 있기 때문에 종료되지 않고 console.log()의 결과가 출력됩니다.
Promise 체인의 오류 처리
fetch('fetchUrl')
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.log('에러가 발생했습니다.', error))
.finally(() => console.log('try & catch의 결과와 상관없이 실행'));
Promise는 자바스크립트에서 비동기 작업을 더욱 효율적으로 처리하는 방법을 제공합니다. 콜백 함수에 비해 코드가 간결해지고, 체이닝과 병렬 처리를 통해 복잡한 비동기 로직도 쉽게 다룰 수 있습니다. 또한 async/await를 통해 가독성을 한층 더 높일 수 있습니다.
추천글
2024.09.20 - [개발 공부 일지/JavaScript] - [JS] 비동기 자바스크립트 - 콜백(Callback)
'개발 공부 일지 > JavaScript' 카테고리의 다른 글
[JS] Javascript에서 Axios 사용하기 (3) | 2024.09.24 |
---|---|
[JS] fetch 함수 - API 호출하기 (GET, POST) (5) | 2024.09.23 |
[JS] 자바스크립트 비동기 - 콜백(Callback) (1) | 2024.09.20 |
[JS] 자바스크립트의 this? (4) | 2024.09.19 |
[JS] 얕은 복사, 깊은 복사 (0) | 2024.09.19 |