JavaScript에서는 비동기 처리를 할 때, 특히 API 호출이나 데이터 로딩과 같은 시간이 오래 걸리는 작업에서 동기적 처리와 같은 방식으로 기다려야 할 때가 많습니다. 이럴 때 유용하게 사용되는 것이 바로 Promise입니다.
Promise란?
Promise는 JavaScript에서 비동기 작업의 결과를 다루기 위한 객체입니다. 비동기 작업이 완료되었을 때 성공적으로 완료되었는지 또는 실패했는지를 처리할 수 있도록 도와줍니다.
Promise의 기본 구조
Promise는 주로 세 가지 상태를 가집니다:
- Pending: 작업이 아직 진행 중일 때.
- Resolved (Fulfilled): 작업이 성공적으로 완료되었을 때.
- Rejected: 작업이 실패했을 때.
let myPromise = new Promise((resolve, reject) => {
let success = true; // 예시로 성공적인 작업을 가정
if (success) {
resolve("작업 성공!");
} else {
reject("작업 실패!");
}
});
myPromise
.then(result => console.log(result)) // 성공 시 호출
.catch(error => console.log(error)); // 실패 시 호출
Promise 사용 이유
비동기 작업을 처리할 때 콜백 함수를 사용하면 여러 개의 비동기 작업이 순차적으로 처리될 때 콜백 지옥(callback hell) 문제가 발생할 수 있습니다. 이를 해결하기 위해 Promise는 **then**과 catch 메서드를 제공하여, 비동기 작업이 완료된 후에 후속 작업을 처리할 수 있게 도와줍니다.
await와 async와 함께 사용하기
async와 await는 Promise를 보다 직관적이고 간단하게 사용할 수 있게 해줍니다. async는 함수 앞에 붙여서 해당 함수가 비동기적으로 실행되도록 하고, await는 비동기 작업이 끝날 때까지 기다리게 만듭니다.
const fetchData = async () => {
try {
let data = await fetch('https://api.example.com/data'); // 비동기 작업
let json = await data.json();
console.log(json); // 데이터가 준비되었을 때 실행
} catch (error) {
console.error("데이터를 불러오는 데 실패했습니다:", error);
}
};
fetchData(); // 호출
위 코드에서는 await를 사용하여 fetch가 완료될 때까지 기다리고, 그 후에 데이터를 처리합니다. 이를 통해 코드가 동기적으로 실행되는 것처럼 보이지만, 실제로는 비동기적으로 작업이 진행됩니다.
비동기 데이터 로딩 후 모달 열기
Promise를 사용하면 비동기 데이터가 로드될 때까지 기다린 후, 그 데이터를 이용해 후속 작업을 실행할 수 있습니다. 예를 들어, 비동기 작업이 완료된 후에 모달을 열거나 UI를 업데이트하는 작업을 할 때, Promise와 await를 활용하여 데이터를 기다리고, 로드된 후에 작업을 진행할 수 있습니다.
예시
let selectDataPromise; // 데이터를 받아오는 Promise 저장 변수
let selectData = []; // 받아온 데이터 저장 변수
const opened = async () => {
// 데이터를 불러오는 Promise 저장 (한 번만 실행)
selectDataPromise = (async () => {
let ret = await api.get('/api.example.com/data'');
selectData = ret.data.contents;
return selectData;
})();
};
const selectGridModalOpen = async () => {
// 데이터가 로드될 때까지 대기
await selectDataPromise;
// 데이터가 로드되면 후속 작업 실행
if (selectData.length > 0) {
isSelectGridModalOpen = true;
} else {
console.log('데이터가 없습니다.');
}
};
위 예시에서는 opened 함수에서 데이터를 비동기적으로 받아오는 Promise를 생성하고, selectGridModalOpen 함수에서 await로 Promise가 완료될 때까지 기다린 후 데이터를 사용해 작업을 진행합니다.
🎯 기대 효과
- 비동기 처리 순차적 관리: Promise를 사용하면 비동기 작업을 순차적으로 기다리고 처리할 수 있어 코드의 흐름을 보다 직관적으로 만들 수 있습니다.
- 콜백 지옥 방지: async/await와 Promise를 활용하면 콜백 지옥을 피할 수 있어 가독성 높은 코드를 작성할 수 있습니다.
- 동기처럼 처리: 비동기 작업을 await와 함께 사용하면 동기 처리처럼 직관적으로 코드를 작성할 수 있습니다. 이를 통해 데이터 로딩 순서를 명확하게 제어할 수 있습니다.
- 에러 처리: Promise는 catch를 통해 에러를 처리할 수 있기 때문에, 비동기 작업 중 발생할 수 있는 오류를 손쉽게 다룰 수 있습니다.
- UI 응답성 유지: 데이터가 로딩될 때까지 기다리면서도 UI 응답성을 유지할 수 있어, 사용자는 데이터가 준비되었을 때 최적화된 경험을 하게 됩니다.
이처럼 Promise와 async/await을 적절히 사용하면 비동기 작업의 흐름을 명확하게 관리할 수 있으며, UI를 효과적으로 관리하고 비동기 데이터 로딩을 최적화할 수 있습니다.