AI 자동화 알림이 두 번 온다면, 재시도 ID부터 확인하세요

부제: Python·SQLite로 중복 예약을 막고, 1 → 0 출력을 직접 확인하는 짧은 실험
자동화가 같은 알림을 두 번 보냈다면 작업 기록에서 첫 요청과 재시도의 request_id를 찾아보세요. 재시도 때 새 ID를 만들고 있으면, 프로그램은 같은 일을 새 작업으로 받아들일 수 있습니다.
이번에는 실제 알림을 보내지 않고 같은 요청의 예약이 한 번만 등록되는지 확인합니다. 계정이나 유료 도구는 필요 없습니다. Python의 sqlite3 모듈과 SQLite 3.24.0 이상이면 예제를 실행할 수 있습니다. SQLite UPSERT 문서
1. 재시도에는 같은 ID를 씁니다
처음 요청한 작업이 task-A라면 재시도에도 task-A를 유지합니다. 별개의 새 작업에만 다른 ID를 부여하세요.
ID만 같고 본문이 달라지는 경우도 살펴야 합니다. 아래 코드는 같은 ID의 새 입력을 건너뛰므로, 바뀐 본문을 자동으로 반영하거나 충돌을 알려주지 않습니다.
2. 복사해서 1, 0을 확인하세요
다음을 retry_demo.py로 저장하고 터미널에서 python3 retry_demo.py (Windows 등에서 python 명령을 사용하는 환경은 python retry_demo.py)를 실행합니다.
import sqlite3
db = sqlite3.connect(":memory:")
db.execute(
"CREATE TABLE jobs ("
"request_id TEXT PRIMARY KEY NOT NULL, "
"payload TEXT NOT NULL)"
)
def reserve(request_id, payload):
with db:
cur = db.execute(
"INSERT INTO jobs(request_id, payload) VALUES (?, ?) "
"ON CONFLICT(request_id) DO NOTHING",
(request_id, payload),
)
return cur.rowcount
print(reserve("task-A", "알림 예약"))
print(reserve("task-A", "알림 예약"))
db.close()
예상 출력과 직접 실행한 출력은 같았습니다.

1
0
1: 예약 행 하나를 추가했습니다.0: 같은 ID가 이미 있어 새 행을 추가하지 않았습니다.
PRIMARY KEY가 같은 ID의 중복을 제한하고, ON CONFLICT(request_id) DO NOTHING이 해당 충돌의 삽입을 건너뜁니다. SQLite 설명
rowcount는 이 SQL로 변경된 행 수입니다. with db:는 열린 트랜잭션을 정상 종료할 때 커밋하고, 오류가 나면 롤백합니다. Python sqlite3 문서, 트랜잭션 처리
실행 환경: 2026년 10월 14일, Python 3.12.14 / SQLite 3.53.1. 합성 ID와 문장만 사용했습니다.
3. 아래 입력도 함께 점검하세요
추가로 직접 확인한 결과입니다.
- 같은 ID·같은 본문: 두 번째 삽입은
0, 기존 행은 1개 - 같은 ID·다른 본문: 삽입은
0, 기존 본문 유지 - 다른 ID: 삽입
1 - 빈 문자열
""또는 공백 ID: 삽입 성공 NoneID:NOT NULL제약 오류
따라서 앱에서 빈 ID와 공백 ID를 거절하고, 같은 ID에 다른 본문이 들어오면 별도 오류로 처리할지 정해야 합니다.
NOT NULL도 생략하지 마세요. SQLite의 일반 테이블에서 TEXT PRIMARY KEY만 선언하면 NULL을 허용할 수 있습니다. 이번 검사에서도 NOT NULL을 뺀 별도 테이블에는 NULL 키 두 행이 들어갔습니다. SQLite 기본키 문서
여기까지 확인한 범위
확인한 것은 로컬 예약 중복 방지입니다. 실제 알림의 정확히 한 번 발송은 보장하지 않습니다.
예제의 :memory: 데이터는 연결을 닫으면 사라집니다. 재시작 후에도 예약을 기억하는 저장 구조는 별도로 마련해야 합니다. Python 연결 문서
이번 검사는 한 연결에서 순서대로 실행했습니다. 여러 연결·프로세스가 동시에 요청하는 상황, 파일 DB의 재시작, 외부 발송 API는 검증하지 않았습니다. 특히 발송은 성공했지만 결과를 기록하기 전에 프로그램이 종료되는 상황은 이 코드로 해결되지 않습니다.
오늘 할 일은 하나입니다. 첫 요청과 재시도의 ID를 나란히 놓고, 같은 작업에 같은 ID가 유지되는지 확인해 보세요.