반응형
JavaScript의 비동기 처리에서 핵심적인 역할을 하는 Promise에 대해 자세히 알아보겠습니다. 이 글에서는 Promise의 개념, 상태, 사용법, 그리고 한계점까지 포괄적으로 다룹니다.
Promise란?
Promise는 JavaScript에서 비동기 작업을 관리하고, 해당 작업의 성공 또는 실패 결과를 나중에 사용할 수 있도록 하는 객체입니다. 쉽게 말해, Promise는 비동기 작업의 완료 여부를 "약속"해주는 개념이라고 할 수 있습니다.
Promise의 등장 배경
기존의 콜백 기반 비동기 처리 방식은 다음과 같은 문제점이 있었습니다:
// 콜백 지옥 예시
fetchData(function(data) {
processData(data, function(processedData) {
saveData(processedData, function(savedData) {
displayData(savedData, function() {
// 더 깊은 콜백 중첩...
});
});
});
});
이러한 "콜백 지옥" 문제를 해결하기 위해 Promise가 도입되었습니다.
Promise의 상태
Promise는 다음 세 가지 상태를 가집니다:
- Pending (대기)
- 비동기 작업이 아직 완료되지 않은 초기 상태
- Promise가 생성된 직후의 상태
- Fulfilled (이행)
- 비동기 작업이 성공적으로 완료된 상태
resolve()
가 호출되어 결과값이 전달된 상태
- Rejected (거부)
- 비동기 작업이 실패한 상태
reject()
가 호출되어 오류가 전달된 상태
const promise = new Promise((resolve, reject) => {
// 비동기 작업 수행
if (/* 성공 */) {
resolve(value); // Fulfilled 상태로 전환
} else {
reject(error); // Rejected 상태로 전환
}
});
Promise 사용법
1. 기본 사용법
const fetchUserData = () => {
return new Promise((resolve, reject) => {
// 비동기 작업 (예: API 호출)
fetch('https://api.example.com/user')
.then(response => response.json())
.then(data => resolve(data))
.catch(error => reject(error));
});
};
// 사용
fetchUserData()
.then(userData => console.log(userData))
.catch(error => console.error(error));
2. Promise 체이닝
fetchUserData()
.then(userData => processUserData(userData))
.then(processedData => saveUserData(processedData))
.then(savedData => displayUserData(savedData))
.catch(error => handleError(error));
3. Promise.all() - 병렬 처리
const fetchMultipleData = async () => {
try {
const [users, posts, comments] = await Promise.all([
fetchUsers(),
fetchPosts(),
fetchComments()
]);
// 모든 데이터가 준비된 후 처리
} catch (error) {
// 하나라도 실패하면 에러 처리
}
};
Promise의 한계점
1. 복잡한 에러 처리
fetchUserData()
.then(userData => {
// 특정 단계에서만 발생하는 에러 처리
if (!userData.isValid) {
throw new Error('Invalid user data');
}
return processUserData(userData);
})
.catch(error => {
// 모든 에러가 여기로 모임
// 어떤 단계에서 발생한 에러인지 구분이 어려움
});
2. 여전히 존재하는 가독성 문제
// Promise 체이닝이 길어질 경우
fetchUserData()
.then(userData => {
return processUserData(userData)
.then(processedData => {
return saveUserData(processedData)
.then(savedData => {
return displayUserData(savedData);
});
});
})
.catch(error => handleError(error));
이러한 문제는 async/await을 통해 개선할 수 있습니다:
// async/await을 사용한 개선된 버전
async function handleUserData() {
try {
const userData = await fetchUserData();
const processedData = await processUserData(userData);
const savedData = await saveUserData(processedData);
await displayUserData(savedData);
} catch (error) {
handleError(error);
}
}
결론
Promise는 JavaScript의 비동기 처리 방식을 크게 개선했지만, 여전히 몇 가지 한계점이 있습니다. 이러한 한계는 async/await과 같은 최신 문법을 통해 보완할 수 있습니다. 실제 프로젝트에서는 상황에 따라 Promise와 async/await을 적절히 조합하여 사용하는 것이 좋습니다.
참고 자료
반응형
'Frontend Development' 카테고리의 다른 글
Conventional Commits: 협업을 위한 커밋 메시지 표준화 전략 (6) | 2025.05.27 |
---|---|
DOM 이벤트 전파(Event Propagation) 완벽 가이드 (0) | 2025.05.27 |
React useEffect 훅 완벽 가이드: 호출 시점과 사용법 (0) | 2025.05.27 |
CSS Flexbox vs Grid: 현대 웹 레이아웃의 두 가지 접근 방식 (0) | 2025.05.27 |
JavaScript의 undefined와 null: 그 차이점과 사용법 (0) | 2025.05.27 |