////
Search
🪬

11장. 결제 시스템

최근 몇 년동안 전세계적으로 전자상거래의 인기는 폭발적으로 성장했다. 이를 가능하게 하는 핵심 시스템이 결제 시스템인데, 이번 장에서는 안정적이고 확장 가능하며 유연한 결제 시스템을 설계해본다.

1단계: 문제 이해 및 설계 범위 확정

결제 시스템은 다양하기 때문에 먼저 어떤 시스템을 설계할 것인지 결정하는 것이 중요하다.
어떤 사람은 애플, 삼성 페이같은 디지털 지갑을 혹은 페이팔같은 결제 처리 백엔드를 생각한다.
다음은 면접관에게 물어볼 수 있는 질문 리스트다.
어떤 결제 시스템을 만들어야 하나요?
어떤 결제 방법을 지원해야 하나요? 신용카드, 페이팔, 은행카드
신용 카드 결제 처리를 직접해야 하나요?
신용 카드 데이터를 시스템에 저장해야 하나요?
전 세계를 대상으로 해야 하나요? 다양한 통화 및 국제 결제를 지원해야 합니까?
하루에 몇 건의 결제가 이루어지나요
아마존과 같은 전자상거래 사이트에서 매월 판매자에게 대금을 지급하는 절차를 지원해야 하나요?
그외 주의사항은 무엇이 있나요?

기능 요구사항

대금 수신 흐름 : 결제 시스템이 판매자를 대신하여 고객으로부터 대금을 수령한다.
대금 정산 흐름 : 결제 시스템이 전 세계의 판매자에게 제품 판매 대금을 송금한다.

비기능 요구사항

신뢰성 및 내결함성 : 결제 실패는 신중하게 처리해야 한다.
내부 서비스와 외부 서비스 간의 조정 프로세스 : 시스템 간의 결제 정보가 일치하는지 비동기적으로 확인한다.

개략적인 규모 추정

이 시스템은 하루에 100만 건의 결제가 발생하므로 100만 건의 트랜잭션 / 86400s = 10 대략 초당 10건의 트랜잭션이 발생한다.
이는 일반적인 데이터베이스로 크게 문제 없이 처리 가능하므로 설계 목적은 처리 대역폭 대신 결제 트랜잭션의 정확한 처리에 초점을 맞추는 것이 좋다.

2단계: 개략적 설계안 제시 및 동의 구하기

아마존의 경우, 구매자가 주문을 하면 아마존의 은행 계좌로 돈이 들어오는데, 이것이 대금 수신 흐름이다. 이 돈은 아마존의 은행 계좌에 있지만 소유권이 아마존의 것은 아니다.
판매자가 상당 부분을 소유하고 있으며 배송이 완료되면 계좌에 묶여 있던 판매 대금에서 수수료를 제외한 잔액이 판매자의 은행 계좌로 지급된다. 이것이 대금 정산 흐름이다.

대금 수신 흐름

결제 서비스
결제 서비스는 사용자로부터 결제 이벤트를 수락하고 결제 프로세스를 조율한다.
일반적으로 가장 먼저 하는 작업은 AML/CFT와 같은 규정을 준수하는지, 자금 세탁이나 테러 자금 조달과 같은 범죄 행위에 연루되어있는지 평가하는 위험 점검이다.
위험 확인 서비스의 경우, 매우 복잡하고 고도로 전문화되어있기 때문에 제3자 제공업체를 사용한다.
결제 실행자
결제 서비스 공급자를 통해 결제 주문 하나를 실행한다.
하나의 결제 이벤트에는 여러 결제 주문이 포함될 수 있다.
결제 서비스 공급자
이는 A 계정에서 B 계정으로 돈을 옮기는 역할을 담당한다. 본 예제의 경우, 구매자의 신용 카드 계좌에서 돈을 인출하는 역할을 한다.
카드 유형
카드사는 신용 카드 업무를 처리하는 조직으로 마스터, 비자 등이 있다.
원장
결제 트랜잭션에 대한 금융 기록으로 사용자가 판매자에게 1달러를 결제하면 사용자로부터 1달러를 인출하고 판매자에게 1달러를 지급하는 기록을 남긴다.
이는 전자상거래 웹사이트의 총 수익을 계산하거나 향후 수익을 예측하는 등, 결제 후 분석에서 매우 중요한 역할을 한다.
지갑
지갑에는 판매자의 계정 잔액을 기록한다. 특정 사용자가 결제한 총 금액을 기록할 수도 있으며 일반적인 결제 흐름은 다음과 같다.
1.
사용자가 주문하기 버튼을 클릭하면 결제 이벤트가 생성되어 결제 서비스로 전송된다.
2.
결제 서비스는 결제 이벤트를 데이터베이스에 저장한다.
3.
때로는 단일 결제 이벤트에 여러 결제 주문이 포함될 수 있다. 한 결제를 여러 결제 주문으로 분할하는 경우, 결제 서비스는 결제 주문마다 결제 실행자를 호출한다.
4.
결제 실행자는 결제 주문을 데이터베이스에 저장한다.
5.
결제 실행자가 외부 PSP를 호출하여 신용 카드 결제를 처리한다.
6.
결제 실행자가 결제를 성공적으로 처리하고 나면 결제 서비스는 지갑을 갱신하여 특정 판매자의 잔고를 기록한다.
7.
지갑 서버는 갱신된 잔고 정보를 데이터베이스에 저장한다.
8.
지갑 서비스가 판매자 잔고를 성공적으로 갱신하면 결제 서비스는 원장을 호출한다.
9.
원장 서비스는 새 원장 정보를 데이터베이스에 추가한다.

