셀프호스팅 AI 도구를 고객에게 팔 때 — n8n의 내부 업무 목적과 Open WebUI의 50명이 갈리는 자리
셀프호스팅 AI 도구 다섯 개의 라이선스 원문을 직접 받아 읽었어요. n8n은 용도로, Dify는 구성으로, Open WebUI는 브랜딩 제거에 인원 임계로 선을 그어요. 선의 종류가 서로 달라요.
AI 기술을 누구나 쉽게 활용할 수 있도록 실전 가이드를 작성합니다. ChatGPT, Claude, AI 자동화, SEO 분야를 전문으로 다룹니다.
자동화를 켜 두고 며칠 지나면 이런 일이 생겨요. 팀 채널에 같은 알림이 두 번 올라오고, 시트를 열어 보면 같은 행이 두 줄이고, 고객에게 나간 메일함을 뒤져 보니 같은 안내가 두 번 나가 있어요. 로그를 보면 실행 기록도 두 개예요.
먼저 결론부터 말할게요. 이건 대개 트리거가 두 번 깨어나서 생긴 일이 아니에요. Zapier의 경우 폴링 트리거에 붙는 중복 제거 장치를 공식 문서에 명시해 두었고, 그 장치가 같은 항목을 두 번 집어 오는 상황을 막아요. 문제는 그 장치가 막아 주는 범위가 생각보다 좁다는 데 있어요. 자동화 한 개의 안쪽만 보거든요. Zapier 도움말이 중복 데이터의 원인으로 적어 둔 목록을 봐도 겹치는 자동화와 의도치 않은 고리와 타임아웃이 나란히 들어가 있어요. 그래서 겹치는 자동화, 실패 뒤의 자동 재시도, 액션이 자기 트리거를 다시 건드리는 고리, 이 세 자리에서 중복이 새어 나와요.
아래에서는 Zapier와 Make와 n8n의 공식 문서에 실제로 적힌 기능 이름과 한도값만 근거로, 중복이 갈라지는 지점을 먼저 나누고 막는 방법 다섯 가지를 순서대로 정리했어요.
![]()
같은 증상처럼 보여도 원인이 다르면 손댈 자리가 완전히 달라져요. 그래서 고치기 전에 세 가지만 확인해 보세요.
첫째, 두 건이 완전히 같은 시각에 왔는지 아니면 시간 차가 있는지예요. 거의 같은 시각이면 겹치는 자동화 쪽을, 몇 분에서 몇 시간 뒤에 왔다면 자동 재시도 쪽을 먼저 의심하는 게 맞아요.
둘째, 두 건에 실린 내용이 완전히 같은지 아니면 한쪽이 갱신된 값인지예요. 값이 조금 다르면 새 항목이 아니라 갱신을 새 항목으로 읽고 있을 가능성이 있어요.
셋째, 두 번에서 멈췄는지 아니면 계속 늘어나는지예요. 계속 늘어나면 고리가 생긴 거고, 이건 다른 셋과 처방이 완전히 달라요.
| 관찰한 증상 | 가장 먼저 볼 곳 | 이 글에서 다루는 방법 |
|---|---|---|
| 거의 같은 시각에 같은 내용 두 건 | 같은 데이터를 보고 있는 자동화가 두 개 이상인지 | 세 번째 방법 |
| 몇 분에서 몇 시간 뒤에 두 번째 건 | 실패한 단계의 자동 재시도 설정 | 네 번째 방법 |
| 한쪽만 값이 조금 다름 | 트리거가 새 항목과 갱신을 어떻게 구분하는지 | 첫 번째 방법 |
| 건수가 계속 늘어남 | 액션이 자기 트리거를 다시 건드리는지 | 다섯 번째 방법 |
| 위 어디에도 안 맞음 | 처리 기록을 남기는 장부가 아예 없는 상태 | 두 번째 방법 |
Zapier 도움말은 진단 순서도 구체적으로 적어 두었어요. 실행 기록에서 여러 레코드에 걸쳐 중복된 고유 식별자, 그러니까 ID나 이메일 주소 같은 값으로 해당 실행들을 검색해 보라고요. 이렇게 하면 문제가 자동화 하나에서 생긴 것인지 여러 개에서 생긴 것인지 가릴 수 있다고 덧붙여요. 순서가 반대면 고생해요. 원인을 모른 채 조건부터 만지면 멀쩡히 와야 할 건까지 같이 막히거든요.
손을 대기 전에 쓰는 도구가 어디까지 해 주는지부터 알아야 해요. Zapier 개발자 문서에는 deduplication 이라는 이름의 문서가 따로 있어요. 첫 문단이 이렇게 시작해요. Zapier가 통합에 들어오는 트리거 데이터를 자동으로 중복 제거하므로, Zap 워크플로가 같은 데이터로 여러 번 실행되지 않는다고요.
기준이 되는 값은 정해져 있어요. 같은 문서는 기본적으로 키가 id 인 필드를 기본 키로 쓴다고 적어요. 작동 순서도 적혀 있어요. 자동화를 처음 켜면 Zapier가 기존 데이터를 한 번 불러와 각 id 필드를 데이터베이스에 저장해 두고, 자동화를 끄면 그 목록이 지워진다고요. 이후 켜져 있는 자동화는 정해진 간격으로 확인하면서 예전에 본 id들과 대조해 새 항목에만 반응하고 본 id 목록을 갱신해요.
문서가 예시로 든 상황이 이해에 도움이 돼요. 할 일 목록을 돌려주는 API가 있고 이미 6번과 7번을 본 상태에서 8번이 새로 생기면, 다음 확인 때 API는 세 개를 전부 돌려주지만 8번만 새 항목으로 잡혀요. 문서는 이렇게 정리해요. 중복 제거의 핵심은 나머지 id인 6번과 7번은 이전 확인에서 이미 봤으므로 무시된다는 점이라고요. 그리고 바로 다음 줄에 조건을 붙여요. 중복 제거가 작동하려면 id 필드가 항상 제공돼야 하고 결과에 담긴 모든 항목 사이에서 고유해야 한다고요.
여기까지가 도구가 해 주는 부분이에요. 그런데 이 장치에는 범위 제한이 하나 붙어 있어요.
Zapier 도움말은 이 점을 따로 상자에 넣어 두었어요. 같은 폼을 트리거로 쓰는 Zap 워크플로처럼 같은 트리거를 쓰는 자동화가 두 개 이상 있으면 전부 트리거되며, 중복 제거 시스템은 같은 Zap 안에서만 검사한다고요.
그래서 예전에 만들어 두고 잊은 자동화가 같은 데이터를 보고 있으면 알림은 그냥 두 번 와요. 각 자동화 입장에서는 둘 다 처음 보는 항목이니 중복이 아니거든요.
같은 문서에 하나 더 있어요. 인스턴트 트리거는 앱이 새 데이터만 보내기 때문에 중복 제거를 쓰지 않는다고 적혀 있어요. 웹훅으로 갈아탔더니 이 장치가 사라졌다는 뜻이 아니라 애초에 그 층에서는 쓰이지 않는다는 뜻이에요. 웹훅과 폴링이 어떻게 다른지는 자동화가 바로 안 도는 이유를 정리한 글에 따로 정리해 두었어요.
액션 쪽 사정도 알아 둘 만해요. 같은 도움말은 액션 단계에서 중복 데이터를 어떻게 다루는지는 그 단계에 쓰인 앱에 달렸다고 적고, 앱이 보이는 동작을 네 가지로 나눠 두었어요. 중복 데이터를 그대로 만드는 경우, 오류를 돌려주는 경우, 기존 데이터를 갱신하는 경우, 그리고 드물게 중복을 그냥 무시하는 경우예요. 마지막 항목의 설명이 특히 신경 쓰여요. 드문 경우지만 앱이 Zapier가 만들려는 중복을 무시할 수 있는데, 이때는 중복 데이터도 안 생기고 오류 메시지도 오지 않는다고요. 조용히 지나간다는 뜻이라 로그만 보고 있으면 알기 어려워요.
도구의 장치가 못 막는 자리를 메우는 가장 확실한 방법은 오래된 것이에요. 처리한 건의 식별자를 어딘가에 적어 두고, 일을 하기 전에 그 장부를 먼저 조회하는 거예요. 이미 있으면 그 자리에서 멈추고, 없으면 적고 진행해요. 프로그래밍 쪽에서 멱등성이라고 부르는 성질을 흉내 내는 거예요.
원리는 결제 API 문서가 가장 깔끔하게 적어 두었어요. Stripe API 레퍼런스는 멱등성을 이렇게 정의해요. 같은 작업을 실수로 두 번 수행하지 않으면서 요청을 안전하게 재시도할 수 있도록 API가 멱등성을 지원하며, 객체를 만들거나 갱신할 때 멱등키를 쓰면 연결 오류가 나더라도 두 번째 객체가 생기거나 갱신이 두 번 되는 위험 없이 요청을 다시 보낼 수 있다고요.
동작 방식도 같은 문서에 적혀 있어요. 어떤 멱등키에 대해서든 첫 요청의 응답 상태 코드와 본문을 저장해 두고, 성공했든 실패했든 상관없이 같은 키로 들어온 뒤 요청에는 저장해 둔 그 결과를 그대로 돌려준다고요. 500 오류까지 그대로 돌려준다는 말이 함께 적혀 있어요.
키를 어떻게 만들지에 대한 조건도 있어요. 키는 클라이언트가 만들고, 만드는 방법은 자유지만 충돌을 피할 만큼 무작위인 값을 권한다고 적혀 있어요. 문서는 V4 UUID 나 그만한 무작위 문자열을 제안하고, 키 길이는 최대 255자라고 밝히고요. 그리고 주의 하나가 붙어요. 이메일 주소나 개인 식별자 같은 민감한 데이터를 멱등키로 쓰지 말라고요.
키의 수명에 대한 서술도 실무에 바로 쓸 만해요. 최소 24시간이 지난 키는 시스템에서 자동으로 지울 수 있고, 원본이 지워진 뒤 같은 키를 다시 쓰면 새 요청을 만든다고 적혀 있어요. 즉 장부는 영원히 남는 장치가 아니에요. 며칠 뒤에 같은 항목이 다시 들어오면 새것으로 처리될 수 있다는 뜻이니, 얼마나 오래 기억해야 하는지를 정해 놓고 도구를 골라야 해요.

