제공 서비스
웹 보안 점검 소스코드 분석 (SAST) CRM 보안 진단 다크웹 유출 조회
요금제 스토어 블로그 파트너 마이페이지 무료 보안 점검
결제 보안 2026.04.25 · 조회 355

AI 코딩으로 만든 SaaS의 결제 연동, 빠지기 쉬운 보안 함정 5가지 (PortOne·토스 기준)

AI 코딩으로 결제 모듈을 빠르게 붙이면 가장 자주 누락되는 게 서버 사이드 검증입니다. PortOne(아임포트)·토스페이먼츠 연동 시 실제로 발생한 결제 우회 사례와 차단법을 정리했습니다.

AI 코딩 SaaS의 결제 모듈, 왜 자꾸 뚫리나

Claude·Cursor·Codex로 SaaS를 빠르게 만들 때 가장 마지막에 붙이는 게 결제 모듈입니다. PortOne(舊 아임포트), 토스페이먼츠, KG이니시스 등 PG사 SDK를 가져다 붙이면 일단 동작하긴 합니다. 문제는 "동작한다"와 "안전하다"는 다른 차원이라는 점입니다.

결제 보안 함정은 발견될 때까지 표면적으로 정상 동작합니다. 매출 누수, 무단 환불, 금액 위변조가 발생해도 로그에 흔적이 남지 않으면 모릅니다. 운영 6개월 후에야 "왜 매출이 안 맞지?" 하면서 알게 되는 경우가 많습니다.

함정 1: 결제 금액 클라이언트에서만 결정

가장 빈번한 패턴. 사용자가 결제 모달을 열 때 클라이언트가 금액을 PG사에 직접 전송합니다. 공격자는 결제 직전 JS를 수정해 9,900원 → 100원으로 바꿔서 결제합니다. PG사는 100원으로 승인하고, 서비스는 "결제 완료" 응답을 받습니다.

차단: PortOne v2 기준, 결제 후 반드시 /payments/{paymentId}를 호출해 실제 결제 금액과 서버 DB의 상품 가격을 비교해야 합니다. 일치하지 않으면 즉시 환불 API 호출.

# 잘못된 코드 (금액 검증 없음)
def confirm(request):
    payment_id = request.POST['paymentId']
    Order.objects.create(payment_id=payment_id, user=request.user, paid=True)

# 올바른 코드
def confirm(request):
    payment_id = request.POST['paymentId']
    res = portone.get_payment(payment_id)
    if res['amount']['total'] != Product.objects.get(id=res['orderName']).price:
        portone.cancel(payment_id, reason='금액 불일치')
        return HttpResponseBadRequest()
    Order.objects.create(...)

함정 2: 중복 승인 처리 누락

결제 완료 후 사용자가 새로고침하거나 confirm API가 두 번 호출되면, 서버에서 같은 결제를 두 번 처리해 권한이 두 번 부여되거나 더 큰 문제로 이어집니다.

차단: payment_id에 unique 제약 + transaction.atomic()으로 묶고, get_or_create 패턴으로 중복 시 기존 Order 반환.

함정 3: Webhook 검증 없이 신뢰

PortOne·토스는 결제 완료 시 서버에 webhook을 보냅니다. 이걸 그대로 신뢰하면 위조된 webhook으로 권한을 받을 수 있습니다.

차단:

  • Webhook 페이로드의 서명 헤더(x-portone-signature 등) 반드시 검증
  • Webhook 출처 IP whitelist (PG사 공식 IP만 허용)
  • Webhook 자체를 신뢰하지 말고 받은 즉시 PG API로 결제 정보 재조회

함정 4: 환불 권한 인증 부실

"내 결제 환불받기" 버튼이 사용자 인증 없이 orderId만 받아 환불 처리하면, 다른 사용자의 orderId를 추측해 환불 가능. UUID여도 로그·이메일·SNS에 노출되면 끝.

차단: 환불 API에서 order.user == request.user 또는 동일 이메일 검증 필수.

함정 5: 시크릿 키 프론트 노출

PG사 SDK 초기화 시 공개키(channel key)와 시크릿 키를 헷갈려 시크릿 키를 프론트엔드에 박아넣는 사례. PortOne v2의 경우 storeId·channelKey는 공개해도 되지만, API Secret은 절대 클라이언트에 노출 금지.

차단: 결제 호출은 프론트, 결제 검증·환불·조회는 100% 서버사이드.

토스페이먼츠 추가 주의사항

  • 테스트 시크릿 키와 라이브 시크릿 키 혼용 → 라이브에서 0원 결제 가능 (실제 사례 다수)
  • 결제 완료 후 /v1/payments/confirm 미호출 시 결제 미확정 상태 방치 → 자동 취소
  • 가상계좌 입금 통보 webhook 처리 누락 → 입금했는데 권한 없음 컴플레인

결제 모듈을 자가 점검하는 5분 체크리스트

  1. 결제 confirm 함수에 PG API 재조회 코드가 있는가?
  2. 금액 비교 로직이 서버에 있는가?
  3. payment_id가 DB에서 unique인가?
  4. Webhook 서명을 검증하는가?
  5. 환불 API가 사용자 본인 인증을 거치는가?

5개 중 1개라도 "아니오"라면 즉시 조치가 필요합니다.

지금 무료로 결제 모듈 보안 점검

CodeScan은 SaaS 결제 모듈을 포함해 21개 보안 항목을 30초 안에 자동 점검합니다. 시크릿 노출, 보안 헤더, SSL, 관리자 경로까지 한 번에 확인하세요.

지금 무료로 점검 시작 →

PortOne 토스결제 결제 연동 SaaS 보안 바이브코딩 결제 보안

내 사이트도 점검해보세요

CodeScan으로 보안 취약점을 무료로 점검할 수 있습니다.

무료 스캔 시작하기 →
🛒
추천 상품
웹서비스 런칭 전 보안 세팅
런칭 전에 반드시 해야 하는 보안 설정을 원격으로 직접 해드립니다. HTTPS, 환경변수 분리, 보안 헤더…
220,000원 150,000원

🔒 바이브코딩 보안 체크리스트 받기

바이브코딩 보안 체크리스트(PDF)를 무료로 받아보세요.