결제 서비스 API

POST /v1/payments
결제 이벤트를 실행하는 엔드포인트로, 여러 결제 주문이 포함될 수 있다.
GET /v1/payments/{:id}
이 엔드포인트는 단일 결제 주문의 실행 상태를 반환한다.

결제 서비스 데이터 모델

결제 서비스에는 결제 이벤트와 결제 주문의 두 개 테이블이 필요하다.
결제 시스템용 저장소 솔루션을 고를 때 일반적으로 성능보단 안정성, 모니터링에 초점을 두고 선택할 수 있도록 한다.
안정성이 검증되었는가?
모니터링 및 데이터 탐사에 필요한 도구가 풍부하게 지원되는가?
데이터베이스 관리자 채용 시장이 성숙한가?
일반적으로 NoSQL보단 ACID 트랜잭션을 지원하는 전통적인 관계형 데이터베이스를 선호한다.

복식부기 원장 시스템

원장 시스템에는 복식부기(double-entry)라는 아주 중요한 설계 원칙이 있다.
이는 모든 결제 시스템에 필수 요소이며 정확한 기록을 남기는데 핵심적인 역할을 한다.

외부 결제 페이지

대부분의 기업은 신용 카드 정보를 내부에 저장하지 않는데, 이는 신용 카드 정보를 내부에 저장하는 경우, 미국의 PCI DSS와 같은 복잡한 규정을 준수해야 하기 때문이다.
신용 카드 정보를 취급하지 않기 위해 기업들은 PSP에서 제공하는 외부 신용 카드 페이지를 사용한다.

대금 정산 흐름

대금 수신 흐름과 유사한데, 한 가지 차이는 PSP를 사용하여 구매자의 신용 카드에서 전자상거래 웹사이트 은행 계좌로 돈을 이체하는 대신, 정산 흐름에서는 타사 정산 서비스를 사용하여 전자상거래 웹사이트 은행 계좌에서 판매자 은행 계좌로 돈을 이체한다는 점이다.
일반적으로 결제 시스템은 대금 정산을 위해 티팔티와 같은 외상매입금 지급 서비스 제공업체를 이용한다. 대금 정산에도 다양한 부기 및 규제 요구사항이 있기 때문이다.

3단계: 상세 설계

PSP 연동

결제 시스템이 은행이나 비자 또는 마스터카드와 같은 카드 시스템에 직접 연결할 수 있다면 PSP 없이도 결제할 수 있다.
하지만 이러한 이런 연결은 아주 특수한 경우로 한정되며 대부분의 회사는 다음 두 가지 방법 중 하나로 결제 시스템을 PSP와 연동한다.
1.
회사가 민감한 결제 정보를 안전하게 저장할 수 있다면 API를 통해 PSP와 연동하는 방법을 택할 수 있다.
2.
복잡한 규정 및 보안 문제로 인해 민감한 결제 정보를 저장하지 않기로 했다면 PSP는 카드 결제 세부 정보를 수집하여 PSP에 안전하게 저장할 수 있도록 외부 결제 페이지를 제공한다.
대부분의 기업이 택하는 접근법이다.

조정