무엇을 키로 삼을지가 이 방법의 전부예요. 고르는 기준은 두 개예요. 항목마다 달라야 하고, 같은 항목이면 몇 번을 봐도 같아야 해요. 주문번호나 접수번호처럼 원래 시스템이 붙여 주는 번호가 있으면 그게 제일 낫고, 없으면 여러 값을 이어 붙여 만들어요. Zapier 개발자 문서가 갱신 트리거를 다루는 방식이 정확히 이 조립이에요. 갱신 시각을 id와 합쳐 새 키를 만들어 Zapier가 새 갱신을 새 항목으로 인식하게 하라고 적고, 예시 코드에서 원래 id 값을 따로 보존한 뒤 id를 합친 값으로 바꿔요. 원래 ID를 살려 두는 이유도 밝혀 두었어요. 검색을 하거나 레코드끼리 연결하는 등 다른 용도로 쓸 수 있게 하기 위해서라고요.
장부를 처음부터 손으로 만들 필요는 없어요. 도구마다 준비된 자리가 있어요. 다만 이름과 동작이 제각각이라 문서에 적힌 이름 그대로 찾는 편이 빨라요.
n8n에는 Remove Duplicates 라는 이름의 노드가 있어요. 공식 문서는 이 노드가 두 종류를 처리한다고 적어요. 한 실행 안에서 모든 필드 또는 일부 필드가 동일한 항목, 그리고 이전 실행에서 본 항목과 동일하거나 그것을 넘어서지 못하는 항목이에요. 동작 모드는 세 가지이고 이름이 각각 Remove Items Repeated Within Current Input, Remove Items Processed in Previous Executions, Clear Deduplication History 예요.
중복 알림을 막는 데 쓰는 건 두 번째 모드예요. 여기서 정할 것이 세 가지 있어요. 무엇을 새것으로 볼지를 정하는 Keep Items Where, 무엇을 키로 볼지를 정하는 Value to Dedupe On, 그리고 기록을 어디에 둘지 정하는 Scope 예요. Keep Items Where 의 선택지는 Value Is New 와 Value Is Higher than Any Previous Value 와 Value Is a Date Later than Any Previous Date 세 개이고, 문서는 고른 선택지에 따라 키에 요구되는 형식이 달라진다고 적어요. Value Is New 를 쓰면 고유 ID를 가진 필드이거나 필드 조합이어야 하고, 날짜 기준을 쓰면 ISO 형식의 날짜 값을 가진 필드여야 한다고요.
Scope 는 기본값이 Node 인데, 이 값을 쓰면 같은 워크플로에 있는 다른 Remove Duplicates 인스턴스와 따로 기록을 저장해요. Workflow 로 바꾸면 Workflow 범위를 쓰는 다른 Remove Duplicates 노드들과 기록을 공유하고요. 그리고 놓치기 쉬운 한도가 하나 있어요. Keep Items Where 를 Value Is New 로 골랐을 때 나타나는 History Size 옵션인데, 문서는 기본값으로 n8n이 10,000개 항목을 저장한다고 적어요. 오래된 항목이 다시 들어와 새것으로 처리됐다면 이 한도부터 확인해 보세요.
Make 쪽은 접근이 달라요. 공식 문서가 안내하는 방식은 데이터 스토어예요. 데이터 스토어를 만들 때 데이터 구조를 비워 두는 선택지가 있는데, 문서가 그 용도를 직접 밝혀요. 데이터 구조를 고르지 않으면 데이터베이스에 기본 키만 들어가며, 키만 저장하고 특정 키가 데이터베이스에 있는지 없는지만 알고 싶을 때 이런 유형이 유용하다고요. 중복 방지 장부에 딱 맞는 설명이에요.
실제 잠금은 모듈 설정에서 걸려요. Add/replace a record 모듈의 Key 필드는 고유 키를 넣는 자리이고, 비워 두면 키가 자동 생성된다고 적혀 있어요. 그 아래 Overwrite an existing record 옵션은 기존 레코드를 덮어쓸 때 켜는 자리고요. 핵심은 이 옵션을 꺼 두었을 때의 동작이에요. 같은 문서가 이렇게 적어요. 같은 이름으로 이미 데이터 스토어에 있는 레코드를 추가하려 하는데 Overwrite an existing record 옵션이 꺼져 있으면 모듈이 오류를 던진다고요. 즉 키를 먼저 쓰게 해 두면 두 번째 시도는 그 자리에서 멈춰요. 키 존재 여부만 묻고 싶다면 Check the existence of a record 모듈이 따로 있어서, 지정한 데이터 스토어에 레코드가 있으면 true를, 없으면 false를 돌려줘요.
Zapier에서 같은 일을 하려면 Storage by Zapier 를 써요. 도움말은 이 도구를 서로 다른 실행이나 서로 다른 자동화 사이에 데이터를 저장하고 꺼내 쓰는 도구라고 설명하고, 이 도구를 쓰는 것은 태스크 사용량에 포함되지 않는다고 덧붙여요. Get Value 단계에는 값을 찾지 못했을 때 이 단계를 성공으로 볼 것인지 고르는 항목이 있어서, 없을 때 진행하고 있을 때 멈추는 흐름을 여기서 갈라요.
Storage by Zapier 문서의 한도 절에 적힌 값은 이래요. 키는 최대 32자이고 스토리지 계정당 최대 500개이며, 값은 최대 1MB(1,000,000바이트)이고, 2개월 동안 사용하지 않으면 키를 삭제한다고요. 시크릿은 최대 36자이고 UUID 형식을 써야 하며, 같은 시크릿을 쓰는 스토리지 동작은 같은 저장소를 쓴다고도 적혀 있어요.
Make 데이터 스토어 쪽 규칙은 성격이 달라요. 총 데이터 저장 용량이 플랜의 작업 수에 연동돼서 작업 1,000개마다 1MB로 계산되고, 데이터 스토어 하나의 최소 크기가 1MB라 새로 만들려면 최소 1MB의 여유가 있어야 한다고 적혀 있어요. 한 조직이 가질 수 있는 데이터 스토어는 플랜과 무관하게 최대 1,000개이고, 레코드 하나의 최대 크기는 15MB예요. 위 수치는 2026년 8월 초에 각 공식 문서에서 확인한 값이에요.
같은 문서가 장기 보관용으로는 다른 곳을 권해요. Storage by Zapier 도움말은 추가 저장이나 장기 저장이 필요하면 스프레드시트 앱이나 데이터베이스 앱을 쓰라고 안내해요.
장부를 따로 두기 부담스러우면 받는 쪽 앱에게 물어보는 방법이 있어요. 같은 것이 이미 있는지 먼저 찾아보고 없을 때만 만드는 액션이에요.
Zapier 도움말은 중복 데이터가 생겼을 때의 처방 중 하나로 이걸 적어요. 앱이 지원한다면 찾거나 만드는 액션을 써서 새 데이터가 이미 존재하지 않을 때만 만들어지게 하라고요. 예시도 함께 들어요. HubSpot의 Find or Create Deal 액션을 쓰면 기존 거래를 검색하고 찾지 못했을 때만 새로 만든다고요. 앱마다 이름은 다르지만 찾기와 만들기가 한 단계로 묶인 액션은 흔해요.
겹치는 자동화 문제도 여기서 같이 정리해요. 같은 문서는 여러 자동화가 같은 트리거 데이터를 쓰고 있을 때의 처방을 두 가지로 제시해요. 조건에 맞지 않으면 진행하지 않도록 필터를 넣는 방법과, 결과가 다른 여러 자동화를 Paths 로 하나에 합치는 방법이에요.
그리고 트리거 설정 자체를 좁히는 방법도 함께 안내해요. 문서는 앱 쪽에서 미리 걸러 Zapier에 닿기 전에 데이터를 줄이는 방법을 권하고, 트리거에 걸러 낼 수 있는 필드가 있는지 아니면 대체할 다른 트리거가 있는지 살펴보라고 적어요. Google Sheets의 새 행 또는 갱신된 행 트리거에서는 행의 어떤 변경에나 반응하는 대신 어느 열에서 반응할지 지정할 수 있다는 예를 들고요. 알림을 받는 창구 자체를 나눠 두는 것도 도움이 되는데, 그 방법은 카카오톡 나에게 보내기로 알림 채널을 만드는 글에서 따로 다뤘어요.
시간 차를 두고 두 번째 건이 왔다면 여기가 원인일 가능성이 높아요. Zapier 도움말은 중복 데이터의 원인 다섯 가지를 목록으로 적어 두었는데, 그중 마지막이 타임아웃이에요. 설명은 이래요. 실행 기록에 timed out 오류 메시지가 있다면, 오류 난 액션을 재실행하려는 시도들이 중복 데이터를 만들고 있을 수 있다고요.

