우선 우리 프로젝트에서는 단순하게 MySQL의 Auto Increment로 주문 테이블의 PK를 관리하고, 이를 각 주문의 ID로 사용했다. 이 질문의 의도가 뭐였을까 잘 모르겠어서 주문 엔티티 설계와 관련해서 정보를 찾아봤다. 다른 곳은 주문 ID를 어떻게 관리하지?
PK로 Auto-Increment를 사용하는 방안과 UUID를 사용하는 방안이 있다고 한다.
이 정보를 참고했을 때는 내부적으로 AI를 사용하고, 외부적으로 UUID를 사용하는 방법이 권장되는 거 같다. 그러면 주문 테이블에 UUID를 저장해야하나? 아니면 PK 값으로 UUID를 찾아내는 어떤 함수를 사용해냐 하나?
추가로 우아한 기술블로그에서 확인한 것은 주문 엔티티의 PK인 ID와 더불어서 orderKey를 필드로 가지고 있었다. 이는 비즈니스적으로 활용하기 위해 사용하는 주문 key이다. 우리 프로젝트에서는 사실 가게의 주문 화면에서 주문 번호를 띄우지 않았고, 고객의 주문 내역에서 주문 번호를 띄우지도 않았다. 사실 실제 서비스라면 주문 번호를 가지고 가게에 가서 "저 ~~ 주문했는데요, 주문 번호는 00 이에요" 라고 말하며 주문 확인도 할 것이고, 가게에 전화해서 "00번 주문한 사람인데.." 라고 말하며 주문에 관한 추가 요청을 전달할 수도 있다. 근데 만약 주문 ID PK를 그대로 사용하면? 극단적으로 엄청 주문 데이터가 쌓였다고 가정했을 때 "저 1012312312312312번 주문한 사람인데요.......라고 할 수는 없다.", 이외에도 비즈니스적으로 주문 데이터를 관리하기 위해서 다양한 이유가 있을 수 있기에 주문 번호가 따로 필요함을 느꼈다. 위 참고 블로그에서는 주문ID + 주문일자로 orderkey를 생성해 주고 있었다. 내 생각에는 각 날짜의 주문을 카운트하면서 cntNum+orderDate로 주문 key를 관리하는 것도 괜찮아 보이고 여러 설계적인 측면을 고려해서 추가를 해야할 것 같다.
우선 결제 요청은 프론트에서 하는가 백에서 하는가? 우리 프로젝트에서는 프론트엔드에서 카카오페이 API를 호출해 결제를 하고 결제가 성공하면 백엔드로 주문 등록 API를 요청하도록 되어 있음.
실제 주문 로직 설계
주문의 상태를 거절/취소로 변경해야 한다. 그리고 관련 주문 데이터가 변경된 게 있으면(ex 재고) 모두 되돌려야 한다.
주문 등록 처리를 완료하고 결제 승인을 요청하는 과정에서 만약 가게가 주문을 거절해서 주문이 취소되면, 결제가 승인된 상태라면 정상적으로 결제 취소를 요청할 수 있지만 결제승인이 아직 진행중인 상태라면 정상 취소가 불가능하다.
카카오페이 REST API 문서를 보니 결제 취소가 불가능한 상태에 대한 응답 ErrorCode가 있다. 그리고 결제 취소 요청 API를 했을 때 응답으로 현재 결제 진행 상태도 들어온다. 이 정보를 조합해서 백엔드에서 적절하게 에러를 처리해야 할 것이다.
주문 등록 비즈니스 로직이 실패하면, 트랜잭션을 통해 조작한 주문 데이터를 모두 roll back 한 후에, 주문이 불가능한 이유에 대한 상태코드를 담아서 클라이언트로 전달해서 적절한 주문 불가능 사유를 띄울 수 있도록 해야 한다.