시스템 구성 요소가 비동기적으로 통신하는 경우, 메시지가 전달되거나 응답이 반환된다는 보장이 없다.
이는 시스템 성능을 위해 비동기 통신을 자주 사용하는 결제 관련 사업의 일반적인 문젠데, 그렇다면 어떻게 정확성을 보장할 수 있을까?
조정을 통해 해결할 수 있다. 관련 서비스 간의 상태를 주기적으로 비교하여 일치하는지 확인하는 것이다.
매일 밤 은행이 점검을 수행할 때, 고객에게 정산 파일을 보낸데, 여기엔 은행 계좌의 잔액과 하루 동안 해당 계좌에서 발생한 모든 거래 내역이 기재되어 있으며 조정 시스템은 이를 읽은 후 원장 시스템과 비교한다.
조정 중에 발견된 차이는 일반적으로 재무팀에 의뢰하여 수동으로 고친다. 발생 가능한 불일치 문제 및 해결 방안은 다음 세 범주로 나눌 수 있다.
1.
어떤 유형의 문제인지 알고 있으면 문제 해결 절차를 자동화할 수 있는 경우
원인과 해결 방법을 알고 있으며 자동화 프로그램을 구현하는 것이 가장 효율적인 경우이다.
2.
어떤 유형의 문제인지는 알지만 문제 해결 절차를 자동화할 수는 없는 경우
자동화 프로그램의 비용이 너무 높은 경우, 작업 대기열에 넣고 재무팀이 수동으로 작업하도록 둔다.
3.
분류할 수 없는 유형의 문제인 경우
이런 불일치 문제의 경우, 특별 작업 대기열에 넣어두고 재무팀이 조사하도록 한다.

결제 지연 처리

결제 요청이 오래 걸리게 되는 사례는 다음과 같다.
PSP가 해당 결제 요청의 위험성이 높다고 보고 담당자 검토를 요구하는 경우
신용 카드사가 구매 확인 용도로 카드 소유자의 추가 정보를 요구하는 3D 보안 인증같은 절차를 요구하는 경우
구매 페이지가 외부 PSP에 호스팅되는 경우, PSP는 다음과 같이 처리한다.
PSP는 결제가 대기 상태임을 알리는 상태 정보를 클라이언트에 반환하고 클라이언트는 이를 사용자에게 표시한다.
PSP는 우리를 대신하여 대기 중인 결제의 진행 상황을 추적하고 상태가 바뀌면 PSP에 등록된 웹훅을 통해 결제 서비스에 알린다.

내부 서비스 간 커뮤니케이션

동기식 통신
HTTP와 같은 동기적 통신은 소규모 시스템에서는 잘 작동하지만 규모가 커지면 단점이 분명해진다.
동기식 통신에서 한 요청에 응답을 만드는 처리 주기는 관련된 서비스가 많을수록 길어진다. 대표적인 단점은 다음과 같다.
성능 저하 : 요청 처리에 관련된 서비스 가운데 하나에 발생한 성능 문제가 전체 시스템의 성능에 영향을 끼친다.
장애 격리 곤란 : PSP 등의 서비스에 장애가 발생하면 클라이언트는 더 이상 응답을 받지 못한다.
높은 결합도 : 요청 발신자는 수신자를 알아야만 한다.
낮은 확장성 : 큐를 버퍼로 사용하지 않고서는 갑작스러운 트래픽 증가에 대응할 수 있도록 시스템을 확장하기 어렵다.
비동기 통신
단일 수신자
각 요청은 하나의 수신자 또는 서비스가 처리한다. 일반적으로 공유 메시지 큐를 사용해 구현한다.
큐에는 복수의 구독자가 있을 수 있으나 처리된 메시지는 큐에서 바로 제거된다.
다중 수신자
각 요청은 여러 수신자 또는 서버가 처리한다.
소비자가 수신한 메시지는 카프카에서 바로 사라지지 않는다. 따라서 동일한 메시지를 여러 서비스가 받아 처리할 수 있다.

결제 실패 처리

결제 상태 추적
결제 상태를 정확하게 유지하여 실패가 일어날 때마다 결제 거래의 현재 상태를 파악하고 재시도 또는 환불이 필요한지 결정한다.
재시도 큐 및 실패 메시지 큐
재시도 큐 : 일시적 오류 같은 재시도 가능 오류는 재시도 큐에 보낸다.
실패 메시지 큐 : 반복적으로 처리에 실패하는 메시지는 실패 메시지 큐로 보낸다.
프로세스는 다음과 같다.
1.
재시도가 가능한지 확인한다.
a.
재시고 가능한 경우 재시도 큐로 보낸다.
b.
잘못된 입려고가 같이 재시도가 불가능한 실패는 오류 내역을 데이터베이스에 저장한다.
2.
결제 시스템은 재시도 큐에 쌓인 이벤트를 읽어 실패한 결제를 재시도한다.
3.
결제 거래가 다시 실패하는 경우에는 다음과 같이 처리한다.
a.
재시도 횟수가 임계값 이내라면 해당 이벤트를 다시 재시도 큐로 보낸다.
b.
재시도 횟수가 임계값을 넘으면 해당 이벤트를 실패 메시지 큐에 넣는다.

