학습
JavaScript 비동기 프로그래밍 (Promise)
JavaScript 비동기 프로그래밍 (Promise) — 초급
비동기 프로그래밍 (Promise)
1. 도입 (왜 배워야 하는가)
비동기 프로그래밍은 현대 웹 개발에서 매우 중요한 개념입니다. 웹 애플리케이션은 사용자와 상호작용하는 동시에 여러 작업을 수행해야 하므로, 비동기 처리를 통해 사용자 경험을 개선할 수 있습니다. 예를 들어, 데이터베이스에서 정보를 가져오거나 외부 API와 통신할 때, 이러한 작업이 완료될 때까지 사용자가 기다리게 만드는 것은 좋지 않은 사용자 경험을 초래합니다.
이런 문제를 해결하기 위해 JavaScript에서는 Promise라는 개념을 도입하였습니다. Promise를 사용하지 않으면, 복잡한 콜백 지옥(callback hell) 구조에 빠질 수 있으며, 코드의 가독성이 떨어지고 유지보수가 어려워집니다.
2. 핵심 개념 설명
Promise는 비동기 작업의 완료 또는 실패를 나타내는 객체입니다. 이를 통해 비동기 작업을 보다 쉽게 관리할 수 있습니다. Promise는 세 가지 상태(state)를 가집니다:
- 대기(pending): 초기 상태, 아직 결과를 반환하지 않음
- 이행(fulfilled): 비동기 작업이 완료되어 결과를 반환함
- 거부(rejected): 비동기 작업이 실패함
비유하자면, Promise는 주문한 음식이 배달될 때까지의 상태와 유사합니다. 음식이 준비되면 "이행"되고, 문제가 발생하면 "거부"됩니다.
| 상태 | 설명 |
|---|---|
| 대기 | 아직 결과가 없음 |
| 이행 | 성공적으로 결과가 반환됨 |
| 거부 | 실패하여 에러가 발생함 |
3. 기본 코드 예제
아래는 Promise의 기본 사용법을 보여주는 코드입니다.
const myPromise = new Promise((resolve, reject) => {
const success = true; // 성공 여부를 결정하는 변수
if (success) {
resolve("작업이 성공적으로 완료되었습니다."); // 이행
} else {
reject("작업에 실패했습니다."); // 거부
}
});
myPromise
.then(result => {
console.log(result); // 이행된 결과 출력
})
.catch(error => {
console.error(error); // 거부된 에러 출력
});
실행 결과:
작업이 성공적으로 완료되었습니다.
const myPromise = new Promise(...): 새로운 Promise 객체를 생성합니다.resolve(...): 비동기 작업이 성공했음을 나타내며, 이후 then으로 연결된 메서드가 호출됩니다.reject(...): 비동기 작업이 실패했음을 나타내며, 이후 catch로 연결된 메서드가 호출됩니다.myPromise.then(...): Promise가 이행되었을 때 실행될 콜백 함수를 정의합니다.myPromise.catch(...): Promise가 거부되었을 때 실행될 콜백 함수를 정의합니다.4. 실전 활용 예제
예제 1: API 데이터 요청
쇼핑몰에서 제품 목록을 API로부터 가져올 때 Promise를 사용할 수 있습니다.
function fetchProducts() {
return new Promise((resolve, reject) => {
setTimeout(() => {
const products = ["상품1", "상품2", "상품3"];
resolve(products);
}, 2000); // 2초 후에 데이터 반환
});
}
fetchProducts()
.then(products => {
console.log("가져온 제품:", products);
})
.catch(error => {
console.error("오류 발생:", error);
});
설명: 위 코드는 2초 후에 제품 목록을 가져오는 예제입니다. 실제 웹 애플리케이션에서는 API 통신 시 Promise를 사용하여 비동기적으로 데이터를 처리합니다.
예제 2: 여러 비동기 작업 처리
여러 개의 API 요청을 동시에 처리할 때 Promise.all을 사용할 수 있습니다.
const fetchUserData = () => new Promise(resolve => {
setTimeout(() => resolve("사용자 데이터"), 1000);
});
const fetchOrderData = () => new Promise(resolve => {
setTimeout(() => resolve("주문 데이터"), 1500);
});
Promise.all([fetchUserData(), fetchOrderData()])
.then(([userData, orderData]) => {
console.log(userData, orderData);
})
.catch(error => {
console.error("오류 발생:", error);
});
설명: 여러 개의 비동기 작업을 동시에 실행하고, 모두 완료된 후에 결과를 처리합니다. 이처럼 Promise는 복잡한 비동기 로직을 단순하게 만들어 줍니다.
5. 흔한 실수와 주의사항
실수 1: Promise 체인을 잊는 것
// 잘못된 코드
myPromise.then(result => {
console.log(result);
// 여기서 return을 하지 않음
});
이 경우, 다음에 이어지는 Promise가 없기 때문에 이후 작업이 실행되지 않습니다.
실수 2: reject를 잊는 것
const myPromise = new Promise((resolve, reject) => {
const success = false;
if (success) {
resolve("성공");
}
// reject를 호출하지 않음
});
myPromise
.then(result => console.log(result))
.catch(error => console.error(error)); // error가 출력되지 않음
이 경우, Promise가 항상 대기 상태로 남아있어 적절한 에러 처리가 되지 않습니다.
6. 정리
.then()과 .catch() 메서드를 활용하여 결과를 처리합니다.Promise.all을 사용하면 유용합니다.다음에 학습하면 좋은 주제: