이번 장에서는 결제 시스템(Payment system)을 설계한다.
전자 상거래를 가능하게 하는 것이 바로 결제 시스템이며, 안정적이고 확장 가능하며 유연한 결제 시스템은 필수다.
결제 시스템?
결제 시스템은 금전적 가치의 이전을 통해 금융 거래를 정산하는 데 사용되는 모든 시스템
결제 시스템의 구조 자체는 어렵지 않지만, 작은 실수로도 상당한 매출 손실이 발생하고, 사용자의 믿음이 무너질 수 있기 때문에 작업하기 부담스러운 시스템이다.
1단계: 문제 이해 및 설계 범위 확정
애플 페이나 구글 페이 같은 디지털 지갑, 페이팔, 스트라이프 같은 결제 처리 백엔드모두 결제 시스템 이므로, 면접을 시작할 때 정확한 요구사항을 파악하여 설계를 시작해야한다.
- Q. 어떤 결제 시스템?
- A. 전자상거래 애플리케이션을 위한 결제 백엔드 구축, 돈의 흐름에 대한 모든 것을 처리해야함
- Q. 어떤 결제 방법 지원?
- A. 이번 면접에서는 신용 카드 결제만 처리
- Q. 신용 카드 결제 처리를 직접 수행?
- A. 전문 결제 서비스 업체 활용
- Q. 신용 카드 데이터를 시스템에 저장?
- A. 보안 및 법규 준수에 대한 어려움으로 결제 처리 업체에 의존
- Q. 다양한 통화 및 국제 결제 지원?
- A. No
- Q. 하루에 발생하는 결제 건수는?
- A. 100만건
- Q. 정산 처리 지원?
- A. Yes
- Q. 다른 주의사항은?
- A. 많은 내부 서비스 및 외부 서비스와 연동하므로 조정 작업을 통해 불일치를 발견하고 교정해야함
기능 요구사항
- 대금 수신(pay-in) 흐름
- 결제 시스템이 판매자를 대신하여 고객으로부터 대금을 수령
- 대금 정산(pay-out) 흐름
- 결제 시스템이 전 세계의 판매자에게 제품 판매 대금을 송금
비기능 요구사항
- 신뢰성 및 내결함성
- 결제 실패는 신중하게 처리
- 내부 서비스(결제, 회계)와 외부 서비스(결제 서비스 제공 업체) 간 조정 프로세스
- 시스템 간의 결제 정보가 일치하는지 비동기적으로 확인
개략적 규모 추정
하루에 100만 건의 트랜잭션을 처리해야하므로 1,000,000 만건 / 10^5초 = 10 TPS
이다.
10TPS는 일반적인 데이터베이스로 별 문제 없이 처리 가능한 양이므로, 처리 대역폭 대신 결제 트랜잭션의 정확한 처리에 초점을 맞춰 진행해야한다.
2단계: 개략적 설계안 제시 및 동의 구하기
대금 수신 흐름
결제 서비스
사용자로부터 결제 이벤트를 수락하고 결제 프로세스를 조율하는데, 일반적으로 가장 먼저 위험 점검(risk check)을 수행한다.
- AML/CFT 같은 규정을 준수 여부 확인
- 자금 세탁이나 테러 자금 조달과 같은 범죄 행위의 증거가 있는지 평가
위험 확인 서비스는 매우 복잡하고 고도로 전문화되어 있기 때문에 제3자 제공 업체를 이용한다.
결제 실행자
결제 서비스 공급자(PSP)를 통해 결제 주문(payment order) 하나를 실행한다.
- 하나의 결제 이벤트에는 여러 결제 주문이 포함될 수 있다.
결제 서비스 공급자
PSP(Payment Service Provider)는 A 계정에서 B 계정으로 돈을 옮기는 역할을 담당한다.
- 구매자의 신용 카드 계좌에서 돈을 인출하는 역할 등
카드 유형
카드사는 신용 카드 업무를 처리하는 조직이다.
- 비자, 마스터카드 등
원장 ledger
결제 트랜잭션에 대한 금융 기록이다.
- 사용자가 판매자에게 1달러를 결제하면 사용자로부터 1달러 인출, 판매자에게 1달러 지급하는 기록
원장 시스템은 전자상거래 웹사이트의 총 수익을 계산하거나 향후 수익을 예측하는 등, 결제 후 분석(post-payment analysis)에서 매우 중요한 역할을 한다.
지갑
판매자의 계정 잔액을 기록한다.
- 특정 사용자가 결제한 총 금액을 기록할 수도 있다.
결제 서비스 API
POST /v1/payments
결제 이벤트를 실행한다.
하나의 결제 이벤트에는 여러 결제 주문이 포함될 수 있다.
buyer_info
- 구매자 정보
checkout_id
- 해당 결제 이벤트를 식별하는 전역적으로 고유한 ID
credit_card_info
- 암호화된 신용 카드 정보 또는 결제 토큰.
- PSP마다 다름
payment_orders
- 결제 주문 목록
payment_order
seller_account
amount
double
같은 자료형은 반올림 오차, 화폐 단위의 차이 등으로 인해string
으로 사용하는 것이 좋다.
currency
payment_order_id
- 전역적으로 고유한 ID
- 결제 실행자가 중복 제거를 위한 멱등키로 사용한다.
GET /v1/payments/{:id}
payment_order_id
가 가르키는 단일 결제 주문의 실행 상태를 반환한다.
결제 서비스 데이터 모델
결제 이벤트와 결제 주문 두 개의 테이블이 필요하다.
결제 시스템용 저장소 솔루션을 고를 때 일반적으로 성능은 가장 중요한 고려사항은 아니며, 다음 사항에 중점을 둬야한다.
- 안정성
- 다른 대형 금융 회사에서 긴 기간동안 긍정적인 피드백을 받으며 사용된 적이 있는가?
- 모니터링 및 데이터 탐사
- 관련 기능을 위한 도구가 풍부하게 지원되는가?
- 인재풀
- 데이터베이스 관리자 채용 시장의 성숙도
일반적으로는 NoSQL/NewSQL 보다는 ACID 트랜잭션을 지우너하는 전통적인 관계형 데이터베이스를 선호한다.
erDiagram PaymentEvent { checkout_id string PK buyer_info string seller_info string credit_card_info string is_payment_done boolean }
- 한번의 결제 행위는 하나의 결제 이벤트를 만들고, 하나의 결제 이벤트에는 여러 개의 결제 주문이 포함될 수 있다.
- 사용자의 결제를 처리하는 중에는 판매자의 응행 계좌가 아닌 구매자의 카드 정보만 필요하다.
erDiagram PaymentOrder { payment_order_id string pk buyer_account string amount string currency string checkout_id string FK payment_order_status string ledger_updated boolean wallet_updated boolean }
payment_order_status
는 결제 주문의 실행 상태를 유지하는 열거 자료형이다.
NOT_STARTED
,EXECUTING
,SUCCESS
,FAILED
업데이트 로직의 흐름은 다음과 같다.
- 초기값은
NOT_STARTED
- 결제 서비스는 결제 실행자에 주문을 전송하면
payment_order_status
의 값을EXECUTING
으로 바꾼다. - 결제 서비스는 결제 처리자의 응답에 따라
payment_order_status
의 값을SUCCESS
또는FAIL
로 바꾼다.
payment_order_status
값이 SUCCESS
로 결정되면 결제 서비스는 지갑 서비스를 호출하여 판매자 잔액을 업데이트하고, wallet_updated
필드의 값은 true
로 업데이트한다.
이 절차가 끝나면 결제 서비스는 원장 서비스를 호출하여 ledger_updated
필드를 true
로 갱신한다.
동일한 check_id
아래의 모든 결제 주문이 성공적으로 처리되면 결제 서비스는 결제 이벤트 테이블의 is_payment_done
을 true
로 업데이트한다.
일반적으로 종결되지 않은 결제 주문을 모니터링 하기 위해 주기적으로 실행되는 작업을 마련해둔다.
- 임계값 형태로 설정된 기간이 지나도록 완료되지 않은 결제 주문이 있을 경우 살펴보도록 엔지니어에게 경보를 보낸다.
복식부기 원장 시스템
원장 시스템에는 복식부기(double-entry)라는 중요한 설계 원칙이 있다.
- 복식부기 회계(accounting)/부기(bookeeping)라고도 한다.
복식부기는 모든 결제 시스템에 필수 요소이며 정확한 기록을 남기는 데 핵심적 역할을 한다.
모든 결제 거래를 두 개의 별도 원장 계좌에 같은 금액으로 기록하며, 한 계좌에서는 차감, 다른 계좌에서는 입금이 이루어진다.
복식부기 시스템에서 모든 거래 항목의 합계는 0이어야 한다.
이 시스템을 활용하면 자금의 흐름을 시작부터 끝까지 추적할 수 있으며, 결제 주기 전반에 걸쳐 일관성을 보장할 수 있다.
외부 결제 페이지
대부분 기업은 신용 카드 정보를 내부에 저장하면 복잡한 규정을 준수해야 하므로 저장하지 않는다.
따라서 PSP에서 제공하는 **외부 신용 카드 페이지(hosted credit card page)**를 사용한다.
- 위젯, iframe, SDK등
이를 통해 우리 결제 서비스가 아닌 PSP가 제공하는 외부 결제 페이가 직접 고객 카드 정보를 수집한다.
대금 정산 흐름
대금 수신 흐름과 아주 유사하다.
한 가지 차이는 PSP를 사용하여 구매자의 신용 카드에서 전자 상거래 웹사이트 은행 계좌로 돈을 이체하는 대신, 타사 정산 서비스를 사용하여 전자 상거래 웹사이트 은행 계좌에서 판매자 은행 계좌로 돈을 이체한다.
일반적으로 외상 매입금(accounts payable) 지급 서비스 제공 업체를 이용한다.
- 마찬가지로 다양한 규제 요구사항들이 있기 때문
3단계: 상세 설계
이번 절에서는 시스템을 더 빠르고 강력하며 안전하게 만드는 데 초점을 맞춘다.
- 분산 시스템에서 오류와 장애는 피할 수 없을 뿐만 아니라 흔하다.
PSP 연동
결제 시스템이 카드 시스템에 직접 연결할 수 있다면 PSP 없이도 결제할 수 있지만, 매우 큰 회사만 가능하여 특수한 경우로 간주한다.
대부분 회사는 두 가지 방법 중 하나로 결제 시스템을 PSP와 연동한다.
- 민감 정보를 안전하게 저장할 수 있다면 API를 통해 PSP와 연동한다.
- 회사는 결제 웹페이지 개발, 민감 정보 수집
- PSP는 은행 연결, 다양한 카드 지원
- 민감 정보를 저장하지 않는다면 PSP를 전부 활용
- 대부분 기업들이 택하는 접근법
조정
시스템 구성 요소가 비동기적으로 통신하는 경우 메시지가 전달되거나 응답이 반환된다는 보장이 없다.
- 시스템 성능을 높이기 위해 비동기 통신을 자주 사용하는 결제 관련 사업에 일반적인 문제
PSP나 은행 같은 외부 시스템도 비동기 통신을 선호하므로 조정을 통해 정확성을 보장할 수 있어야한다.
조정 Reconciliation
관련 서비스 간의 상태를 주기적으로 비교하여 일치하는지 확인하며, 일반적으로 결제 시스템의 마지막 방어선으로 받아들여진다.
매일 밤 PSP나 은행은 고객에게 정산 파일을 보낸다.
- 은행 계좌의 잔액, 하루 동안 계좌에서 발생한 모든 거래 내역이 기재
조정 시스템은 정산 파일의 세부 정보를 읽어 원장 시스템과 비교한다.
조정은 결제 시스템의 내부 일관성을 확인할 때도 사용된다.
- 원장과 지갑의 상태가 같은지 확인
조정 중 발견된 차이는 일반적으로 재무팀에 의뢰하여 수동으로 고치게되느데 발생 가능한 불일치 문제 및 해결 방안은 세 가지 범주로 나눌 수 있다.
- 어떤 유형의 문제인지 알고 있으며 문제 해결 절차를 자동화할 수 있는 경우
- 자동화 프로그램을 작성하는 것이 효율적이다.
- 어떤 유형의 문제인지는 알니만 자동화할 수 없는 경우
- 작업 대기열에 넣고 재무팀에서 수동으로 수정하도록 한다.
- 분류할 수 없는 유형 문제인 경우
- 특별 작업 대기열에 넣고 재무팀에서 조사하도록 한다.
결제 지연 처리
결제 요청은 많은 컴포넌트를 거치며, 내부 및 외부의 다양한 처리 주체와 연동한다.
대부분의 경우 결제 요청은 몇 초만에 처리되지만, 완료되거나 거부되기까지 몇 시간 또는 며칠이 걸리는 경우도 있다.
- PSP가 해당 결제 요청의 위험성이 높다고 보고 담당자 검토를 요구하는 경우
- 신용 카드사가 구매 확인 용도로 카드 소유자의 추가 정보를 요청하는 3D 보안 인증 같은 추가 보호 장치를 요구하는 경우
결제 서비스는 처리하는 데 시간이 오래 걸리는 위와 같은 요청에도 대응할 수 있어야 하며, 구매 페이지가 외부 PSP에 호스팅 되는 경우 PSP는 대부분 다음과 같이 처리한다.
- 결제가 대기 상태임을 알리는 상태 정보를 클라이언트에 반호나하고, 클라이언트는 이를 사용자에게 표시한다.
- 우리 회사를 대신하여 대기 중인 결제의 진행 상황을 추적하고, 상태가 바뀌면 PSP에 등록된 웹훅을 통해 결제 서비스에 알린다.
결제 요청이 최종적으로 완료되면 PSP는 웹훅을 호출한다.
결제 서비스는 내부 시스템에 기록된 정보를 업데이트하고 고객에게 배송을 완료한다.
- 어떤 PSP는 웹훅을 통해 결제 서비스에 결제 상태 변경을 알리는 대신, 결제 서비스로 하여금 대기 중인 결제 요청의 상태를 주기적으로 확인하도록 하기도 한다.
내부 서비스 간 커뮤니케이션
두 가지 패턴이 있다.
동기식 통신
HTTP 같은 동기식 통신은 소규모 시스템에서는 잘 작동하지만 규모가 커지면 단점이 분명해지며, 한 요청에 응답을 만드는 처리 주기는 관련된 서비스가 많을수록 길어진다.
- 성능 저하
- 처리에 관계된 서비스 가운데 하나에 발생한 성능 문제가 전체 시스템의 성능에 영향을 끼친다.
- 장애 격리 곤란
- PSP 등의 서비스에 장애가 발생하면 클라이언트는 더 이상 응답을 받지 못한다.
- 높은 결합도
- 요청 발신자는 수신자를 알아야 한다.
- 낮은 확정성
- 큐를 버퍼로 사용하지 않고서는 갑작스러운 트래픽 증가에 대응할 수 있도록 시스템을 확장하기 어렵다.
비동기 통신
크게 두가지 점주로 나눌 수 있다.
- 단일 수신자
- 요청은 하나의 수신자 또는 서비스가 처리한다.
- 공유 메시지 큐를 사용해 구현한다.
- 복수 구독자가 있을 수 있으나 처리된 메시지는 큐에서 바로 제거
- 다중 수신자
- 메시지는 여러 수신자 또는 서버가 처리한다.
- 카프카가 적합하다.
- 소비자가 수신한 메시지는 카프카에서 바로 사라지지 않기 때문에 동일한 메시지를 여러 서비스가 받아 처리할 수 있다.
- 결제시스템에서는 하나의 요청이 푸시 알림, 재무 보고 업데이트, 분석 결과 업데이트 등 다양한 용도로 쓰일 수 있기 때문에 적합하다.
일반적으로 동기식 통신은 설계하기 쉽지만 서비스의 자율성을 높이기에는 적합하지 않다.
- 의존성 그래프가 커지면 전반적 성능은 낮아진다.
비동기 통신은 설계의 단순성과 데이터 일관성을 시스템 확장성 및 장애 감내 능력과 맞바꾼 결과다.
- 비즈니스 로직이 복잡하고 타사 서비스 의존성이 높은 대규모 결제 시스템에는 비동기 통신이 더 나은 선택이다.
결제 실패 처리
모든 결제 시스템은 안정성 및 결함 내성이 핵심적 요구사항으로 실패한 결제를 적절히 처리할 수 있어야한다.
결제 상태 추적
결제 주기의 모든 단계에서 결제 상태를 정확하게 유지하는 것은 매우 중요하다.
실패가 일어날 때마다 결제 거래의 현재 상태를 파악하고 재시도 또는 환불이 필요한지 여부를 결정한다.
- 결제 상태는 데이터 추가만 가능한 데이터베이스 테이블에 보관한다.
재시도 큐 및 실패 메시지 큐
실패를 우아하게 처리하기 위해서는 재시도 큐와 실패 메시지 큐를 두는 것이 바람직하다.
- 재시도 큐
- 일시적 오류 같은 재시도 가능 오류는 재시도 큐에 보낸다.
- 실패 메시지 큐
- 반복적으로 처리에 실패한 메시지는 실패 메시지 큐로 보낸다.
- 문제가 있는 메시지를 디버깅하고 결기하여 성공적으로 처리되지 않은 이유를 파악하기 위한 검사에 유용하다.
정확히 한 번 전달
결제 시스템에 발생 가능한 가장 심각한 문제 중 하나는 고객에게 이중으로 청구하는 것이다.
결제 주문이 정확히 한 번만 실행되도록 결제 시스템을 설계하는 것이 중요하다.
어려운 문제로 보이지남 문제를 두 부분으로 나누면 훨씬 쉽게 해결할 수 있으며 수학적으로 다음 요건이 충족되면 주어진 연산은 정확히 한 번 실행된다.
- 최소 한 번은 실행된다.
- 최대 한 번 실행된다.
재시도를 통해 최소 한 번 실행을 보증하는 방법과 멱등성 검사를 통해 최대 한 번 실행을 보증하는 방법을 알아본다.
재시도
네트워크 오류나 시간 초과로 인해 결제 거래를 다시 시도해야 하는 경우 재시도 메커니즘을 활용하면 어떤 결제가 최소 한 번은 실행되도록 보장 가능하다.
재시도 매커니즘을 도입할 때는 얼마나 간격을 두고 재시도할지 정하는 것이 중요하다.
- 즉시 재시도(immediate retry)
- 클라이언트는 즉시 요청을 다시 보낸다.
- 고정 간격(fixed interval)
- 재시도 전에 일정 시간을 기다린다.
- 증분 간격(incremental interval)
- 재시도 전에 기다리는 시간을 특정한 양 만큼 점진적으로 늘려나간다.
- 지수적 백오프(exponential backoff)
- 재시도 전에 기다리는 시간을 직전 재시도 대비 두 배씩 늘려 나가는 방안
- 취소(cancel)
- 요청을 철회한다.
- 실패가 영구적이거나 재시도를 하더라도 성공 가능성이 낮은 경우 흔히 사용된다.
모든 상황에 맞는 해결책은 없지만, 일반적으로 네트워크 문제가 단시간 해결될 것 같지 않다면 지수적 백오프를 사용한다.
지나치게 공격적인 재시도 전략은 컴퓨팅 자원을 낭비하고 서비스 과부하를 유발한다.
- 에러 코드를 반환할 때는
Retry-After
헤더를 같이 붙여 봰는 것이 바람직하다.
멱등성
멱등성은 최대 한 번 실행을 보장하기 위한 핵심 개념이다.
멱등성 Idempotency
수학 또는 컴퓨터 과학적 연산이 가질 수 있는 한 가지 속성으로, 연산을 여러 번 실행하여도 최초 실행 결과가 그대로 보존되는 특성 일걷는다.
API 관점에서 보자면 클라이언트가 API 여러번 호출해도 항상 동일한 결과가 나온다는 뜻이다.
클라이언트와 서버 간의 통신을 위해서 일반적으로 클라이언트가 생성하고 일정 시간이 지나면 만료되는 고유한 값을 멱등 키로 사용한다.
- UUID를 멱등 키로 군장하며 실제 널리 쓰인다.
시나리오 1: 고객이 결제 버튼을 빠르게 두 번 클릭하는 경우
요청에 포함된 멱등 키를 이전에 받은 적이 있다면 재시도로 처리하며, 이전 결제 요청의 가장 최근 상태를 활용한다.
동일한 멱등 키로 동시에 많은 요청을 받으면 결제 서비스는 그 가운데 하나만 처리하고 나머지에 대해서 429 Too Many Requests
상태 코드를 반환한다.
- 멱등성을 지원하는 한 가지 방법으로 데이터베이스의 고유 키 제약 조건을 활용하여 테이블의 기본 키를 멱등키로 사용할 수 있다.
시나리오 2: PSP가 결제를 성공적으로 처리했지만 네트워크 오류로 응답이 결제 시스템에 전달되지 않아 사용자가 결제 버튼을 다시 클릭하는 경우
결제 서비스는 PSP에 비중복 난수를 전송하고 PSP는 해당 난수에 대응되는 토큰을 반환한다.
이 난수는 결제 주문을 유일하게 식별하며, 해당 토큰은 그 난수에 일대일로 대응되어 토큰 또한 결제 주문을 유일하게 식별할 수 있다.
사용자가 결제 버튼을 다시 누른다고 해도 결제 주문이 같으니 PSP로 전동되는 토큰도 같기 때문에, PSP가 이중 결제로 판단하고 종전 실행 결과를 반환하게 된다.
일관성
결제 실행 과정에서 상태 정보를 유지 관리하는 여러 서비스가 호출된다.
- 결제 서비스
- 비중복 난수, 토큰, 결제 주문, 실행 상태 등 결제 관련 데이터
- 원장
- 모든 회계 데이터
- 지갑
- 판매자의 계정 잔액
- PSP
- 결제 실행 상태
- + 여러 데이터베이스의 사본에 복제될 수 있다.
분산 환경에서는 서비스 간 통신 실패로 데이터의 불일치가 발생할 수 있으므로 내부 서비스 간 데이터 일관성을 유지하려면 요청이 정확히 한 번 처리되도록 보장하는 것이 아주 중요하다.
- 내부 서비스와 외부 서비스(PSP) 간의 데이터 일관성 유지를 위해 일반적으로 멱등성과 조정 프로세스를 활용한다.
하지만 외부 서비스가 멱등 API를 지원하더라도 항상 옳다고 가정할 수는 없다.
데이터를 다중화하는 경우 복제 지연으로 인해 기본 데이터베이스와 사본 데이터베이스가 불일치하는 일이 발생할 수 있으며 두 가지 해결 방법이 있다.
- 주 데이터베이스에서만 읽기와 쓰기를 수행
- 설정은 쉽지만 규모 확장성이 떨어진다.
- 사본은 데이터 안정성 보장에만 활용하고 트래픽은 처리하지 않는다.
- 자원 낭비
- 모든 사본을 항상 동기화
- 팩서스, 래프트 같은 합의 알고리즘을 사용
- YugabyteDb, CockroachDB와 같은 합의 기반 분산 데이터베이스를 사용한다.
결제 보안
결제 보안은 매우 중요하다. 사이버 공격과 카드 도난에 대응하기 위한 몇 가지 그술을 간략하게 살펴본다.
문제 | 해결책 |
---|---|
요청/응답 도청 | HTTPS |
데이터 변조 | 암호화 및 무결성 강화 모니터링 |
중간자 공격 | 인증서 고정과 함께 SSL 사용 |
데이터 손실 | 여러 지역에 걸쳐 데이터베이스 복제 및 스냅숏 생성 |
분산 서비스 거부 공격 | 처리율 제한 및 방화벽 |
카드 도난 | 토큰화. 실제 카드 번호를 사용하는 대신 토큰을 저장하고 결제에 사용 |
PCI 구정 준수 | PCI DSS는 브랜드 신용 카드를 처리하는 조직을 위한 정보 보안 표준 |
사기 | 주소 확인, 카드 확인 번호(CVV), 사용자 행동 분석 등 |
4단계: 마무리
대금 수신과 정산 흐름을 살펴보고 재시도, 멱등성, 일관성에 대해서도 자세히 살펴보았다.
결제 시스템은 아주 복잡하며 다루지 않았지만 중요한 주제들도 많이 남아있다.
- 모니터링
- 주요 지표를 모니터링 하는 것은 모든 현대적 애플리케이션에 아주 중요하다.
- 광범위한 모니터링을 통해 많은 정보들을 알 수 있다.
- 대시보드를 만들 수도 있다.
- 경보
- 비정상적인 사요항이 발생하면 온콜 중인 개발자에게 알려 신속하게 대앙흘 수 있도록 한다.
- 디버깅 도구
- 엔지니어와 고객 지원팀이 더 쉽게 디버깅 할 수 있도록 결제 거래의 상태, 처리 서버 기록, PSP 기록 등을 검토할 수 있는 도구를 개발하는 것이 중요하다.
- 환율
- 국제적인 결제 시스템 설계에 중요한 고려 사항
- 지역
- 지역마다 가용한 결제 수단이 완전히 달라질 수 있다.
- 현금 결제
- 구글/애플 페이 연동 등