1. 문제 상황


"코드가 실행되다가 서버가 죽거나 행(Hang)이 걸려서, PG사에서 돈은 나갔는데 내 DB는 그대로라면?"

  1. prepareOrderForPayment: DB 상태를 IN_PROGRESS로 변경.

    	public Payment executePayment(String paymentKey, Long orderNo, BigDecimal amount, Long productNo, Integer count) {
    		orderService.prepareOrderForPayment(orderNo, amount); // pending -> payment_in_progress 
    
    		PaymentResult paymentResult; 
    		try {
    			paymentResult = paymentClient.approve(paymentKey, orderNo, amount); // PG 사 통신을 통해 결제 : 여기서 개오래걸려서 밑에 실행 안되면?
    		} catch (Exception e) {
    			orderService.rollbackToPending(orderNo); // payment_in_progress -> pending : 이거 실패하면?
    			throw e;
    		}
    
    		switch (paymentResult.status()) {
    			case "DONE" -> {
    				return paymentService.completePayment(orderNo, paymentResult); // payment_in_progress -> paid / payment 저장
    			}
    			case "ABORTED" -> {
    				paymentService.registerFailedPayment(orderNo, paymentResult); // 실패한 결제 이력 payment 저장
    				orderService.rollbackToPending(orderNo); // payment_in_progress -> pending
    				throw PaymentFailedException.aborted(paymentKey, orderNo, paymentResult.failureMessage());
    			}
    			case "EXPIRED" -> {
    				paymentService.registerFailedPayment(orderNo, paymentResult); // 실패한 결제 이력 payment 저장
    				purchaseFacade.cancel(orderNo, productNo, count); // payment_in_progress -> canceled / stock 복구
    				throw PaymentFailedException.expired(paymentKey, orderNo, paymentResult.failureMessage());
    			}
    			default -> throw PaymentFailedException.invalid(paymentKey, orderNo, paymentResult.status());
    		}
    	}
    
  2. paymentClient.approve: PG사에 요청을 보냄. (성공 → 고객 돈 출금)

  3. — 여기서 서버 터짐 / CPU 100%로 스레드 멈춤 —

  4. completePayment: 이 코드는 영원히 실행되지 않음.

  5. catch 블록: 당연히 실행되지 않음.

2. 해결 방법: 믿지 말고 확인


2.1 Read Timeout 설정


paymentClient.approve()에서 무한정 대기하는 것을 막기 위해 Timeout 설정을 걸어주자.

→ 하지만 이것은 지연을 막을 뿐, 서버가 죽는 것은 못 막는다.

2.2 결제 전 확인