티스토리 뷰
목차
배경
최근 사이드 프로젝트로 주문서 페이지를 제작하고 있다. 프로젝트의 목표는 원하는 상품을 선택하고 실제 주문까지 이어질 수 있도록 구현하여 실제 서비스 운영까지 하는 것이다. 이번 글은 프로젝트에서 사용할 결제 API 선정 배경과 주문서 페이지에서 결제 페이지로의 연동을 위해 고민했던 내용을 다룬다.
결제 API 선정
주문서 페이지에서 주문할 상품과 수량을 선택하고 신용 카드/페이 등으로 실제 결제까지 할 수 있는 서비스를 개발하고 있다. 모든 기능을 직접 구현하기보다는 꼭 필요한 기능만 빠르게 개발하여 배포하기 위해 결제 기능은 이미 제공되는 API를 활용하기로 했다. 또한 직접 은행 계좌나 카드 업체에 출금 요청과 입출금 기능까지 구현하는 것은 금융 정책상으로도 어려울 것이라 생각했다.
국내에서 간편 결제 시스템으로 가장 많이 쓰이는 네이버페이, 카카오페이, 토스페이먼츠의 결제 API를 분석했고, 최종적으로 토스페이먼츠 API로 결정했다. 토스페이먼츠의 결제 API를 선택한 이유는 API 사용에 대한 문서화가 매우 잘 되어있었기 때문이다.
토스페이먼츠 개발자 센터 : https://docs.tosspayments.com/guides/v2/get-started
시작하기 | 토스페이먼츠 개발자센터
토스페이먼츠 결제 연동하는 클라이언트, 서버 개발자가 꼭 읽어야할 문서를 추천해드려요. 빠르게 개발을 시작해보세요.
docs.tosspayments.com
결제 서비스를 개발해본 적이 없어서 기본적으로 어떻게 동작하는지조차 배경 지식이 없었는데, 토스페이먼츠의 결제 위젯 연동 가이드 문서에 자세히 설명이 되어있어서 어렵지 않게 이해할 수 있었다.
가이드 문서의 예시 코드는 프로그래밍 언어와 프레임워크 별로 선택할 수 있어 프로젝트의 기술 스택에 맞게 선택할 수 있다.
제공하고 있는 예시 코드는 라인별로 토스페이먼츠의 결제 위젯의 어떤 부분에서 어떻게 동작하는지를 애니메이션으로 자세히 설명하고 있다. 이를 통해 코드를 쉽게 이해할 수 있다.
또한 결제가 이뤄질 때 사용자 - 클라이언트 - 서버 - 토스페이먼츠 API와의 데이터 연동 과정을 시퀀스 다이어그램으로 설명하고 있어, 결제 서비스를 개발해본 적이 없음에도 기본적인 결제 서비스의 데이터 흐름을 쉽게 파악할 수 있었다. 뿐만 아니라 결제 서비스를 개발할 때 주의해야할 점(결제 과정에서 서버에 저장해야하는 값(주문 ID, 결제 키)), 데이터 무결성을 위해 결제 요청전 데이터베이스에 주문 정보를 저장하고 비교)을 명확히 설명하고 있어 배경 지식이 없음에도 안정적으로 구축하는데 도움이 되었다.
이처럼 공식 문서로 API 사용 방식과 주의해야할 점을 친절하고 자세히 설명하고 있어 토스페이먼츠 API를 선정했다.
주문서 페이지와 결제 API 연동
결제 API를 선정하고 나서 주문서 페이지에서 결제 API를 연동하는 방안에 대해 고민했다. 토스페이먼츠는 결제 위젯을 제공하고 있고, 결제는 주문서 페이지에서 이 결제 위젯을 렌더링하여 이뤄진다.
주문서 페이지에서 결제 위젯을 렌더링하기 위한 과정은 3가지 방안을 고려했다. 먼저 가장 간단한 방법으로 주문서 페이지에 결제 위젯도 함께 구현하는 방안이 있다. 예를 들어 OrderForm.js라는 주문서 페이지를 렌더링하는 파일이 있다면, 이 파일에 결제 위젯을 렌더링하는 코드도 추가하는 것이다.
하나의 컴포넌트에서 로직을 관리해 구현이 가장 간단하다는 장점이 있다. 하지만 파일의 소스 코드와 페이지가 복잡해지고 리렌더링시 결제 위젯이 초기화되는 문제가 발생한다. 예를 들어 주문 상품과 수량을 선택해서 결제 페이지로 이동했다가 주문 수량을 바꾸기 위해 뒤로가면 결제 정보가 초기화된다. 이는 안좋은 사용자 경험을 유발한다.
또한 만약 사용자가 주문서 페이지를 거치지 않고 결제 페이지의 URL로 직접 들어온다면 주문 정보가 없는 상태로 결제 페이지에 들어오게 된다. 이는 서비스 에러나 결제 위젯이 뜨지 않는 등 문제가 발생할 수 있다.
두번째로는 프론트엔드에서 useNavigate를 통해 페이지를 이동하며 state를 넘기는 방안이 있다. (현재 화면은 React로 개발하고 있다.) 하지만 React의 state는 메모리에 저장되어 있는데, 웹 브라우저를 새로고침하는 경우 메모리가 초기화되어 state로 넘긴 데이터가 사라지게 된다. 즉 결제 위젯으로 넘어갔는데 주문 정보가 없어지는 상황이 발생할 수 있다. 또한 첫번째 방안과 마찬가지로 주문 정보가 없는 상태에서 결제 페이지의 URL로 직접 들어오는 문제가 발생한다.
또한 프론트엔드에서만 주문 정보를 담고 결제 API와 연동하는 것은 데이터 보안상 취약점이 될 수 있다. 주문 정보는 웹 브라우저에서 사용자가 조작할 수 있는데, 의도적으로 결제 직전에 주문서 페이지에서 담은 금액과 다른 금액으로 변경하여 결제 API를 호출해버릴 수 있다. 물론 토스페이먼츠 API에서 적절하게 처리를 하고 있겠지만, 데이터 위변조 위험이 있을 수 있고 결국 서비스 상에서도 주의할 필요가 있다.
프론트엔드에서만 주문 데이터가 흘러간다면 사용자의 주문 정보를 안전하게 저장할 수 없다. 또한 사용자의 주문이 실제로 이루어졌는지, 실패하거나 취소된다면 어느 지점에서 그렇게 됐는지 데이터 추적이 어렵다.
결제 데이터의 무결성을 보장하고 안전하게 결제 데이터를 처리하기 위해 서버와의 연동을 추가했다. 최종 설계 방안은 다음과 같다.
먼저 사용자가 주문서 페이지(OrderForm.js)에서 주문 상품 정보를 담고 결제를 진행한다. 이 때 바로 토스페이먼츠의 결제 API로 연동되는 것이 아니라 서버에 먼저 결제 데이터를 생성한다. 서버는 사용자의 결제 정보를 DB에 초기 상태로 저장한다.
서버가 초기 상태의 결제 데이터를 저장하면 클라이언트에게 생성된 결제 ID(Order Id)를 반환한다. 그 후 클라이언트는 이 결제 ID만 state에 담고 토스 결제 위젯(TossPaymentWidget.js)으로 이동한다. 토스 결제 위젯에서는 결제 ID를 기반으로 결제 정보를 서버에 요청해서 받아온다. 이렇게 받아온 결제 정보를 기반으로 토스페이먼츠에 결제위젯 렌더를 요청하고 최종적으로 결제위젯을 렌더링하여 결제를 진행한다.
안전하게 결제 데이터가 처리될 수 있도록 결제 정보는 항상 서버의 DB에 저장하고 DB에서 가져온다. 이를 통해 상태를 안전하게 유지하고, URL 직접 접근 방지와 state 소실, 리렌더링시 초기화 등을 방지하는 주문서 페이지와 결제 API의 연동 과정을 설계했다.
'시스템 디자인' 카테고리의 다른 글
[객체지향 프로그래밍] 양방향 의존성 개선하기 (0) | 2024.12.12 |
---|---|
[함수형 프로그래밍] 불변 객체와 장점과 단점 (1) | 2024.12.09 |
[객체지향 프로그래밍] -er, -or로 끝나는 이름을 사용하지 마세요 (0) | 2024.11.23 |
[시스템 디자인] 실습으로 배우는 선착순 이벤트 시스템 (번외) - DLT(DeadLetterTopic)을 이용한 메시지 Consume 재처리 (3) | 2024.09.11 |
[시스템 디자인] 실습으로 배우는 선착순 이벤트 시스템 (3/3) - 요구사항 변경과 쿠폰 발급 실패 예외처리 (0) | 2024.09.06 |