Stripe Webhook 테스트: 로컬 개발 가이드
요약
Stripe CLI를 사용하여 로컬 개발 환경에서 Webhook을 효율적으로 테스트하는 방법을 안내합니다. CLI 설치부터 인증, 로컬 서버로의 이벤트 전달, 그리고 보안을 위한 서명 검증 방법까지 단계별 가이드를 제공합니다.
핵심 포인트
- Stripe CLI를 통한 로컬 Webhook 테스트 환경 구축
- stripe listen 명령어로 로컬 엔드포인트에 이벤트 전달
- stripe trigger를 활용한 가상 결제 이벤트 생성
- 보안을 위한 Webhook 서명 검증(Signature Verification) 필수
Stripe webhooks는 성공적인 결제, 결제 실패, 구독 변경, 분쟁(disputes)과 같은 이벤트에 대해 귀하의 애플리케이션에 알림을 보냅니다. 이를 올바르게 처리하는 것은 매우 중요합니다. Webhook을 놓치면 주문 미이행이나 고객 혼란으로 이어질 수 있습니다.
과거에는 Webhook을 로컬에서 테스트하는 것이 고통스러운 작업이었습니다. 이제 Stripe는 괜찮은 도구(tooling)를 제공합니다. 이를 효과적으로 사용하는 방법을 소개합니다.
Stripe CLI 설정하기
Stripe CLI는 로컬 Webhook 테스트를 위한 주요 도구입니다. 먼저 설치하십시오.
macOS:
brew install stripe/stripe-cli/stripe
Windows:
scoop install stripe
Linux:
Stripe의 릴리스 페이지에서 다운로드하거나 apt/yum 저장소를 사용하십시오.
설치 후, 인증을 진행합니다:
stripe login
이 명령을 실행하면 Stripe 계정을 연결하기 위해 브라우저가 열립니다. 세션이 만료되므로 주기적으로 이 과정을 다시 수행해야 합니다.
Webhook을 Localhost로 전달하기
리스너(listener)를 시작합니다:
stripe listen --forward-to localhost:3000/webhooks/stripe
다음과 같은 출력이 표시됩니다:
Ready! Your webhook signing secret is whsec_abc123...
이 서명 비밀키(signing secret)를 저장하십시오. 서명 검증 (signature verification)을 위해 이 키가 필요합니다. 이는 대시보드의 Webhook 비밀키와는 다르며, 이 CLI 세션에 특화된 것입니다.
환경 변수에 설정하십시오:
export STRIPE_WEBHOOK_SECRET=whsec_abc123...
이제 Stripe CLI가 Webhook을 가로채서 귀하의 로컬 서버로 전달합니다.
테스트 이벤트 트리거하기
실제 결제를 진행하지 않고도 특정 이벤트를 트리거 (trigger specific events)할 수 있습니다:
stripe trigger payment_intent.succeeded
테스트할 일반적인 이벤트들:
# 결제 흐름 (Payment flow)
stripe trigger payment_intent.succeeded
stripe trigger payment_intent.payment_failed
...
각 트리거는 전달된 엔드포인트(endpoint)로 실제와 유사한 Webhook 페이로드(payload)를 전송합니다.
서명 검증 (Signature Verification)
항상 웹훅 서명(webhook signatures)을 검증해야 합니다. 자세한 내용은 Stripe의 서명 검증 가이드를 참조하세요. 여러 언어별 패턴은 다음과 같습니다:
Node.js:
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
app.post('/webhooks/stripe', express.raw({type: 'application/json'}), (req, res) => {
...
Go:
func handleWebhook(w http.ResponseWriter, r *http.Request) {
payload, err := io.ReadAll(r.Body)
if err != nil {
...
Python:
import stripe
from flask import Flask, request
...
원본 본문 문제 (The Raw Body Problem)
흔히 발생하는 실수: 서명 검증에는 **원본 요청 본문(raw request body)**이 필요합니다. 프레임워크가 핸들러 실행 전에 JSON을 자동으로 파싱하는 경우, 검증에 실패할 수 있습니다.
Express에서는 express.raw()를 사용하세요:
app.post('/webhooks/stripe', express.raw({type: 'application/json'}), handler);
다른 프레임워크의 경우, JSON 파싱 미들웨어가 작동하기 전에 원본 본문을 읽도록 하세요. Stripe 서명 오류 관련 문서에서 이 내용을 자세히 다루고 있습니다.
웹훅 실패 디버깅 (Debugging Failed Webhooks)
문제가 발생했을 때:
1. CLI 출력 확인
Stripe CLI는 요청/응답 세부 정보를 보여줍니다:
2026-01-25 10:23:45 --> payment_intent.succeeded [evt_123...]
2026-01-25 10:23:45 <-- [400] POST http://localhost:3000/webhooks/stripe
400 응답은 일반적으로 서명 검증 실패를 의미합니다.
2. 로그 확인
서명 검증 전후에 로깅을 추가하여 어디서 실패하는지 확인하세요.
3. 시크릿(Secret) 확인
CLI는 세션별 시크릿을 제공합니다. 올바른 것을 사용하고 있는지 확인하세요. Stripe 대시보드의 시크릿은 CLI를 통해 전달되는 웹훅에는 작동하지 않습니다.
4. 본문 파싱 문제 확인
때로는 캡처된 실제 페이로드 (payload)로 테스트하고 싶을 때가 있습니다. 다음과 같은 옵션이 있습니다:
Stripe 대시보드에서 재전송 (Replay):
Stripe 대시보드에서 Developers > Webhooks > 해당 엔드포인트(endpoint)로 이동하세요. 최근에 전송된 모든 웹훅을 다시 보낼 수 있습니다.
웹훅 캡처 서비스 사용:
ThunderHooks와 같은 서비스는 웹훅 수신함 역할을 합니다. Stripe의 목적지를 ThunderHooks URL로 한 번 설정해 두면, 노트북이 꺼져 있는 상태에서도 모든 웹훅이 캡처됩니다.
디버깅할 준비가 되었다면:
- 대시보드를 열어 Stripe가 보낸 정확한 페이로드 (payload)를 확인합니다.
- ngrok 또는 선호하는 터널링 (tunneling) 도구를 시작합니다.
- 웹훅을 터널 URL로 재전송 (replay)합니다.
- 버그를 수정하고 다시 재전송합니다. 동일한 웹훅을 사용하므로 Stripe 이벤트를 다시 트리거할 필요가 없습니다.
이는 특히 운영 환경 (production)의 문제를 디버깅할 때 매우 유용합니다. 실제 운영 환경의 웹훅을 캡처한 다음, 버그를 찾을 때까지 로컬 코드에 대해 재전송하여 테스트하세요.
웹훅 모킹 (Mock):
단위 테스트 (unit tests)를 수행할 때는 Stripe를 호출하지 마세요. 웹훅 페이로드 (payload)를 모킹 (mock)하고 핸들러 (handler) 로직을 직접 테스트하세요.
운영 환경 체크리스트 (Production Checklist)
라이브로 전환하기 전에 다음 사항을 확인하세요:
- 웹훅 엔드포인트 (endpoint)가 HTTPS인지 확인 (Stripe 필수 요구 사항)
- 운영 환경 시크릿 (production secret)을 사용하여 서명 검증 (signature verification)이 활성화되었는지 확인
- 핸들러 (handler)가 빠르게 2xx 응답을 반환하는지 확인 (< 30초)
- 중복 전달에 대한 멱등성 (idempotency) 처리 여부
- 디버깅을 위해 에러 로그에 이벤트 ID (event ID)가 포함되는지 확인
- 일시적인 실패에 대한 재시도 (retry) 처리 여부
- 주요 이벤트에 대한 모니터링/알림 (monitoring/alerting) 설정 여부
처리해야 할 일반적인 이벤트
최소한 대부분의 Stripe 연동에는 다음이 필요합니다:
| 이벤트 | 시점 | 작업 |
|---|---|---|
checkout.session.completed | 고객이 결제를 완료했을 때 | 주문 이행 (fulfill order) |
| ... |
전체 목록은 Stripe의 웹훅 이벤트 문서를 참조하세요.
결론
Stripe CLI를 사용하면 로컬 웹훅 테스트를 관리하기 쉬워집니다. 포워딩 (forwarding)을 설정하고, 이벤트를 트리거하며, 서명이 작동하는지 확인하고, 핸들러 (handler) 로직을 테스트하세요.
핵심은 결제 실패, 분쟁 발생(disputed charges), 만료된 카드와 같은 예외 경로(unhappy paths)도 테스트하는 것입니다. 이러한 부분들이 웹훅 처리 버그가 숨어 있기 쉬운 곳입니다.
리소스
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기