실전으로 비동기 코드를 작성할 수는 있지만, 누군가 내게 Promise가 뭔지 ,async/await는 뭔지 물어본다면
"어..그...비동기로 호출할때 쓰이는....."
나도 모르게 설명하다가 막혀버린다 😅
누군가에게 당당하게 설명을 해주기 위해, 자바스크립트에서의 비동기에 대해 정리해보고자 한다.
예제코드와 더 자세한 설명은 아래에서 참고해주세요.
⏱ 비동기작업과 콜백함수
비동기작업이란 동시에 코드를 실행하게 해주는 작업이라 생각하면 된다.
서버에서 데이터를 불러올 때 굉장히 오래걸릴 수도 있는데, 그동안 다른 코드를 실행하지 않고 기다린다면 매우 오래걸릴 것이다.
데이터를 불러오는 작업을 비동기로 처리한다면, 데이터를 불러오는 도중에 다른 코드를 실행하게 할 수 있다.
하지만,
이러한 비동기작업에서 순서대로 불러야할 코드가 있으면 어떻게 될까?
예를들어, A라는 비동기 작업으로 인해 나온 결과를 B작업에 활용하고 싶은데,
A작업이 비동기로 실행되다 보니 A와 B가 동시에 이루어질 수도 있다.
즉, A 작업이 끝나기도 전에 A의 연산 결과를 B작업에서 사용한다면 에러가 날 것이다.
이렇게 비동기작업을 순차적으로 실행하기 위해 콜백함수를 사용한다. 콜백함수는 특정 로직이 끝났을 때 원하는 코드를 실행하게 해준다.
하지만, 콜백에 콜백, 여러번 호출되면 우리는 콜백지옥에 빠질 수 있다.
step1(function (value1) {
step2(function (value2) {
step3(function (value3) {
step4(function (value4) {
step5(function (value5) {
step6(function (value6) {
// 으아아아아악!!!
});
});
});
});
});
});
✨ 콜백지옥의 구세주, Promise 등장 !
이러한 콜백지옥의 단점은, promise로 해결할 수 있다.
- Promise는 비동기 함수가 반환하는 객체 이다.
- Promise는 비동기함수의 결과를 담고 있다.
- Promise는 함수의 성공과 실패 상태를 알려준다.
Promise는 비동기함수의 결과의 세가지 상태를 가지고 있는데,
대기 Pending, 성공 Fulfilled, 실패 Rejected 이다.
Promise의 상태가 바뀌면, `.then()` `.catch()` 체인 함수를 사용해, 성공/실패 상태를 각각 처리할 수 있다.
예제를 보자.
function requestPayment(paymentData) {
// ...
return new Promise((resolve, reject) { // Pending 상태
if(isSuccess) {
resolve(data) // 성공 상태
}
else {
reject(error) // 실패 상태
}
})
}
paymentWidget.requestPayment({
orderId: "t9JI0Bs1SVdJxRs8yjiQJ",
orderName: "토스 티셔츠 외 2건",
})
.then(function (data) {
console.log(data);
// 성공 처리
})
.catch(function (error) {
// 에러 처리
if (error.code == "NEED_CARD_PAYMENT_DETAIL") {
console.log(error.message);
}
`.then()` 을 이용해, promise로 만든 비동기작업의 결과를 받아올 수 있다.
매번 콜백함수로 받아오던 작업이 `then()` 으로 교체된 것이다.
하지만, 이러한 Promise에도 콜백과 비슷한 문제가 일어날 수 있다.
.then() 체인이 길게 이어나가면 콜백체인과 마찬가지로 가독성이 떨어지게 된다.
😘 Promise 단점을 채워주는 async/await !
함수를 정의할 때 `async` 를 붙이면, 이 함수는 비동기적인 함수이고, Promise 객체를 반환해 라고 선언해주는 것과 같다.
만약, 반환하는 값이 Promise가 아니더라도, resolve 상태인 Promise로 값을 감싸 반환한다.
async function f() {
return 1;
}
f().then(alert); // 1
async function handleSubmit() {
...
return paymentData
// return Promise.resolve(paymentData) // 위와 같은 결과
}
await는 async함수에서만 사용할 수 있는 문법인데, Promise 를 반환하는 함수 앞에 await를 붙이면 해당 Promise 의 상태가 바뀔때 까지 코드가 기다린다.
즉, Promise가 성공 상태 또는 실패 상태로 바뀌기 전 까지는 다음 연산을 시작하지 않는다.
promise.then 보다는 조금 더 가독성이 좋게 promise의 result 값을 얻어올 수 있다.
async function handleSubmit() {
const paymentData = await paymentWidget.requestPayment({
orderId: "KOISABLdLiIzeM-VGU_8Z", // 주문 ID(직접 만들어주세요)
orderName: "토스 티셔츠 외 2건" // 주문명
});
console.log(paymentData);
return paymentData
}
'🌳Frontend > etc' 카테고리의 다른 글
Next.js의 Cypress에서 테스트코드 실행해보기 (feat. MSW) (1) | 2023.10.21 |
---|---|
Next.js환경에서 Cypress시작하기 (Cypress 설치/실행) (0) | 2023.10.21 |
CSR SSR SSG 당신의 선택은 무엇인가요? (0) | 2023.10.02 |
쿠키, 세션 (2) | 2023.09.10 |
[Web] Gzip 압축으로 사이트를 최적화해보자 (0) | 2023.09.06 |