분류 전체보기 23

결제 로직에서 발생하는 예외 처리하기(feat.트랜젝션 의존 줄이기)

현재 진행중인 사이드 프로젝트 내에서 아이템을 구매할 때에는 서비스 재화인 포인트가 사용됩니다. 포인트는 게임 캐시처럼 직접 현금 결제하여 충전할 수 있습니다.현금 결제를 위해 Portone이라는 솔루션을 이용하여 처리하고 있습니다.이번 포스팅은 기존에 작성되었던 결제 로직을 리팩토링 하면서 고민했었던 내용입니다.결제 플로우충전 할 금액을 선택 하면 PortOne 모듈을 통해 위와 같은 결제 창이 뜨게 됩니다.사용자가 결제를 마무리하면 PortOne에서는 Webhook을 통해 사전에 지정한 서버 주소로 처리 된 PaymentId, Status 등 정보를전송해줍니다. Webhook을 수신 한 애플리케이션 서버는 결제 검증, 처리 후 포인트 충전 로직을 수행합니다.PG 모듈을 이용하여 결제 완료WebHook..

spring 2024.12.06

리뷰 기능 평점 통계 개선기

진행중인 프로젝트에는 특정 아이템에 대한 리뷰와 평점을 남기는 기능이 있습니다.평점의 평균을 구하기 위해서 API 요청마다 DB의 Sum, Count와 같은 집계함수를 이용하여 처리하였습니다.그러다 우연히 다른 기능의 테스트를 하다가 리뷰 테이블에 1000만건 정도의 더미 데이터를 넣게되었는데요.리뷰 조회 API에서 성능적으로 부하가 발생함을 발견하였고 개선하기 위해 시도했던 것들을 포스팅하게 되었습니다. 리뷰 시스템의 테이블 구조는 위 사진과 같습니다.select count(qr.id), sum(qr.rate), qr.question_id from question_review qr where qr.question_id = 1 특정 상품 리뷰의 평균 평점을 조회 할 때는 위와 같이 count, sum ..

spring 2024.12.06

알고 쓰자 - ContentCachingRequestWrapper

ServletInputStream은 1회용Spring boot 환경에서 Request, Response Logging을 하기 위해 Google 검색을 한다면 대부분의 글에서InputStream은 1번만 읽을 수 있으니 이미 캐싱 기능이 만들어져있는 ContentCachingRequestWrapper를 사용하거나 HttpServletRequestWrapper를 상속해서 직접 캐싱 기능을 구현하는 방법이 나옵니다.처음에 Logging을 구현할 때는 HttpServletRequestWrapper를 상속해서 구현했었는데 좀 찾아보니 ContentCachingRequestWrapper를 사용해도 충분할 것 같다는 생각이 들었기에 ContentCachingRequestWrapper를적용하는 과정을 남기게 되었습니다..

spring 2024.12.06