재실행이 어디까지 다시 도는지를 알아야 판단이 서요. Zapier 문서는 실행 기록에서 하는 재실행과 편집기에서 하는 전체 재실행을 나눠서 설명해요. 앞쪽은 오류로 멈춘 단계만 다시 돌아요. 문서의 예시가 명확해요. 폼 제출로 시작해 메일을 보내고 시트에 행을 추가하는 자동화에서 메일은 성공하고 시트 행 추가가 실패했다면, 재실행할 때 트리거도 메일 단계도 다시 돌지 않고 시트 행 추가만 다시 시도한다고요.
뒤쪽은 성격이 완전히 달라요. 편집기에서 전체를 재실행하면 실행 기록에 별도로 나타나는 새 실행이 만들어지고, 트리거부터 모든 단계를 상태와 상관없이 다시 돌려요. 문서는 사용량 이야기까지 덧붙여요. 전체 재실행은 새 실행으로 간주되어 이미 성공했던 단계도 이전 실행에서 이미 집계됐더라도 사용량에 포함된다고요. 이미 성공한 단계를 다시 돌린다는 말은, 그 단계가 알림을 보내는 단계였다면 알림도 다시 나간다는 뜻이에요.
자동으로 도는 쪽이 Autoreplay 예요. 문서는 최대 5회까지 재실행을 시도한다고 적고, 간격이 시도할 때마다 벌어진다며 표를 붙여 두었어요. 오후 1시에 처음 실패한 경우를 예로 들면 첫 시도는 최초 트리거 이벤트로부터 5분 뒤인 1시 5분, 두 번째는 직전 시도로부터 30분 뒤인 1시 35분, 세 번째는 1시간 뒤인 2시 35분, 네 번째는 3시간 뒤인 5시 35분, 다섯 번째는 6시간 뒤인 11시 35분이에요. 문서는 마지막 재실행이 첫 오류로부터 약 10시간 35분 뒤에 일어난다고 정리해요.
여기서 함께 알아 둘 것이 있어요. 같은 문서가 마지막 자동 재실행 시도가 실패하기 전까지는 오류 알림 메일을 보내지 않는다고 적고 있어요. 그러니 알림이 안 왔다고 문제가 없는 게 아니에요. 조용한 사이에 재시도가 돌고 있을 수 있어요. 필터와 경로 단계는 실행 기록에서 하는 재실행 대상이 아니라는 서술도 있어요. 앞 단계를 다시 돌려 조건이 바뀌었을 상황에서도 다시 돌지 않는다고 적혀 있으니, 필터로 막는 설계를 재실행과 함께 쓸 때는 이 점을 감안해야 해요.
Make에서 같은 자리는 미완료 실행이에요. 공식 문서는 미완료 실행이 기본적으로 꺼져 있고, 저장하려면 시나리오 설정에서 Store incomplete executions 옵션을 켜야 한다고 적어요. 처리 방법은 자동 재시도와 수동 해결과 삭제 세 가지고요. 자동 재시도 문서는 지원되는 오류 유형만 자동으로 다시 시도한다고 밝히면서, 그 밖의 유형은 기본적으로 자동 재시도하지 않는다고 적어요. 같은 시나리오에서 동시에 도는 재시도는 3개로 제한되는데, 문서는 그 이유를 한꺼번에 많은 미완료 실행을 재시도할 때 뒤따라오는 요청량 초과 오류를 막기 위해서라고 설명해요.
에러 핸들러 쪽에도 자동 완료 설정이 있어요. Retry 에러 핸들러 문서는 자동 완료를 예로 두면 지정한 시도 횟수와 간격에 따라 시스템이 자동으로 재시도한다고 적고, 예시로 세 번 더, 15분마다를 들어요. 아니오로 두면 오류가 해결할 때까지 미완료 실행 탭에 남아 있고요. 그리고 전제 조건이 하나 붙어요. Retry 에러 핸들러를 시나리오에서 쓰려면 설정에서 미완료 실행을 먼저 켜야 한다고요. Make 에러 핸들러를 어떻게 조합하는지는 Make 시나리오 에러 모니터링을 정리한 글에 더 자세히 있어요.
결국 이 방법의 요지는 재시도를 끄라는 게 아니에요. 재시도는 일시적 오류를 넘기는 데 필요해요. 대신 재시도되는 단계가 두 번 실행돼도 결과가 같아지게, 즉 첫 번째 방법의 장부를 그 앞에 두라는 뜻이에요.
건수가 두 번에서 멈추지 않고 계속 늘어난다면 이건 다른 문제예요. Zapier 도움말은 이 상태를 고리라고 부르고, 생기는 형태를 세 가지로 정리해요. 한 자동화의 액션이 다른 자동화를 트리거하고 그 두 번째 자동화의 액션이 다시 첫 번째를 트리거하는 경우, 한 자동화의 액션이 그 자동화 자신을 트리거하는 경우, 그리고 새 항목 또는 갱신된 항목 트리거를 쓰면서 자동화가 자기를 트리거한 바로 그 레코드를 갱신하는 경우예요.
세 번째가 특히 눈에 띄지 않게 생겨요. 문서의 예시는 Airtable의 새 레코드 또는 갱신된 레코드 트리거와 같은 테이블의 레코드 갱신 액션 조합이에요. 자동화가 자기를 트리거한 레코드를 갱신하면 그 갱신이 다시 자동화를 트리거해 끝없는 고리가 만들어진다고 적혀 있어요.

