일반적인 쇼핑몰의 주문 및 결제 프로세스는 어떻게 이뤄지나요?
일반적인 쇼핑몰의 주문 및 결제 프로세스에 대해 질문이 있습니다.
아래와 같이 주문, 주문상품, 상품 테이블이 있습니다. (최대한 간략화)
대략적으로 주문 및 결제 프로세스를 그려보면.. (제 개인적인 생각입니다.)
1. 고객이 상품을 선택하고 주문을 합니다.
2. 그리고 결제수단을 선택하고 "결제하기" 버튼을 클릭합니다.
3. 버튼 클릭 후 결제모듈을 호출하기 직전에 서버를 호출하여 주문정보를 주문테이블에 저장(최초 주문상태는 "미결제")하고 생성된 주문번호를 클라이언트에게 반환해줍니다.
4-1. 결제모듈이 호출된 후 잔액부족, 카드정지 등의 사유로 인해 정상적으로 승인이 떨어지지 않고 결제실패가 된 경우 클라이언트에게 실패에 관한 응답값이 반환되고(콜백함수로) 콜백함수에서 반환받은 응답값을 처리합니다. (서버를 호출하여 주문상태 값을 "결제실패"로 변경)
4-2. 결제모듈이 호출되고 PG사로부터 정상적으로 결제 승인이 떨어진 후 클라이언트에게 정상 응답값이 반환되고(콜백함수로) 콜백함수에서 반환받은 응답값을 가지고 서버를 호출합니다.
5. 서버에서 주문 테이블의 주문상태값을 "결제완료"로 업데이트 합니다.
위와 같은 흐름일 것 같습니다.
질문은 다음과 같습니다.
질문1. 위 절차 중 3번에서 주문 테이블에 데이터를 넣고 주문상품에도 데이터를 넣어야 될까요? (주문상품 테이블에 데이터를 넣고 주문번호까지 넣음)
만약 고객이 "결제하기" 버튼을 클릭하고 결제모듈이 호출된 상태에서 결제창을 꺼버리거나 브라우저를 종료해버리면 주문 테이블에는 "미결제" 또는 "결제실패"의 데이터가 쌓이게 될텐데 이시점에 각각의 주문 데이터에 주문상품의 데이터가 맵핑이 되어있는게 맞나요? 아니면 주문상품에 데이터는 정상적으로 결제완료가 된 후에 인서트하는게 맞을까요??
질문2. 위 절차 중 3번에서 주문 테이블과 주문상품 테이블에 모두 데이터를 넣는게 맞다고 하면 사용자가 결제모듈을 호출하고 꺼버리고 반복된 행동을 할 경우 주문상품 테이블에 중복된 데이터가 계속 쌓일텐데 그래도 별 문제가 없을까요?
질문3. 위 절차 중 3번에서 주문 테이블엔 인서트하고 주문상품 테이블에 인서트를 하지 않는다면 정상적으로 "결제완료"가 된 후에만 주문상품 테이블에 데이터를 넣고 주문번호를 넣어주면 될까요?
현업에서 주문과 결제 프로세스를 경험해보지 못해서 궁금한 점이 많네요.
혹시나 제가 생각한 절차가 이상하다거나 잘못된 부분이 있을경우 말씀해주시면 감사하겠습니다.
많은 조언 부탁드립니다.
감사합니다.
안녕하세요. 쇼핑몰을 직접 운영하고 있는 개발자 입니다.
제 분야라 도움되는 답변을 드릴 수 있을 것 같습니다.
질문1. 위 절차 중 3번에서 주문 테이블에 데이터를 넣고 주문상품에도 데이터를 넣어야 될까요?
=> 주문서에도 데이터를 넣고 주문상품에도 데이터를 넣는게 맞습니다. 결제완료 처리 부분은 최대한 심플할수록 좋습니다.
결제요청 버튼을 클릭할 때, 주문정보, 주문상품의 정보는 넣을 수 있는 정보는 모두 넣어서 row를 insert하시면 됩니다.
질문2. 위 절차 중 3번에서 주문 테이블과 주문상품 테이블에 모두 데이터를 넣는게 맞다고 하면 사용자가 결제모듈을 호출하고 꺼버리고 반복된 행동을 할 경우 주문상품 테이블에 중복된 데이터가 계속 쌓일텐데 그래도 별 문제가 없을까요?
=> 저 또한 결제 프로세스를 만들 때, 이부분이 고민되었지만 걱정하지 않으셔도 됩니다. 문제 없습니다. 나중에 테이블 row가 많아지면, 미결제 이면서 생성시간이 30분 이상 지난 것들은 삭제하는 함수를 만들어서 crontab으로 30분마다 돌려주셔 됩니다. 결론은 테이블 row가 많아지는 것은 큰 문제가 되지 않습니다.
질문3. 위 절차 중 3번에서 주문 테이블엔 인서트하고 주문상품 테이블에 인서트를 하지 않는다면 정상적으로 "결제완료"가 된 후에만 주문상품 테이블에 데이터를 넣고 주문번호를 넣어주면 될까요?
=> 1번 질문에서 말씀드렸듯이 주문상품 테이블에 인서트는 해주시면 되고 결제완료가 되었을 때는
- 결제여부(N->Y 또는 0 -> 1),
- 결제금액(결제요청과 구분하시는게 좋아요),
- 결제시간(서버 now함수 말고 콜백에서 넘어오는 시간이 있으면 그걸 쓰시는게 좋아요)
대표적으로 이 3가지만 업데이트 되면 모든 프로세스가 마무리 되도록 해주시는게 좋습니다.
위 테이블구조에 조금만 첨언을 드리자면,
"주문" 테이블에는 요청결제금액, 실제결제금액 두 컬럼을 구분해서 쓰시길 권장드립니다. (나중에 어뷰징 발생 시, 분석 가능)
"주문상품" 테이블에서는 상품1개분의 결제금액 컬럼을 추가하시길 권해드립니다. (부분 환불요청 시, 계산 용이)
결제완료 이후 업데이트 되는 프로세스를 간소화 하는 이유는 나중에 이벤트 등을 진행하셔서 서버에 과부하가 걸렸을 때,
결제완료 단계에서 주문서를 생성하는 프로세스를 두시면, 딜레이가 생기면서 주문서 누락이 발생할 수도 있습니다. 저 역시 초반에 주문서를 결제완료 이후에 생성했으나, 잦은 딜레이와 시간 차이로 인해 심플하게 전부 변경하였습니다.
도움이 되셨길 바랍니다.
감사합니다.
안녕하세요 모든 회사마다 다 다르지만 정규적으로는 아래와 같이 진행합니다.
----
질문1. 위 절차 중 3번에서 주문 테이블에 데이터를 넣고 주문상품에도 데이터를 넣어야 될까요? (주문상품 테이블에 데이터를 넣고 주문번호까지 넣음)
만약 고객이 "결제하기" 버튼을 클릭하고 결제모듈이 호출된 상태에서 결제창을 꺼버리거나 브라우저를 종료해버리면 주문 테이블에는 "미결제" 또는 "결제실패"의 데이터가 쌓이게 될텐데 이시점에 각각의 주문 데이터에 주문상품의 데이터가 맵핑이 되어있는게 맞나요? 아니면 주문상품에 데이터는 정상적으로 결제완료가 된 후에 인서트하는게 맞을까요??
----
>> 주문 테이블에 데이터를 넣는 순간 주문상품에도 데이터를 넣습니다.
애초에 주문상품 테이블에 FK 를 주문 테이블에 주문번호로 잡으셨기때문에 DB 무결성만 생각하셔도 FK 물려있는 주문상품 테이블에 인서트 하시는게 더 좋습니다.
거기다가 주문 테이블은 총 결제금액이고 주문상품 테이블이 다중 주문에 대한 주문 등을 저장하시는거기때문에 비록 결제가 실패하거나 취소되더라도 디테일 항목을 가지고 계시는게 좋습니다. ( 추후 결제 중간취소, 실패 된 상품명 집계 등 다양한 용도로도 활용 가능 )
----
질문2. 위 절차 중 3번에서 주문 테이블과 주문상품 테이블에 모두 데이터를 넣는게 맞다고 하면 사용자가 결제모듈을 호출하고 꺼버리고 반복된 행동을 할 경우 주문상품 테이블에 중복된 데이터가 계속 쌓일텐데 그래도 별 문제가 없을까요?
----
>> "결제" 와 관련된 테이블을 별도로 하나 더 생성하는게 보통입니다.
보통 더 복잡하게 들어가는 경우 "결제 모듈과 통신 내역을 저장하는 테이블" / "최종 결제 승인된 정보를 저장된 테이블" 등으로 또 이원화 하기도 합니다.
결제모듈을 태울때마다 Log 성으로라도 만들어두시는게 더 좋습니다.
보여주신 ERD 처럼 보자면 보통 아래와 같습니다.
결제 테이블
PK 결제테이블 고유번호
FK 주문번호
결제 모듈 타입( 모듈이 여러개인 경우)
결제 시도일시
결제모듈 응답일시
결제모듈 응답결과 전문
결제모듈 응답결과 전문에서 발라낸 성공/실패 여부
최종 결제값
----
질문3. 위 절차 중 3번에서 주문 테이블엔 인서트하고 주문상품 테이블에 인서트를 하지 않는다면 정상적으로 "결제완료"가 된 후에만 주문상품 테이블에 데이터를 넣고 주문번호를 넣어주면 될까요?
----
질문 1번과 좀 겹치는 답변인것 같습니다.
결제 되기 전에 이미 주문은 모두 생성해두고.
결제 관련 내역은 따로 별도의 테이블에 쌓으시는게 좋아보입니다.
추가적인 질문 있으시면 언제든지 더 질문 부탁드립니다^^
안녕하세요.
질문 주신 내용은 상품의 재고 관리를 어떻게 할지에 따라서 달라질수 있을것 같습니다. 우선 별도의 재고관리를 하지 않는다고 가정하면,
질문1. 위 절차 중 3번에서 주문 테이블에 데이터를 넣고 주문상품에도 데이터를 넣어야 될까요? (주문상품 테이블에 데이터를 넣고 주문번호까지 넣음)
만약 고객이 "결제하기" 버튼을 클릭하고 결제모듈이 호출된 상태에서 결제창을 꺼버리거나 브라우저를 종료해버리면 주문 테이블에는 "미결제" 또는 "결제실패"의 데이터가 쌓이게 될텐데 이시점에 각각의 주문 데이터에 주문상품의 데이터가 맵핑이 되어있는게 맞나요? 아니면 주문상품에 데이터는 정상적으로 결제완료가 된 후에 인서트하는게 맞을까요??
주문 상품기준으로 발주가 나간다면, 결제완료후에 인서트하시는 것이 좋을거 같습니다.
질문2. 위 절차 중 3번에서 주문 테이블과 주문상품 테이블에 모두 데이터를 넣는게 맞다고 하면 사용자가 결제모듈을 호출하고 꺼버리고 반복된 행동을 할 경우 주문상품 테이블에 중복된 데이터가 계속 쌓일텐데 그래도 별 문제가 없을까요?
나중에 주기적으로 해당 데이터는 지워주는 배치 작업을 하시면 될 거 같습니다. 사실 결제모듈을 호출하고 꺼버리는 반복적인 행동은 악의적인 것이 아니라면 자주 발생하는 일은 아니니 무리가 있어 보이지는 않습니다.
질문3. 위 절차 중 3번에서 주문 테이블엔 인서트하고 주문상품 테이블에 인서트를 하지 않는다면 정상적으로 "결제완료"가 된 후에만 주문상품 테이블에 데이터를 넣고 주문번호를 넣어주면 될까요?
네, 그게 깔끔할것 같습니다.
다만 위의 방식은 재고 관리가 조금 마음에 걸립니다. 카페24기준으로 재고가 있는 상품도 있고 아닌것도 있는데요, 재고가 있는 경우에는 재고정보가 어디엔가 들어 있어야 합니다. 이는 상품정보DB와는 별도의 DB가 되어야 할것이구요, 즉 별도의 스키마가 필요합니다.
저라면 주문상품DB를 따로 두지 않고, 주문정보에 상품정보와 수량을 기록하고, 이후에 발주 정보를 생성할때에는 혹은 주문 내역을 보여줄때 Join을 통해서 데이터를 생성할 것 같습니다. 그리고 재고정보DB와 수량을 맞추기 위해서 이것의 업데이트는 트랜잭션으로 묶어 주구요,
감사합니다.