Originally published on integrationstars.com.
요약: 공유 상태(달력, 재고 수량, CRM 기록 등)를 확인한 다음 조치를 취할 때, 그 사이에 두 번째 실행이 개입하는 것을 막는 장치가 없다면 문제가 발생합니다. AI 단계는 이 시간 간격(window)을 밀리초 단위에서 몇 초 단위로 늘립니다. 해결책은 행동하기 전에 먼저 자원을 확보하고, 모든 비즈니스 액션에 Idempotency Key를 부여하며, 최종 쓰기 작업 직전에 실제 시스템을 다시 확인하는 것입니다. 더 나은 프롬프트나 더 엄격한 모델 또는 n8n 큐 모드는 이 문제를 해결해주지 못하며, 오히려 병렬성을 추가하여 레이스 컨디션을 더 발생하기 쉽게 만듭니다.
왜 이런 문제가 계속 발생하는가
이번 달 LinkedIn에서 공유된 인기 있는 n8n 예약 시스템 워크플로우를 본 최소 7명의 엔지니어들이 같은 질문을 했습니다.
에이전트 역시 자체적인 중복을 발생시킵니다: 모델은 한 실행(run)에서 동일한 예약 도구(booking tool)를 두 번 호출할 수 있고, 또는 시간 초과(timeout)로 인해 실제로 성공했던 호출을 워크플로우가 재시도하게 만들 수 있습니다. 이 둘 모두는 더 나은 프롬프트로 고칠 수 있는 방식으로 모델이 '실수'하는 것이 아닙니다. 이것들은 새로운 문을 통해 들어온 일반적인 분산 시스템 문제들입니다.
중복 및 병렬 실행의 원인
- 동시 요청: 두 명의 사용자, 두 개의 웹훅 호출(webhook calls), 두 번의 실행, 동일한 리소스
- 웹훅 재전송: Stripe와 같은 송신자들, 그리고 대부분의 웹훅 제공업체들은 충분히 빠른 응답을 받지 못하면 이벤트를 재전송합니다.
- 실패 시 재시도(Retry On Fail): n8n의 노드 수준 재시도는 첫 번째 시도가 이미 다른 쪽에서 성공했더라도 시간 초과 후 단계를 다시 실행합니다.
- 에이전트 도구 호출: 모델이 동일한 도구를 두 번 호출하거나, 또는 두 번째 에이전트 실행이 동일한 작업을 가져갑니다.
- 여러 워커를 사용하는 큐 모드: 설계상 더 많은 실행을 병렬로 처리합니다.
해결책: 먼저 소유권을 주장하고(claim first), 모든 액션에 키를 부여하며, 쓰기 전에 재확인하기
1. 행동하기 전에 리소스의 소유권을 주장하라 (Claim the resource before acting on it)
'확인 후 예약(check, then book)' 방식 대신, 워크플로우는 먼저 두 번째 소유권 주장을 거부하는 스토어에서 해당 슬롯을 **소유권 주장(claim)**하려고 시도합니다. 소유권을 주장하는 것 중 승리한 실행만이 계속 진행됩니다. Postgres에서는 이는 고유 제약 조건(unique constraint)에 대한 단일 삽입(insert)입니다:
INSERT INTO slot_claims (slot_id, execution_id)
VALUES ('2026-10-08T15:00', 'EXECUTION_ID')
ON CONFLICT (slot_id) DO NOTHING
...
(n8n에서 EXECUTION_ID는 현재 실행의 ID를 위한 표현식입니다.)
만약 행(row)이 반환되면, 이 실행이 해당 슬롯의 소유자입니다. 아무것도 반환되지 않으면, 다른 누군가가 먼저 가져갔다는 의미이므로
실제 행동(예: 예약 요청 ID, 주문 ID, 웹훅 이벤트 ID)마다 고유한 ID를 생성하고, 사이드 이펙트가 발생하기 전에 이를 기록하며, 모든 시도에서 먼저 해당 ID를 확인합니다. 웹훅이 재전송되거나, 재시도가 발생하거나, 에이전트가 도구를 다시 호출할 때, 두 번째 시도는 이미 키가 완료된 것을 감지하고 예약이나 청구가 중복되는 대신 멈춥니다. 다운스트림 API가 자체적인 Idempotency Key를 허용하는 경우(Stripe처럼), 이 키도 함께 전달해야 합니다.
3. 최종 쓰기 직전에 실제 시스템을 재확인하기
사용자가 주장한 테이블(claim table)은 이 워크플로우의 다른 실행으로부터 보호합니다. 하지만 달력 앱에서 누군가 같은 슬롯을 직접 예약하는 상황까지는 알지 못합니다. 따라서, 쓰기 직전에 최신 정보를 읽어오고(last read), 만약 해당 슬롯이 사라졌다면 명확한 실패 경로를 설정하는 것이 주장 테이블이 커버하지 못하는 부분을 보완해 줍니다.
에이전트가 결정하게 하고, 커밋은 하지 않게 하세요. 가장 깔끔한 구조는 AI를 중요한 섹션(critical section)에서 완전히 분리하는 것입니다. 에이전트는 사용자가 _무엇_을 원하는지 파악하고, 그 후 주장(claim), 재확인(re-check), 예약(book)을 수행하는 단순하고 결정론적인 하위 워크플로우에 구조화된 요청을 전달합니다. 느리고 예측 불가능한 부분은 레이스 조건이 발생하는 창문 바깥에 머물러야 합니다.
고객이 테스트하기 전에 어떻게 검증할 수 있나요
동일한 요청을 웹훅에서 한 번에 20번 실행해 보세요(짧은 스크립트나 부하 테스트 도구로 몇 초 만에 가능합니다) 그리고 예약된 건수를 세어봅니다. 그중 하나가 정답입니다. 그런 다음 단일 웹훅 이벤트를 세 번 재전송하고 두 번 이상 발생하지 않는지 확인하세요. 두 테스트 모두 몇 분밖에 걸리지 않지만, 일반적인 클릭 기반 테스트로는 절대 잡아낼 수 없는 실패를 포착해 줍니다.
구축이 필요하신가요?
Entech Solutions는 실제 트래픽에서도 견딜 수 있는 n8n 에이전트 워크플로우를 구축합니다: 우선 주장(claim-first) 동시성 처리, Idempotent 사이드 이펙트, 그리고 출시 전 부하 테스트까지 진행합니다. 저희 n8n AI 및 에이전트 워크플로우 설계 페이지, n8n 오류 처리 가이드, 또는 이미 운영 중인 워크플로우 검토를 위해 문의하기를 참고해 주세요.