정확히 한 번 전달

결제 주문이 정확히 한 번만 처리되도록 시스템을 설계하는 것이 중요하다.
수학적으로 다음의 요건들이 충족되면 주어진 연산은 정확히 한 번 실행된다.
최소 한 번은 실행된다.
최대 한 번 실행된다.
재시도
간혹 네트워크 오류나 시간 초과로 결제 거래를 다시 시도해야 하는 경우, 재시도 메커니즘을 활용하면 어떤 결제가 최소 한 번은 실행되도록 보장 가능하다.
재시도 메커니즘의 경우, 전략을 잘 선택해야 한다. 일반적으로 사용되는 전략들은 다음과 같다.
즉시 재시도 : 클라이언트는 즉시 요청을 다시 보낸다.
고정 간격 : 재시도 전에 일정 시간 기다리는 방안이다.
증분 간격 : 재시도 전에 기다리는 시간을 특정한 양 만큼 점진적으로 늘려가는 방안이다.
지수적 백오프 : 재시도 전에 기다리는 시간을 직접 재시도 대비 두 배씩 늘려가는 방안이다.
취소 : 요청을 철회하는 방안이다.
멱등성
멱등성은 최대 한 번 실행을 보장하기 위한 핵심 개념이다.
클라이언트와 서버 간의 통신을 위해서는 일반적으로 클라이언트가 생성하고 일정 시간이 지나면 만료되는 고유한 값을 멱등 키로 사용한다.

일관성

결제 실행 과정에서 상태 정보를 유지 관리하는 여러 서비스가 호출된다.
1.
결제 서비스는 비중복 난수, 토큰, 결제 주문, 실행 상태 등의 결제 관련 데이터를 유지 관리한다.
2.
원장은 모든 회계 데이터를 보관한다.
3.
지갑은 판매자의 계정 잔액을 유지한다.
4.
PSP는 결제 실행 상태를 유지한다.
5.
데이터는 안정성을 높이기 위해 여러 데이터베이스 사본에 복제될 수 있다.

결제 보안

문제
해결책
요청/응답 도청
HTTPS 사용
데이터 변조
암호화 및 무결성 강화 모니터링
중간자 공격
인증서 고정과 함께 SSL 사용
데이터 손실
여러 지역에 걸쳐 데이터베이스 복제 및 스냅샷 생성
분산 서비스 거부 공격
처리율 제한 및 방화벽
카드 도난
토큰화, 실제 카드 번호를 사용하는 대신 토큰을 저장하고 결제에 사용
PCI 규정 준수
PCI DSS는 브랜드 신용 카드를 처리하는 조직을 위한 정보 보안 표준이다.
사기
주소 확인, 카드 확인번호, 사용자 행동분석 등

4단계: 마무리

결제 시스템은 아주 복잡하며 많은 주제를 다루었지만 아직도 언급할 가치가 있는 주제가 많이 남아 있다.
모니터링 : 주요 지표를 모니터링하는 것은 아주 중요하다. 대표적으로 특정 결제 수단의 평균 승인율은 몇인가?, 서버의 CPU 사용량은 얼마인가 등의 지표들을 수집해볼 수 있다.
경보 : 비정상적인 상황이 발생하면 온콜 중인 개발자에게 알려 신속하게 대응할 수 있도록 하는 것이 중요하다.
디버깅 도구 : 엔지니어와 고객 지원팀이 쉽게 디버깅할 수 있도록 결제 거래의 상태, 처리 서버 기록, PSP 기록 등을 검토할 수 있는 도구를 개발하는 것이 중요하다.
환율 : 국제적인 결제 시스템을 설계할 때 환율은 중요한 고려사항이다.
지역 : 지역마다 가용한 결제 수단이 다를 수 있다.
현금 결제 : 현금 결제는 인도, 브라질 등의 국가에서 매우 일반적인데, 우버와 에어비앤비가 현금 결제 방법에 대해 엔지니어링 블로그에 올려놓았으므로 이를 참고하면 좋다.
구글/애플 페이 연동