Promise란?
promise는 비동기 함수가 반환하는 객체이다. 함수의 성공 또는 실패 상태를 알려준다. 콜백은 직접 호출하는 방법 대신, Promise로 콜백을 부를 수 있다. 이런 특징 때문에 Promise를 사용하면 비동기 처리 시점, 비동기 함수의 결과를 쉽게 확인할 수 있고 에러도 어디서 일어났는지 파악하기 편리하다.
Promise를 생성하는 방법
function requestPayment(paymentData) {
//...
return new Promise((resolve, reject) { //Pending 상태
if(isSuccess) {
resolve(data) // 성공 상태
} else {
reject(error) // 실패 상태
}
})
}
위와 같은 코드가 있다고 했을때 리턴 값으로 Promise를 생성하고 있다.
결제가 요청되기 전에는 Promise가 대기(Pending) 상태이고, 결제 요청에 성공하면, Promise 생성 함수에 있는 resolve() 메서드가 호출된다. Promise가 성공 상태로 바뀌고 data 값을 가지게 된다. 성공 상태를 가진 Promise는 fullfilled된 상태라고 말한다. 하지만 결제 요청에 문제가 있다면 reject()를 호출하여 Promise 상태를 실패로 바꾸고 error 데이터를 가지게 된다. 실패 상태를 가진 Promise는 rejected된 상태라고 말한다.
Promise는 세 개의 상태를 가질 수 있다.
- 대기(Pending) : 비동기 함수가 아직 시작하지 않은 상태
- 성공(Fulfilled) : 비동기 함수가 성공적으로 완료된 상태
- 실패(Rejected) : 비동기 함수가 실패한 상태
그렇다면 이렇게 생성된 Promise를 처리하려면 어떻게 해야할까?
Promise를 처리할 때는 then() 또는 catch() 메서드를 사용할 수 있다. 각 메서드 파라미터에는 콜백 함수를 넣는데, 결제 요청에 성공 상태의 Promise가 반환되면 then() 메서드가 호출되고, 반대로 실패 상태의 Promise가 반환되면 then() 메서드를 건너뛰고 catch() 메서드가 호출된다.
하지만 이러한 Promise에도 단점이 존재한다. then() 체인을 길게 이어 나가면 콜백 체인과 마찬가지로 코드의 가독성이 떨어지고 에러가 어디서 발생했는지 파악하기 어렵다.
그래서 async/await을 사용한다.
aync/await이란?
콜백과 Promise 체인의 단점을 async와 await을 사용하여 보완할 수 있다.
async function handleSubmit() {
return paymentData
// return Promise.resolve(paymentData) // 위의 예제와 같은 결과
}
위처럼 함수를 정의할때 async 를 함수 앞에 붙이면, "이 함수는 비동기적인 함수이고 Promise를 반환한다"라고 선언하는 것이다.
반환 값이 Promise 생성 함수가 아니어도 반환되는 값을 Promise 객체에 넣는 것이다.
await는 async 함수 안에만 사용할 수 있는 특별한 문법인데, Promise 를 반환하는 함수 앞에 await를 붙이면, 해당 Promise의 상태가 바뀔 때까지 코드가 기다린다. Promise가 성공 상태 또는 실패 상태로 바뀌기 전까지는 다음 연산을 시작하지 않는 것이다.
async function requestPayment(paymentData) {
//...
const paymentData = await payment.requestPayment({});
console.log(paymentData);
return paymentData
}
위의 예시를 보면 requestPayment() 메서드 앞에 await 이 붙어 있는 것을 알 수 있다. 결제 요청이 완료되어 Promise객체의 상태가 바뀐 이후에만 console.log(paymentData) 가 실행된다. 비동기 작업을 동기로 바꾸는 것이다.
사실상 await은 then()과 같은 역할을 하는데, 콜백 함수를 등록할 필요가 없기 때문에 더 편리하다. 또 체이닝으로 인해 코드가 복잡해질 필요도 없다.
그렇다면 에러 처리는 어떻게 할까? async/await 로 코드를 동기적으로 바꾸는 것으로 생각할 수 있다고 했는데, try/catch를 사용하면 된다.
async function handleSubmit() {
try {
const paymentData = await paymentWidget.requestPayment({
orderId: "EKRUWOIIWO10-2931", // 주문 ID(직접 만들어주세요)
orderName: "t-shirt" // 주문명
});
console.log(paymentData);
// 성공 처리
return paymentData;
} catch (error) {
// 에러 처리
console.log(error.message);
}
}
위 코드에서 requestPayment() 메서드를 실패하여 실패 상태의 Promise객체를 반환하면, 바로 catch 블록을 실행한다.
'Front-End > React&Next.js' 카테고리의 다른 글
| React 기본 (0) | 2024.03.14 |
|---|