결제 시스템 구축하기

단순한 UI 연동을 넘어, 실제 돈이 오가는 과정의 전체 구조와 안전한 백엔드 검증 로직을 포함한 실전 구축 가이드를 안내해 드립니다. 적당히 흐름만 이해하시고, 해당 결제 사이트에서 사업자 등록 및 매장 등록하신 후, 아래 코드 프롬프트에 붙여넣어서 구현하세요. 그리고 카드사 검수 2~3주 정도 생각하시면 편합니다.

💡 핵심 추천: 수수료와 정산 속도를 고려할 때 토스페이먼츠페이플(Payple) 조합을 가장 추천합니다. 특히 페이플은 업계 후발주자로서 매우 공격적인 D+1 정산 혜택을 제공하여 초기 사업자의 자금 회전에 큰 도움이 됩니다.


1. PG사 선택 가이드 (왜 이 두 곳인가?)

대한민국에는 많은 결제 대행사(PG)가 있지만, 바이브 머니에서는 아래 두 곳을 우선순위로 추천합니다.

🔵 토스페이먼츠 (Toss)

  • 장점: 압도적으로 깔끔한 결제창 UX, 개발자 문서가 매우 잘 되어 있음
  • 수수료: 일반 카드 결제 약 2.0% ~ 3.4%
  • 추천: 사용자 경험(UX)이 브랜드 이미지에 중요한 경우

🔴 페이플 (Payple)

  • 장점: D+1 빠른 정산 (오늘 팔면 내일 입금), 낮은 수수료
  • 정산: 후발주자 혜택으로 자금 회전속도가 매우 빠름 (강력 추천)
  • 추천: 현금 흐름이 중요한 초기 스타트업 및 소상공인

2. 전체 구조 먼저 이해하기

결제는 프론트엔드 혼자서 처리할 수 없습니다. 보안을 위해 다음과 같은 5단계 흐름을 거칩니다.

  1. 결제 호출: 사용자가 결제 버튼을 클릭하고 프론트에서 SDK를 띄웁니다.
  2. 1차 승인: 사용자가 카드 정보를 입력하면 PG사에서 결제를 일시 승인합니다.
  3. 데이터 전달: PG사가 결제 키, 주문 번호, 금액을 프론트 주소로 넘깁니다.
  4. 최종 검증 (서버): Netlify Function(백엔드)이 PG사 서버에 "이 결제 진짜 맞냐?"라고 한 번 더 확인합니다.
  5. 완료: 검증이 끝나면 DB를 업데이트하고 사용자에게 완료 화면을 보여줍니다.

📌 핵심: 중요한 비밀 키와 검증 로직은 전부 Netlify Function(백엔드)에서 처리해야 안전합니다.

3. 공통 세팅 (Next.js + Netlify)

3-1. 폴더 구조

Netlify Functions를 사용하기 위해 아래와 같이 폴더를 구성한다고 가정합니다.

Project Structure
my-app/
  src/app/
    payment/page.tsx   # 결제 버튼 페이지
    success/page.tsx   # 결제 성공 페이지
  netlify/
    functions/
      toss-confirm.ts  # 토스 결제 승인용 함수
      payple-auth.ts   # 페이플 AUTH_KEY 발급
  netlify.toml         # Netlify 설정 파일

3-2. 환경 변수 (.env) 설정

클라이언트 키는 NEXT_PUBLIC_을 붙이고, 비밀 키는 서버에서만 사용하도록 설정합니다.

.env.local
# Toss
NEXT_PUBLIC_TOSS_CLIENT_KEY=발급받은_클라이언트키
TOSS_SECRET_KEY=발급받은_시크릿키

# Payple
NEXT_PUBLIC_PAYPLE_CST_ID=테스트_상점ID
NEXT_PUBLIC_PAYPLE_CUST_KEY=테스트_custKey
PAYPLE_SECRET_KEY=실서비스용_시크릿키

4. 상세 구현 가이드

01

프론트엔드: SDK 로드 및 결제 요청

토스페이먼츠 SDK를 동적으로 로드하고 결제창을 띄우는 예시입니다.

src/app/payment/page.tsx
const handlePay = async () => {
  const tossPayments = await loadTossPayments(clientKey);
  
  await tossPayments.requestPayment('카드', {
    amount: 50000,
    orderId: 'ORDER-' + Date.now(),
    orderName: '바이브 머니 구독',
    successUrl: window.location.origin + '/success',
    failUrl: window.location.origin + '/fail',
  });
};
02

백엔드: Netlify Function 승인 검증

PG사로부터 전달받은 정보를 서버에서 최종 승인하는 핵심 로직입니다.

netlify/functions/toss-confirm.ts
export const handler: Handler = async (event) => {
  const { paymentKey, orderId, amount } = JSON.parse(event.body);
  const secretKey = process.env.TOSS_SECRET_KEY;
  const auth = Buffer.from(secretKey + ":").toString('base64');

  const resp = await fetch('https://api.tosspayments.com/v1/payments/confirm', {
    method: 'POST',
    headers: {
      Authorization: `Basic ${auth}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ paymentKey, orderId, amount }),
  });

  return { statusCode: 200, body: JSON.stringify(await resp.json()) };
};

5. 왕초보가 특히 주의해야 할 점

  • 테스트 모드 vs 실운영 키 분리: 토스는 테스트 키와 라이브 키가 완전히 다르며, 페이플 또한 호출 도메인 자체가 다릅니다. 배포 전 반드시 확인하세요.
  • 중요 키 보안: Secret Key는 절대로 프론트엔드 코드에 두지 마세요. 오직 Netlify Function 환경 변수에서만 관리해야 합니다.
  • 금액 검증: 사용자가 조작할 수 있는 프론트엔드 금액 대신, 서버에서 DB에 저장된 주문 금액과 대조하여 다를 경우 승인을 거절해야 합니다.
  • 결제 중복 처리 방지: 새로고침 등으로 결제가 두 번 처리되지 않도록, DB에 주문 상태 컬럼을 두고 '이미 결제됨'인 경우 승인 요청을 차단하세요.

6. 공식 개발자 문서 링크

더 구체적인 API 명세나 최신 기능은 아래 공식 문서를 참고하세요.

방향키로 이동