중복·순서 역전 웹훅, 마지막 알림을 그대로 믿으면 안 되는 이유

이 카테고리 글 목록

전체글 보기

주문 변경 웹훅이 두 번 들어왔고, 취소 알림 뒤에 오래된 수정 알림이 도착했다. 마지막으로 도착한 내용을 저장하면 될까? 같은 전달의 재수신인지 먼저 구별하고, 전달 순서를 업무 상태의 순서로 취급하지 않아야 한다. 현재 상태 동기화가 목적이면 대상 ID로 원본을 조회해 맞추고, 개별 사건을 빠짐없이 처리해야 하는 업무라면 사건 이력과 처리 결과도 따로 보존한다.

이 글은 웹훅을 받아 AI 분류·알림·업무 갱신을 시작하는 담당자를 위한 설명이다. Shopify와 GitHub 공식 문서의 서로 다른 식별자 계약을 비교한다. 뒤의 주문 사례와 처리 제안은 가상이며 실제 상점이나 저장소에 이벤트를 보내 시험한 결과가 아니다.

전달 ID, 이벤트 ID, 업무 대상 ID를 섞지 않는다

전달 ID는 서비스가 정한 전달 단위를 식별한다. 이벤트 ID는 사건을 묶는 용도일 수 있다. 주문 ID나 작업 ID는 변경 대상 자체를 찾는다. 이 셋을 하나의 “요청 ID”로 합치면 같은 주문의 서로 다른 변경을 중복으로 지우거나, 같은 사건의 재전달을 새 업무로 실행하기 쉽다.

Shopify의 전달 검증 문서는 X-Shopify-Webhook-Id로 개별 전달의 중복을 구별하고, X-Shopify-Event-Id로 같은 상점 동작에서 나온 전달들을 연결한다고 설명한다. 같은 주제의 구독이 여럿이면 전달 ID는 달라도 이벤트 ID를 공유할 수 있다. 어떤 구독의 어떤 업무를 한 번 처리할지에 따라 중복 기준을 정해야 한다.

GitHub의 웹훅 지침에서는 재전달을 요청해도 X-GitHub-Delivery가 원래 전달과 같다고 안내한다. 이 계약을 다른 서비스의 헤더에 그대로 적용해서는 안 된다. 어떤 ID도 문서상 보장 없이 숫자·문자열 크기를 비교해 업무 버전으로 사용하지 않는다.

식별하려는 것 묻는 질문 그 값만으로 알 수 없는 것
전달 단위 이미 받은 전달을 다시 받았는가 업무 처리가 끝났는지, 사건이 최신인지
원래 사건 여러 구독의 전달이 같은 사건에서 나왔는가 모든 구독에서 같은 행동을 해야 하는지
업무 대상 어느 주문·티켓·작업의 변화인가 같은 대상의 서로 다른 변경이 중복인지
문서화된 버전·발생 시각 다른 변경과 어떤 관계인가 누락된 사건 유무나 전체 업무의 완전한 순서

가상 사례: 취소된 주문이 늦은 수정 알림으로 되살아난다

가상의 주문 시스템에서 주문 order-a의 배송지 수정과 주문 취소가 차례로 일어났다. 전송 지연으로 취소 알림이 먼저 도착하고, 수정 당시의 상태를 담은 알림이 나중에 도착했다고 하자. 이 흐름은 실제 Shopify 주문 상태나 특정 이벤트 이름을 재현한 것이 아니다.

수신한 순서대로 payload 전체를 저장하면 취소된 주문을 예전 진행 상태로 덮어쓸 수 있다. Shopify의 웹훅 개요도 같은 주제 안과 같은 자원의 다른 주제 사이에서 순서를 보장하지 않는다고 명시한다. 발생 시각 등 제공된 정보를 활용하도록 안내하지만, 이것이 모든 사건에 전역적인 순번이 있다는 뜻은 아니다.

이 가상 업무의 목적이 현재 주문 상태를 맞추는 것이라면 주문 ID로 원본을 읽어 현재 취소 상태를 확인한다. 늦은 알림은 과거 변화가 있었다는 신호로 보존하되 현재 상태를 되돌리는 근거로 사용하지 않는다. 조회 결과가 아직 불명확하면 상태 갱신과 후속 배송 안내를 보류하고 같은 대상의 확인을 이어간다. 이벤트마다 무조건 새 쓰기 요청을 만드는 방식은 피한다.

현재 상태만 맞추는 일과 사건을 처리하는 일을 구별한다

