본문 바로가기

코드개선, 성능개선

비동기 결제 처리 고민

아임포트를 이용해 결제를 구현

 

클라이언트단

async function requestCardPay() {
    const isAuthenticated = checkCookieExistence('Authorization');
    const orderContainer = document.querySelector('.order_container');
    const orderId = orderContainer.getAttribute('data-order-id');
    
    if (isAuthenticated) {
        const quantity = parseInt(document.getElementById("orderQuantity").textContent);
        const totalPrice = parseInt(productPrice) * quantity;
        const merchant_uid = generateMerchantUid();
        const card_number = document.getElementById("cardNumber").value;
        const expiry = document.getElementById("cardExpiry").value;
        const pwd_2digit = document.getElementById("cardPassword").value;
        const birth = document.getElementById("userBirth").value;
        const customer_uid = card_number + expiry;
        const pg = "nice.iamport01m";

        const requestBody = JSON.stringify({
            pg :pg,
            merchant_uid:merchant_uid,
            amount: totalPrice,
            card_number: card_number,
            expiry: expiry,
            birth: birth,
            pwd_2digit: pwd_2digit,
            customer_uid: customer_uid,
            buyer_email: buyerEmail,
            buyer_name: buyerName,
            buyer_tel: buyerTel,
            buyer_addr: buyerAddr,
            buyer_postcode: buyerPostcode
        });

        const response = await fetch("/subscribe/payments/onetime", {
            method: "POST",
            headers: {
                "Content-Type": "application/json"
            },
            body: requestBody
        });

        if (!response.ok) {
            const errorMessage = await response.text();
            throw new Error(`Failed to issue billing key: ${errorMessage}`);
        }

        const responseData = await response.json();
        alert("빌링키 발급 성공");

        if (responseData.code === 0) {
            $.ajax({
                type: 'PUT',
                url: `/api/orders/${orderId}/paymentStatus`
            })
            alert("결제 요청이 완료되었습니다.");
            window.location.href="/my-page";
        } else {
            alert("결제 실패: " + requestBody);
        }

    } else {
        alert('로그인 후에 결제할 수 있습니다.');
        window.location.href = '/api/user/login-page';
    }
}

 

서버단

 

    @PostMapping("/subscribe/payments/onetime")
    public ResponseEntity<CompletableFuture<IamportResponse<Payment>>> paymentOnetime(@RequestBody PaymentOnetimeDto paymentOnetimeDto)
            throws IamportResponseException, IOException {
        CompletableFuture<IamportResponse<Payment>> response = paymentService.getPaymentOnetime(paymentOnetimeDto);
        return ResponseEntity.ok(response);
    }
    @Async
    public CompletableFuture<IamportResponse<Payment>> getPaymentOnetime(PaymentOnetimeDto paymentOnetimeDto) throws IOException, IamportResponseException {
        log.info("비동기 시작~", LocalDateTime.now());
        String merchant_uid = paymentOnetimeDto.getMerchant_uid();
        BigDecimal amount = paymentOnetimeDto.getAmount();
        String cardNumber = paymentOnetimeDto.getCard_number();
        String expiry = paymentOnetimeDto.getExpiry();
        String birth = paymentOnetimeDto.getBirth();
        String pwd2Digit = paymentOnetimeDto.getPwd_2digit();
        CardInfo card =new CardInfo(cardNumber,expiry,birth,pwd2Digit);

        OnetimePaymentData data = new OnetimePaymentData(merchant_uid,amount, card);
        data.setCustomer_uid(paymentOnetimeDto.getCustomer_uid());
        data.setPg(paymentOnetimeDto.getPg());
        data.setBuyerName(paymentOnetimeDto.getBuyer_name());
        data.setBuyerEmail(paymentOnetimeDto.getBuyer_email());
        data.setBuyerTel(paymentOnetimeDto.getBuyer_tel());
        data.setBuyerAddr(paymentOnetimeDto.getBuyer_addr());
        data.setBuyerPostcode(paymentOnetimeDto.getBuyer_postcode());

        IamportResponse<Payment> payment = iamportClient.onetimePayment(data);
        log.info("비동기 끝~",  LocalDateTime.now());
        return CompletableFuture.completedFuture(payment);
    }

 

    @PutMapping("/api/orders/{orderId}/paymentStatus")
    public ResponseEntity<OrderResponseDto> updatePayment(@PathVariable Long orderId) {
        OrderResponseDto orderResponseDto = paymentService.updatePaymentStatus(orderId);
        return ResponseEntity.ok(orderResponseDto);
    }

 

    @Transactional
    public OrderResponseDto updatePaymentStatus(Long orderId) {
        log.info("오더 상태 변경", LocalDateTime.now());
        Orders order = orderService.findOrderById(orderId);
        order.update();
        return new OrderResponseDto(order);
    }

 

결제 서비스인 getPaymentOnetime에 @Async만을 붙여서 비동기를 구현??

getPaymentOnetime가 비동기로 처리 되는건 확인했는데 결제 로직만을 비동기로 처리하는거에  대한 이점이 있나??

 

생각해보면 만약 결제에 여러 도메인이 붙었다고 생각했을때,(결제 시 이벤트 참가, 사용한 쿠폰 삭제, 포인트 삭감 등) -> 결제가 성공해야 저 로직들이 실행되어야 된다고 생각,

if (responseData.code === 0) {
            $.ajax({
                type: 'PUT',
                url: `/api/orders/${orderId}/paymentStatus`
            })
            alert("결제 요청이 완료되었습니다.");
            window.location.href="/my-page";
        } else {
            alert("결제 실패: " + requestBody);
        }

 근데 위의 코드와 같이 지금의 구조 상, 결국 동기적인 흐름이라고 생각이 됨(결제 성공을 리턴 받아야 오더의 상태를 결제 완료로 변경)

 

1. 결제하는 로직 자체만 비동기로 처리해도 되는가?

2. 결제 이후 이루어져야 하는 로직 자체도 비동기로 처리를 해야하는가?(근데 결국 결제가 성공 리턴을 받아야 처리를 해야하는데 비동기로 묶을수가 있는가?

'코드개선, 성능개선' 카테고리의 다른 글

비동기 결제 수정  (0) 2024.03.08
N+1 없애보기  (0) 2024.02.28
검색 성능 개선 - 2  (0) 2024.01.20
검색 성능개선 - 1  (0) 2024.01.20