밤빵's 개발일지
[TIL]20240916 결제 연동 흐름의 보완점 본문
포트원을 연동한 결제 시스템을 구현하면서, 흐름을 분석하고 몇 가지 보완해야 할 점을 알게됐다. 결제는 사용자가 직접적으로 자금과 관련된 매우 중요한 기능이고, 흐름의 안정성과 보안성, 그리고 사용자 측면에서 추가적인 보완이 필요하다. (결제 기능한다고 열심히 알아보던 동시성이슈나 락개념, 멱등성같은건 추가 할 엄두도 못내는 중...)
▶ 결제 실패에 대한 대응
현재 결제 성공에 대한 흐름은 잘 정의되어 있지만, 결제 실패 또는 예외 상황에 대한 처리가 조금 미흡하다. 결제 실패는 다양한 이유(카드 승인 거절, 네트워크 문제, 사용자 취소 등)로 발생할 수 있기때문에, 실패 시에도 명확한 처리와 사용자 안내가 필요하다.
▷ 개선 사항:
→ 결제 실패 처리 로직 강화:
결제 실패 시 어떤 조치를 취할 것인지 명확히 정의해야 한다. 예를 들어, 결제가 실패했을 때 사용자에게 명확한 메시지를 제공하고, 재시도 옵션을 제시하는 등 사용자 경험을 개선할 수 있다.
→ 로그 기록:
결제 실패나 오류가 발생한 경우에는 로그를 남겨야 한다. 이렇게 남겨진 로그는 이후 문제 분석과 해결에 큰 도움이 될 수 있다.
// 결제 실패 처리 예시
if (paymentFailed) {
log.error("결제 실패: " + paymentResult.getErrorMessage());
return new ResponseEntity<>("결제가 실패했습니다. 다시 시도해주세요.", HttpStatus.BAD_REQUEST);
}
▶결제 검증 강화
현재 흐름에서 백엔드가 클라이언트로부터 결제 완료 결과를 받아 포트원 서버에 결제 정보를 조회하고 검증하는 과정을 거친다. 하지만 클라이언트로부터 전송된 결제 완료 결과에 의존하는 구조는 보안적으로 위험할 수 있다. 클라이언트가 데이터를 조작하여 서버에 잘못된 결제 정보를 보낼 수 있기 때문이다.
▷개선 사항:
서버에서 직접 결제 완료 검증 요청: 클라이언트로부터 결제 완료 정보를 받는 것만으로는 충분하지 않다. 백엔드는 포트원 서버에 직접 결제 상태를 확인하여 검증하는 과정을 반드시 추가해야 한다.
// 포트원 서버에서 결제 정보 검증
IamportResponse<Payment> paymentResponse = iamportClient.paymentByImpUid(impUid);
if (paymentResponse == null || !paymentResponse.isPaid()) {
throw new IllegalArgumentException("결제 검증 실패: 결제가 완료되지 않았습니다.");
}
→ 이 과정에서 포트원 API로부터 응답받은 데이터가 실제로 결제가 성공적으로 완료되었는지 확인하고, 그 후에만 결제를 성공으로 처리해야 한다. 클라이언트 측 데이터를 신뢰하기보다는, 항상 포트원 API에서 검증된 데이터를 기반으로 결제 상태를 처리하는 것이 중요하다.
▶결제 상태 변경 시 알림 처리
결제 과정에서 네트워크 문제나 기타 예기치 않은 상황이 발생할 수 있다. 이런 경우 결제가 완료되지 않았거나, 반대로 결제가 중복 처리되는 문제가 발생할 수 있다. 이를 방지하기 위해, 포트원에서 제공하는 Webhook을 설정해 두면 백엔드가 결제 상태 변경을 실시간으로 감지할 수 있다.
▷개선 사항:
Webhook 설정: Webhook을 사용하면 포트원 서버가 결제 상태가 변경될 때마다 백엔드 서버에 알림을 보낸다. 중복 결제, 부분 결제 등의 상태를 실시간으로 처리할 수 있다.
@PostMapping("/payment/webhook")
public ResponseEntity<String> handlePaymentWebhook(@RequestBody PaymentResult paymentResult) {
// 결제 상태 업데이트 처리
if (paymentResult.isPaid()) {
// 결제 완료 처리
} else {
// 결제 실패 처리
}
return ResponseEntity.ok("Webhook processed successfully.");
}
→ Webhook을 통해 결제 상태를 실시간으로 업데이트할 수 있어서, 결제 흐름이 더 견고해지고, 사용자가 중복 결제와 같은 문제를 겪을 가능성을 줄일 수 있다.
▶토큰 발급 실패 처리
포트원 API와 통신할 때 토큰 발급 과정이 필수적이다. 하지만 네트워크 문제나 기타 서버 문제로 인해 토큰 발급이 실패할 수 있다. 현재 토큰 발급 실패 시의 예외 처리가 부족한 경우, 결제 과정이 중단되거나 사용자가 결제 실패에 대한 명확한 안내를 받지 못할 수 있다.
▷개선 사항:
토큰 발급 실패 시 재시도 로직 추가: 포트원 API 호출 시 토큰 발급이 실패할 경우, 이를 감지하여 일정 횟수 재시도하는 로직을 추가할 필요가 있다. 네트워크 지연이나 일시적인 오류일 수 있으므로, 일정 횟수까지는 재시도하고, 실패할 경우 사용자에게 오류 메시지를 제공해야 한다.
public String getPortOneToken() {
int retryCount = 0;
while (retryCount < MAX_RETRY) {
try {
// 토큰 발급 요청
return iamportClient.getToken();
} catch (Exception e) {
retryCount++;
log.warn("토큰 발급 실패, 재시도 횟수: " + retryCount);
}
}
throw new RuntimeException("토큰 발급 실패: 재시도 횟수를 초과했습니다.");
}
→ 이와 같은 로직을 통해 토큰 발급 과정에서 발생할 수 있는 오류에 보다 유연하게 대응할 수 있다.
▶결론
포트원 결제 연동을 통해 기본적인 결제 흐름을 구현하는 건 어찌저찌 진행되고있지만, 실제 서비스에서 안정적으로 동작하기 위해서는 위에서 제시한 보완점들이 반드시 필요할 것 같다. 결제 실패 처리, 서버에서의 결제 검증, Webhook 설정, 토큰 발급 실패 처리 등은 결제 기능의 신뢰성과 안정성을 높이기 위한 중요한 요소들이다.
'개발Article' 카테고리의 다른 글
[TIL]20240918 TCP? UDP? (0) | 2024.09.18 |
---|---|
[TIL]20240917 Singleton! (0) | 2024.09.18 |
[WIL]20240915 JSON직렬화/역직렬화 (0) | 2024.09.15 |
[TIL]20240914 Gradle과 Maven의 차이점 (0) | 2024.09.15 |
[TIL]20240913 내부DB & 그냥DB 그리고 동기화 (1) | 2024.09.14 |