같은 평가 카드가 청록색과 노란색 두 목록으로 나뉘고 돋보기로 실패 카드를 살펴보는 삽화
같은 항목의 두 결과를 대조하는 기존 AI 생성 개념도. 알림에 담긴 상태와 원본에서 조회한 현재 상태를 같은 대상으로 비교하는 맥락으로 재사용했다. 웹훅 도착 순서나 실제 중복 제거 성능을 나타내지 않는다.

현재 상태 조회는 중요한 수단이지만 모든 업무를 대신하지는 않는다. 가격이 바뀌었다가 원래대로 돌아왔다면 현재 가격만 읽어서는 중간 변경을 알 수 없다. 사건마다 별도 처리가 필요한 업무라면 문서화된 사건 이력·복구 수단과 처리 결과를 보존해야 한다. 최종 상태가 같다는 이유로 모든 과거 사건을 처리했다고 보고할 수 없다.

Shopify는 웹훅 수신만 믿지 말고 놓친 데이터를 API로 맞추는 보완 절차도 안내한다. 운영에서는 사용하는 API의 조회 권한·제한과 업무에 필요한 신선도에 맞춰 범위를 정한다. 이 글은 새로운 고빈도 감시기를 제안하는 것이 아니다. 누락 시 어떤 대상과 기간을 다시 확인할지 정해 두는 것이 핵심이다.

받음, 처리 중, 처리 완료를 구별해야 중복을 막을 수 있다

작성자는 기존 수신·작업 기록에 출처와 계정 범위, 전달 식별자, 업무 대상, 처리 상태와 결과를 연결하는 방법을 제안한다. “ID가 있음”만 검사하면 처음 받은 이벤트를 처리하다 실패했는데 다음 재전달을 무조건 버리는 문제가 생긴다. 반대로 처리 뒤에만 ID를 적으면 동시에 들어온 두 요청이 모두 미처리로 판단할 수 있다.

따라서 같은 전달을 한 실행만 맡도록 원자적으로 선점하거나, 기존 작업 큐가 제공하는 중복 방지·동시 처리 통제를 활용한다. 처리 중인 기록과 완료 기록을 구분하고 실패한 처리의 이어받기를 정한다. 외부 알림 전송은 별도 효과이므로 로컬 완료 기록과 한 번에 묶이지 않을 수 있다. 수신 ID 기록만으로 외부 전송까지 정확히 한 번 실행된다고 보장하지 않는다.

확인한 상황 권장 판단 피해야 할 처리
같은 전달, 업무 처리 완료 근거 있음 중복 업무를 시작하지 않음 AI 분류·메일 전송을 다시 수행
같은 전달, 처리 중 또는 실패 기존 실행과 실제 효과를 확인해 이어받기 판단 ID가 있다는 이유로 완료 처리
같은 대상의 다른 사건, 순서 불명확 업무 목적에 따라 현재 원본 또는 사건 이력 대조 도착 순서나 불투명한 ID로 최신값 결정
전달 출처 검증 실패 또는 모르는 유형 계약에 맞게 거절·분리하고 허용된 처리만 수행 payload 내용을 그대로 실행 지시로 취급

수신 응답과 업무 완료도 나눈다. GitHub 지침은 빠른 응답과 백그라운드 처리를 제안하고 이벤트 종류와 action 확인을 요구한다. 안전하게 저장·인계된 범위에서 수신 확인을 보내고, 이후 업무 실패는 내부 처리 상태로 남길 수 있어야 한다. 출처 검증을 생략한 채 ID만 믿는 중복 제거는 충분하지 않다.

자주 묻는 질문

같은 주문 ID면 전부 중복으로 버려도 되나요?

주문 하나에도 여러 유효한 사건이 생긴다. 주문 ID는 대상 연결에 쓰고, 중복 판단은 서비스의 전달·사건 계약과 처리 업무에 맞춘다. 기본적인 중복 실행 문제는 AI 자동화 재시도의 중복 실행과 함께 볼 수 있다.

타임스탬프가 더 크면 무조건 최신인가요?

그 시각이 발생·발행·수신·자원 수정 중 무엇인지 먼저 확인한다. 같은 시각의 사건, 누락, 서로 다른 자원의 의존성도 있을 수 있다. 문서화된 순서 규칙 없이 시각 하나로 전체 업무 순서를 확정하지 않는다.

성공 웹훅과 취소 화면이 서로 다르면 무엇을 믿나요?

같은 작업인지와 현재 서비스의 최종 상태를 확인한다. 취소 요청과 완료의 경합에서는 요청 성공과 작업 종료를 나눈다. 애초 접수 상태를 완료로 표시하지 않으려면 202 뒤의 완료 확인 기준부터 맞추면 된다.

이 카테고리의 다른 글

전체글 보기

댓글 남기기