FE develop/Javascript
자바스크립트 비동기 이해하기 - (3.2) Promise를 더 알아보자
hoj0806
2025. 4. 18. 12:14
2025.04.16 - [FE develop/Javascript] - 자바스크립트 비동기 이해하기 - (3.1) Promise란?
지난 포스트에 이어 이번 글에서는 Promise에 대해 더 깊이 알아보겠습니다.
특히 Promise Chaining과 Fetch API, 그리고 이를 활용한 간단한 실전 예제도 함께 다뤄보겠습니다.
🔗 Promise Chaining이란?
Promise 객체의 .then() 메서드는 새로운 Promise를 반환합니다.
따라서 .then()을 계속 연결해 체인처럼 이어지는 구조로 만들 수 있는데, 이를 Promise Chaining이라고 합니다.
이 기법을 활용하면, 비동기 작업을 순차적으로 실행할 수 있고, 콜백 지옥(Callback Hell)을 피할 수 있어 코드가 훨씬 깔끔해집니다.
예를 들어 다음과 같은 코드가 있습니다
function getData() {
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
const data = { name: '철수' }
if (data) {
console.log("네트워크 요청 성공")
resolve(data)
} else {
reject(new Error("네트워크 문제가 발생했습니다"))
}
}, 1000)
})
return promise
}
getData()
.then(() => getData()) // 첫 번째 작업이 완료된 후 두 번째 작업 실행
.then((data) => {
console.log(data)
})
또한 .then() 안에서 값을 리턴하면, 그 값은 자동으로 Promise.resolve()로 감싸진 상태로 다음 .then()으로 전달됩니다
function getData() {
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
const data = { name: '철수' }
if (data) {
console.log("네트워크 요청 성공")
resolve(data)
} else {
reject(new Error("네트워크 문제가 발생했습니다"))
}
}, 1000)
})
return promise
}
getData()
.then(() => getData()) // 첫 번째 작업이 완료된 후 두 번째 작업 실행
.then((data) => {
console.log(data)
})
🌐 Fetch API 사용법
fetch() 함수는 자바스크립트에서 데이터를 받아올 때 사용하는 API로, Promise를 반환합니다.
다음은 기본적인 사용 예제입니다
fetch("https://jsonplaceholder.typicode.com/users")
.then((response) => {
return response.json() // 응답을 JSON 형식으로 변환
})
.then((data) => {
console.log(data) // 실제 데이터 출력
})
.catch((error) => {
console.error(error) // 에러 처리
})
.finally(() => {
console.log('마무리 작업') // 성공, 실패와 관계없이 항상 실행
})
- fetch()는 네트워크 요청을 보낸 후 Response 객체를 반환합니다.
- response.json()은 비동기적으로 JSON 파싱을 수행하며, 이 역시 Promise를 반환합니다.
💡 실전 예제: 로그인 → 장바구니 → 결제
실제 사용 시나리오처럼 여러 비동기 작업을 순차적으로 처리하는 예제를 만들어보겠습니다.
// 1. 로그인
function login(username) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if(username) {
resolve(username)
} else {
reject(new Error("아이디를 입력해주세요"))
}
}, 1000);
})
}
// 프로미스를 이런식으로 사용가능
// login.then((data) =>).catch((error))
// 2. 장바구니에 상품 추가
function addToCart(product) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if(product) {
resolve(product)
} else {
reject(new Error("상품을 넣어주세요"))
}
}, 1000);
})
}
// 3. 결제
function makePayment(cardNumber, product) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if(cardNumber.length !== 16) {
reject(new Error("잘못된 카드 번호입니다"))
}
resolve(product)
}, 1000);
})
}
📦 Promise Chaining을 활용한 흐름 처리
login('홍길동')
.then((username) => {
console.log(`${username}님 환영합니다`)
return addToCart('감자')
})
.then((product) => {
console.log(`${product}를 장바구니에 넣었습니다`)
return makePayment('1231231231231231', product)
})
.then((product) => {
console.log(`${product}를 구매했습니다`)
})
.catch((error) => {
console.error("에러 발생:", error.message)
})
.finally(() => {
console.log("모든 프로세스가 완료되었습니다")
})
이처럼 Promise Chaining을 이용하면 비동기 로직을 순차적으로 깔끔하게 처리할 수 있습니다.
에러 처리도 중간에 .catch() 하나만 두면, 어디서 문제가 발생하든 한 번에 처리할 수 있어 더욱 효율적입니다.