Promise는 자바스크립트에서 비동기 작업을 처리하는 데 사용되는 객체로, 비동기 작업의 완료 또는 실패 상태를 나타냅니다. 기본적으로 Promise는 비동기 작업이 성공했는지 실패했는지를 추적하고, 그에 맞는 후속 처리를 관리하는 방식입니다. **콜백 지옥(Callback Hell)**을 피하고, 비동기 흐름을 더욱 읽기 쉽고, 관리하기 쉽게 만들어주는 중요한 도구입니다.
1. Promise의 기본 개념
Promise는 비동기 작업이 완료되었을 때의 약속을 나타냅니다. Promise는 3가지 상태를 가집니다:
• Pending (대기): 초기 상태로, 비동기 작업이 아직 완료되지 않은 상태입니다.
• Fulfilled (이행됨): 작업이 성공적으로 완료된 상태입니다.
• Rejected (거부됨): 작업이 실패한 상태입니다.
Promise의 구조
Promise는 resolve 또는 reject 함수로 이행되거나 거부되며, 각각 성공 또는 실패 상태를 나타냅니다. Promise는 이를 관리하기 위해 then(), catch(), **finally()**와 같은 메서드를 제공합니다.
let promise = new Promise(function(resolve, reject) {
// 비동기 작업 수행
let success = true; // 성공/실패를 나타내는 플래그
if (success) {
resolve("작업 성공!");
} else {
reject("작업 실패!");
}
});
then(), catch(), finally()
• then(onFulfilled): Promise가 **이행(Fulfilled)**되었을 때 실행할 함수를 정의합니다.
• catch(onRejected): Promise가 **거부(Rejected)**되었을 때 실행할 함수를 정의합니다.
• finally(onFinally): Promise의 성공 여부와 상관없이 항상 실행될 함수를 정의합니다.
2. Promise 사용 예시
다음은 기본적인 Promise 사용 예시입니다. setTimeout을 비동기 작업으로 가정하고, 2초 후 성공적으로 작업이 완료된 후 resolve가 호출됩니다.
let promise = new Promise(function(resolve, reject) {
setTimeout(() => {
resolve("2초 후 작업 성공!");
}, 2000);
});
promise
.then((result) => {
console.log(result); // "2초 후 작업 성공!"
})
.catch((error) => {
console.error(error);
})
.finally(() => {
console.log("Promise 완료"); // 항상 실행
});
3. Promise의 상태 변화
Promise는 다음과 같은 순서로 상태가 변경됩니다:
1. Pending: Promise가 처음 생성될 때.
2. Fulfilled: resolve가 호출되면 Promise가 이행됩니다.
3. Rejected: reject가 호출되면 Promise가 거부됩니다.
Promise는 한 번 상태가 변경되면 다시 상태가 변하지 않습니다. 즉, 이행되거나 거부되면 해당 상태가 고정됩니다.
let promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("작업 성공");
reject("작업 실패"); // 이 코드는 실행되지 않음
}, 1000);
});
promise.then(console.log).catch(console.error); // "작업 성공" 출력
4. Promise의 체이닝 (Chaining)
Promise 체이닝은 여러 비동기 작업을 순차적으로 처리해야 할 때 유용합니다. 하나의 Promise가 완료되면 다음 then()에서 다른 Promise를 반환하여, 그 결과를 다시 처리하는 방식입니다.
let promise = new Promise((resolve, reject) => {
setTimeout(() => resolve(1), 1000); // 1초 후 resolve(1)
});
promise
.then((result) => {
console.log(result); // 1
return result * 2; // 다음 then()에 값 전달
})
.then((result) => {
console.log(result); // 2
return result * 2;
})
.then((result) => {
console.log(result); // 4
});
여기서 중요한 점은 then()이 새로운 Promise를 반환한다는 것입니다. 이 덕분에 여러 비동기 작업을 순차적으로 처리할 수 있으며, 코드의 흐름을 더 쉽게 이해할 수 있습니다.
5. Promise.all()과 Promise.race()
자바스크립트에서 여러 Promise를 동시에 처리해야 할 때 유용한 메서드가 **Promise.all()**과 **Promise.race()**입니다.
5.1 Promise.all()
Promise.all()은 주어진 모든 Promise가 이행될 때까지 기다렸다가 결과를 배열로 반환합니다. 만약 하나의 Promise라도 거부되면, 전체 Promise가 거부됩니다.
let promise1 = new Promise((resolve) => setTimeout(resolve, 1000, "첫 번째"));
let promise2 = new Promise((resolve) => setTimeout(resolve, 2000, "두 번째"));
let promise3 = new Promise((resolve, reject) => setTimeout(reject, 1500, "세 번째 실패"));
Promise.all([promise1, promise2, promise3])
.then((results) => {
console.log(results); // 모든 Promise가 성공했을 때 출력
})
.catch((error) => {
console.error(error); // 하나라도 실패하면 에러 출력
});
위 코드에서 promise3가 실패하기 때문에, Promise.all()은 그 즉시 거부됩니다.
5.2 Promise.race()
Promise.race()는 가장 먼저 완료되는 Promise의 결과를 반환합니다. 즉, 여러 Promise 중 가장 빠른 Promise의 결과를 취합니다.
let promise1 = new Promise((resolve) => setTimeout(resolve, 1000, "첫 번째"));
let promise2 = new Promise((resolve) => setTimeout(resolve, 2000, "두 번째"));
let promise3 = new Promise((resolve, reject) => setTimeout(reject, 500, "세 번째 실패"));
Promise.race([promise1, promise2, promise3])
.then((result) => {
console.log(result); // 가장 먼저 완료된 Promise 출력 (세 번째 실패)
})
.catch((error) => {
console.error(error); // 에러 발생 시 처리
});
위 코드에서는 promise3가 500ms 후 거부되기 때문에, Promise.race()는 가장 먼저 완료된(거부된) Promise를 반환합니다.
6. async/await와 Promise
async/await는 Promise 기반 비동기 작업을 더 직관적이고 동기적인 방식으로 처리할 수 있게 해줍니다. await 키워드는 Promise가 해결될 때까지 기다리는 역할을 하며, 이는 비동기 코드를 동기적 코드처럼 읽기 쉽게 만들어줍니다.
6.1 async/await의 기본 사용법
async function fetchData() {
try {
let result = await new Promise((resolve, reject) => {
setTimeout(() => resolve("데이터 가져오기 성공!"), 1000);
});
console.log(result); // "데이터 가져오기 성공!" 출력
} catch (error) {
console.error(error);
}
}
fetchData();
• async 함수는 항상 Promise를 반환하며, 함수 내부에서 await 키워드를 사용해 Promise의 결과를 기다릴 수 있습니다.
• try/catch 블록을 사용해 비동기 작업 중 발생한 에러를 처리할 수 있습니다.
6.2 async/await와 Promise.all()
Promise.all()과 async/await을 함께 사용하면, 여러 비동기 작업을 동시에 처리할 수 있습니다.
async function fetchAllData() {
let [data1, data2, data3] = await Promise.all([
new Promise((resolve) => setTimeout(resolve, 1000, "데이터1")),
new Promise((resolve) => setTimeout(resolve, 2000, "데이터2")),
new Promise((resolve) => setTimeout(resolve, 1500, "데이터3")),
]);
console.log(data1, data2, data3); // 데이터1 데이터3 데이터2 출력
}
fetchAllData();
결론
• Promise는 자바스크립트에서 비동기 작업을 처리하는 중요한 객체로, 콜백 지옥을 피하고 체이닝을 통해 비동기 작업을 순차적으로 처리할 수 있습니다.
• Promise의 상태는 Pending(대기), Fulfilled(이행), Rejected(거부)로 나뉘며, 각각의 상태에서 후속 처리를 할 수 있는 then, catch, finally 등의 메서드를 제공합니다.
• Promise 체이닝은 여러 비동기 작업을 순차적으로 처리해야 할 때 유용하며, then()을 통해 하나의 작업이 완료된 후 다음 작업을 정의할 수 있습니다.
• **Promise.all()**은 여러 Promise가 모두 이행될 때까지 기다리며, 성공한 결과를 배열로 반환하는 반면, **Promise.race()**는 가장 먼저 완료되는 Promise의 결과를 반환합니다.
• **async/await**는 Promise 기반 비동기 작업을 동기적인 방식으로 처리할 수 있게 해주는 문법으로, 코드의 가독성을 크게 개선하며 try/catch를 통해 에러 처리가 가능합니다.
결론적으로 Promise는 자바스크립트의 비동기 작업을 처리하는 강력한 도구로, 다양한 상황에서 유용하게 활용됩니다. 또한, **async/await**을 사용하면 비동기 코드를 더욱 직관적으로 작성할 수 있어 가독성과 유지보수성을 높일 수 있습니다.
'JavaScript' 카테고리의 다른 글
[JS] async/await (1) | 2024.09.20 |
---|---|
[JS] 얕은복사, 깊은복사 (2) | 2024.09.08 |
[JS] 자바스크립트의 동작방식(비동기,동기) (0) | 2024.09.08 |
[JS] Callback (0) | 2024.09.08 |
[JS] 함수와 클래스(this) (0) | 2024.09.08 |