웹훅 본문의 서명이 유효해도 예전에 보냈던 요청을 누군가 다시 전달할 수 있습니다. 서명은 누가 보냈는지를 검증하지만 요청이 지금 처음 도착했다는 사실까지 보장하지는 않습니다. 시간 제한과 이벤트 중복 기록을 함께 사용해야 합니다.
원문 바이트로 서명을 검증한다
JSON을 파싱하고 다시 직렬화하면 공백과 필드 순서가 바뀌어 검증이 실패할 수 있습니다. 제공자가 지정한 원문 형식과 서명 헤더를 그대로 사용합니다.
서명 키 교체 중에는 현재와 이전 키가 잠시 함께 유효할 수 있습니다. 키 식별과 교체 기간을 정하고 잘못된 서명을 명확히 거절합니다.
시간창의 의미를 정한다
웹훅에 서명된 시각이 있다면 서버 시계와 비교해 지나치게 오래된 요청을 막을 수 있습니다. 시계 오차와 정상 전송 지연을 고려해 허용 범위를 정합니다.
시간창만으로 중복 실행을 막을 수는 없습니다. 유효 범위 안에서 같은 요청이 여러 번 도착할 수 있기 때문입니다.
이벤트 ID로 중복을 처리한다
제공자의 고유 이벤트 ID를 저장하고 이미 처리한 ID는 같은 결과로 응답합니다. 처리 중 동시에 들어오는 두 요청에 대해서도 원자적인 중복 방지가 필요합니다.
이벤트 전달 순서는 보장되지 않을 수 있습니다. 결제 완료와 취소 이벤트가 역순으로 도착할 때 현재 업무 상태를 확인해야 합니다.
가상 사례: 배송 상태의 오래된 재전송
어제의 '배송 중' 웹훅이 오늘 '배송 완료' 뒤에 다시 도착했다고 가정해 봅시다. 서명이 맞아도 현재 상태를 이전으로 되돌려서는 안 됩니다.
이벤트 시각과 상태 전이 규칙, 중복 ID를 확인한 뒤 처리하거나 무시합니다. 이 사례는 특정 제공자의 보장 범위를 뜻하지 않습니다.
거절과 재시도 경로를 시험한다
서명 실패, 오래된 시각, 중복 이벤트, 일시적 DB 장애에 대해 서로 다른 응답을 정합니다. 제공자의 재시도 정책과 맞지 않으면 불필요한 반복 요청이 쌓일 수 있습니다.
검증 실패 로그에는 서명 원문과 비밀키를 남기지 않습니다. 이벤트 ID와 원인 분류만으로 운영자가 문제를 추적할 수 있게 합니다.
현장에 적용할 때의 순서
- 원문 바이트와 서명을 검증한다
- 서명된 시각의 허용 범위를 정한다
- 이벤트 ID와 상태 전이를 확인한다
주의할 실패: 유효 서명이 있는 오래된 배송 상태도 다시 적용하면 현재 상태가 과거로 돌아간다.
관찰할 지표: 오래된 이벤트·중복·역순 도착을 각각 집계한다.
적용 전 체크리스트
- 서명 검증이 원문 바이트에 적용되는가
- 시간창과 이벤트 ID 중복 처리를 함께 쓰는가
- 역순 이벤트가 상태를 되돌리지 않는가
참고 자료
Stripe Webhooks 문서. 공식 문서는 Stripe 웹훅의 서명 검증과 이벤트 전달을 설명합니다. 시간창과 중복·역순 처리의 세부 정책은 제공자별로 확인해야 합니다.
이미지와 도식은 이해를 돕기 위한 개념 시각화입니다. 특정 고객의 실제 설비·데이터·화면을 재현한 것이 아닙니다.
#웹훅보안 #서명검증 #재전송방지 #멱등성 #API보안 #이벤트처리 #결제연동 #타임스탬프 #백엔드 #보안