메일 자동응답도 같은 구조가 될 수 있어요. 문서는 새 메일에 답장을 보내는 자동화에서 트리거가 보낸편지함을 포함한 모든 폴더를 검색하면 자동화 자신의 답장이 다시 자동화를 트리거한다고 적고, 처방으로 새 메시지 대신 새 대화 트리거를 쓰고 검색 조건에 받은편지함 조건을 넣어 보낸 메일을 제외하라고 안내해요.
이미 돌고 있다면 순서가 있어요. 문서는 고리가 도는 자동화를 즉시 끄고, 두 개가 서로 물려 있으면 둘 다 끄라고 적어요. 그다음 실행 기록에서 고리가 멈췄는지 확인하고 사용량을 점검하라고 이어져요.
막는 방법은 두 단계예요. 문서의 문장을 그대로 옮기면, 고리를 만드는 액션에 고유한 데이터를 추가한 다음 그 데이터를 필터 단계에서 써서 고리를 막으라는 거예요. 첫 단계에서는 이 자동화가 이미 한 번 처리했다는 표시가 될 고유한 값을 액션에 넣어요. 문서는 원래 흐름에 영향을 주지 않는 필드를 쓰라며 메모나 설명 필드를 예로 들고, 값은 원래 업무에서는 나타나지 않을 값으로 고르라고 덧붙여요. 두 번째 단계에서는 고리를 만드는 액션 앞에 필터를 넣고, 그 값이 발견되면 진행하지 않게 설정해요. 문서는 필터 조건으로 포함하지 않음을 쓰라고 예시를 들어요.
이 방식이 첫 번째 방법과 닮았다는 점을 눈여겨보세요. 둘 다 처리했다는 표시를 데이터에 남기고 그 표시를 보고 진행 여부를 가르거든요. 다른 점은 표시를 두는 자리예요. 첫 번째 방법은 별도 장부에 두고, 이 방법은 데이터 자체에 둬요. 받는 쪽 앱에 쓸 만한 자유 입력 필드가 있으면 이쪽이 더 간단해요.
표에 넣은 이름은 전부 각 도구의 공식 문서에 적힌 표기 그대로예요. 확인하지 못한 칸은 지어내지 않고 닫았어요.
| 항목 | Zapier | Make | n8n |
|---|---|---|---|
| 트리거 단계 자동 중복 제거 | deduplication, 기본 키는 id 필드 | 이 글에서 확인하지 않음 | 이 글에서 확인하지 않음 |
| 그 장치의 검사 범위 | 같은 Zap 안에서만 | 이 글에서 확인하지 않음 | 이 글에서 확인하지 않음 |
| 중복 제거 전용 기능 이름 | 별도 노드 없음, Storage by Zapier 로 구성 | 별도 모듈 없음, Data stores 로 구성 | Remove Duplicates 노드 |
| 처리 기록 저장소 | Storage by Zapier | Data stores | Remove Duplicates 의 내부 기록 |
| 기록 한도 | 키 32자, 계정당 500개, 값 1MB | 작업 1,000개당 1MB, 조직당 스토어 1,000개 | History Size 기본 10,000개 항목 |
| 기록 만료 | 2개월 미사용 시 키 삭제 | 이 글에서 확인하지 않음 | 이 글에서 확인하지 않음 |
| 같은 키 재입력 시 동작 | 이 글에서 확인하지 않음 | 덮어쓰기 옵션이 꺼져 있으면 오류 | Value Is New 기준으로 제거 |
| 자동 재시도 기능 이름 | Autoreplay, 최대 5회 | 미완료 실행 자동 재시도, Retry 에러 핸들러 | 이 글에서 확인하지 않음 |
| 자동 재시도 기본 상태 | 이 글에서 확인하지 않음 | 미완료 실행 저장이 기본 꺼짐 | 이 글에서 확인하지 않음 |
Zapier 칸은 개발자 문서와 도움말에서, Make 칸은 데이터 스토어와 미완료 실행 문서에서, n8n 칸은 Remove Duplicates 노드 문서에서 확인한 내용이에요. Make의 트리거 단계 자동 중복 제거를 닫아 둔 이유는 이래요. Make 도움말 사이트맵에 실린 문서 URL 373개를 훑었을 때 이 주제를 다루는 문서를 찾지 못했고, 데이터 스토어 문서만 확인했거든요. 있다 없다를 단정하는 대신 확인하지 않은 것으로 두는 편이 맞아요.
순서대로 다섯 개만 확인해 보세요. 대부분 여기서 걸려요.
첫째, 지금 그 데이터를 보고 있는 자동화가 몇 개인지 세어 보세요. 목록을 열어 같은 앱과 같은 트리거를 쓰는 것을 전부 찾으면 돼요. 두 개 이상이면 그 자체가 원인이에요.
둘째, 두 번째 알림이 첫 번째와 얼마나 떨어져 왔는지 보세요. 몇 분에서 몇 시간 뒤라면 자동 재시도 쪽을 먼저 열어 보세요. Zapier라면 재실행 설정을, Make라면 시나리오 설정의 미완료 실행 저장 옵션을 확인하면 돼요.
셋째, 자동화의 마지막 액션이 트리거로 쓰는 그 데이터를 다시 건드리는지 보세요. 같은 시트, 같은 테이블, 같은 메일함이면 거의 확실해요.
넷째, 처리한 건을 적어 두는 자리가 자동화 안에 있는지 보세요. 없다면 그게 근본 원인이에요. 도구별로 Storage by Zapier, Data stores, Remove Duplicates 중 하나를 트리거 바로 다음에 놓으면 돼요.
다섯째, 키로 쓸 값이 항목마다 다르고 같은 항목에서는 항상 같은지 확인하세요. 이 조건이 깨지면 위 넷을 다 해도 새어 나가요. 시간처럼 매번 달라지는 값을 키에 섞어 넣는 실수가 흔한데, 그러면 같은 항목이 매번 새것으로 보여요.
마지막으로 하나만 덧붙일게요. 중복을 막는 장치를 넣을 때는 막힌 건이 어디에 기록되는지도 같이 정해 두세요. 필터나 오류로 멈춘 건은 조용히 사라지거든요. 나중에 그날 왜 안 왔는지를 확인할 때, 멈춘 기록이 남아 있는지 없는지가 크게 갈려요.
그럴 수도 있지만 먼저 볼 곳이 따로 있어요. 적어도 Zapier는 폴링 트리거에 대해 중복 제거 장치를 이미 갖추고 있거든요. Zapier 개발자 문서는 이 장치를 deduplication 이라고 부르고 목적을 이렇게 적어요. Zapier가 들어오는 트리거 데이터를 자동으로 중복 제거하므로 Zap 워크플로가 같은 데이터로 여러 번 실행되지 않는다고요. 그러니 알림이 두 번 왔다면 트리거가 두 번 깨어났는지보다 먼저 볼 곳이 세 군데예요. 같은 트리거를 쓰는 자동화가 두 개 이상인지, 실패한 단계를 도구가 자동으로 다시 돌렸는지, 액션이 자기 트리거를 다시 건드렸는지예요. 이 세 가지는 중복 제거 장치가 막아 주는 범위 밖이에요.
네, 둘 다 돌아요. Zapier 도움말이 이 점을 따로 못 박아 두었어요. 같은 폼을 트리거로 쓰는 Zap 워크플로가 두 개 있으면 전부 트리거되며, 중복 제거 시스템은 같은 Zap 안에서만 검사한다고요. 여기서 오해가 자주 생겨요. 도구가 중복을 막아 준다는 말을 계정 전체에 적용되는 규칙으로 읽으면 틀려요. 그 장치는 자동화 한 개의 안쪽만 봐요. 그래서 예전에 만들어 두고 잊은 자동화가 같은 데이터를 보고 있으면 알림은 그냥 두 번 와요. 이럴 때 공식 문서가 권하는 처방은 두 가지예요. 조건에 맞을 때만 진행하도록 필터를 넣거나, 결과가 다른 여러 자동화를 Paths 로 하나에 합치는 거예요.
같은 요청을 여러 번 보내도 결과가 한 번 보낸 것과 같아지는 성질이에요. 결제 API 쪽 설명이 가장 명확해요. Stripe API 레퍼런스는 멱등성을 이렇게 정의해요. 같은 작업을 실수로 두 번 수행하지 않으면서 요청을 안전하게 재시도할 수 있도록 API가 멱등성을 지원하며, 객체를 만들거나 갱신할 때 멱등키를 쓰면 연결 오류가 나도 두 번째 객체가 생기거나 갱신이 두 번 되는 위험 없이 요청을 다시 보낼 수 있다고요. 동작 원리도 같은 문서에 적혀 있어요. 어떤 멱등키에 대해서든 첫 요청의 응답 상태 코드와 본문을 저장해 두고, 성공이든 실패든 상관없이 같은 키로 온 뒤 요청에는 저장해 둔 그 결과를 그대로 돌려준다고요. 자동화에서 흉내 낼 부분은 이 저장 단계예요.
Remove Duplicates 노드예요. 공식 문서는 이 노드가 두 종류를 처리한다고 적어요. 한 실행 안에서 모든 필드 또는 일부 필드가 같은 항목, 그리고 이전 실행에서 본 항목과 같거나 그것을 넘어서지 못하는 항목이에요. 동작 모드는 세 가지이고 이름이 각각 Remove Items Repeated Within Current Input, Remove Items Processed in Previous Executions, Clear Deduplication History 예요. 이전 실행과 비교하는 모드에서는 판정 기준을 Value Is New, Value Is Higher than Any Previous Value, Value Is a Date Later than Any Previous Date 중에서 고르고, 무엇을 키로 볼지는 Value to Dedupe On 에 지정해요. 참고로 이 노드는 n8n 1.64.0 에서 전면 개편됐다고 문서 상단에 안내가 붙어 있으니, 화면과 문서가 다르면 버전부터 확인하세요.
기억하는 개수에 한도가 있어서 그럴 수 있어요. 공식 문서의 History Size 옵션 설명이 이렇게 적혀 있어요. 실행을 건너뛰며 중복을 추적하기 위해 n8n 이 저장할 항목 수이고, 기본값으로 n8n 은 10,000개 항목을 저장한다고요. 이 옵션은 Keep Items Where 를 Value Is New 로 골랐을 때 나타나요. 그리고 그 저장 범위가 어디까지인지는 Scope 옵션이 정해요. 기본값인 Node 는 같은 워크플로의 다른 Remove Duplicates 노드와 따로 저장하고, Workflow 로 두면 Workflow 범위를 쓰는 다른 Remove Duplicates 노드들과 같은 기록을 공유해요. 그래서 노드를 지웠다 다시 만들었거나 Scope 를 바꿨다면 기억이 이어지지 않을 수 있어요.
공식 문서가 안내하는 방식은 데이터 스토어예요. 데이터 스토어를 만들 때 데이터 구조를 비워 두는 선택지가 있는데, 문서는 그 선택의 용도를 이렇게 설명해요. 데이터 구조를 고르지 않으면 데이터베이스에 기본 키만 들어가며, 키만 저장하고 특정 키가 데이터베이스에 있는지 없는지만 알고 싶을 때 이런 유형이 유용하다고요. 실제 잠금은 Add/replace a record 모듈에서 걸려요. 같은 문서가 이렇게 적어요. 같은 이름으로 이미 데이터 스토어에 있는 레코드를 추가하려 하는데 Overwrite an existing record 옵션이 꺼져 있으면 모듈이 오류를 던진다고요. 즉 이 옵션을 꺼 둔 채로 키를 먼저 쓰게 해 두면, 두 번째 시도는 그 자리에서 멈춰요. 다만 Make 가 트리거 단계에서 자동으로 중복을 걸러 주는 장치를 두는지는 이 글에서 확인하지 않았어요.
생길 수 있어요. Zapier 도움말도 중복 데이터의 원인 중 하나로 타임아웃을 적으면서, Zap 실행에 timed out 오류 메시지가 있다면 오류 난 액션을 재실행하려는 시도가 중복 데이터를 만들고 있을 수 있다고 밝혀요. 다만 재실행이 어디까지 다시 도는지는 알아 둘 필요가 있어요. Zap history 에서 하는 재실행은 실패한 단계만 다시 돌아요. 문서의 예시가 명확해요. 메일 보내기는 성공하고 시트 행 추가가 실패한 Zap 을 재실행하면 트리거도 메일 단계도 다시 돌지 않고 시트 행 추가만 다시 시도한다고요. 반면 편집기에서 하는 전체 재실행은 다르게 동작해요. 별도의 새 실행으로 기록되고 트리거부터 모든 단계를 상태와 상관없이 다시 돌려요.
공식 문서 기준 최대 5회예요. 간격은 시도할 때마다 벌어져요. 문서는 오후 1시에 처음 실패한 경우를 예로 들어, 첫 시도는 최초 트리거 이벤트로부터 5분 뒤, 두 번째는 직전 시도로부터 30분 뒤, 세 번째는 1시간 뒤, 네 번째는 3시간 뒤, 다섯 번째는 6시간 뒤라고 적고, 마지막 재실행은 첫 오류로부터 약 10시간 35분 뒤에 일어난다고 덧붙여요. 여기서 실무상 중요한 대목이 하나 더 있어요. 같은 문서가 마지막 자동 재실행 시도가 실패하기 전까지는 오류 알림 메일을 보내지 않는다고 적고 있어요. 즉 조용하다고 해서 잘 돌고 있다는 뜻은 아니에요.
Zapier 공식 문서가 두 단계짜리 처방을 제시해요. 첫째, 고리를 만드는 액션에 고유한 값을 하나 넣어서 이 자동화가 이미 한 번 처리했다는 표시를 남기고, 둘째, 그 값을 필터에서 읽어 값이 있으면 진행하지 않게 막는 거예요. 문서는 필터 조건으로 Does not contain 을 쓰라고 안내하고, 표시로 쓸 값은 원래 업무에서는 나타나지 않을 값으로 고르라고 덧붙여요. 넣을 자리는 원래 흐름에 영향을 주지 않는 필드가 좋다며 메모나 설명 필드를 예로 들고요. 그리고 이미 돌고 있다면 순서가 있어요. 같은 문서는 고리가 도는 자동화를 즉시 끄고, 두 개가 서로 물려 있으면 둘 다 끄라고 적어요.
도구마다 조건이 달라요. Storage by Zapier 의 한도는 문서에 이렇게 적혀 있어요. 키는 최대 32자, 스토리지 계정당 최대 500개, 값은 최대 1MB 이고, 2개월 동안 사용하지 않으면 키를 삭제한다고요. n8n Remove Duplicates 는 기본값이 10,000개 항목이고요. Stripe 쪽은 결이 조금 달라서, 최소 24시간이 지난 키는 시스템에서 자동으로 지울 수 있고 원본이 지워진 뒤 같은 키를 다시 쓰면 새 요청을 만든다고 적어요. 그러니 장부는 영구 보관 장치가 아니라 유효기간이 있는 장치로 다루세요. 오래 남겨야 하는 기록이라면 시트나 데이터베이스 쪽으로 옮기는 편이 안전해요.