AI 활용

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

오픈시드 2026. 10. 14. 10:38
반응형

같은 요청은 한 번만: 두 요청 카드가 하나의 데이터베이스 행으로 모이는 SQLite 중복 예약 개념도
같은 요청 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()

예상 출력과 직접 실행한 출력은 같았습니다.

같은 ID로 두 번 예약했을 때 첫 삽입은 1, 두 번째는 0인 실제 콘솔 출력
직접 실행한 Python 3 콘솔 출력 일부입니다. 첫 요청은 1, 같은 ID의 재시도는 0입니다.

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: 삽입 성공
  • None ID: NOT NULL 제약 오류

따라서 앱에서 빈 ID와 공백 ID를 거절하고, 같은 ID에 다른 본문이 들어오면 별도 오류로 처리할지 정해야 합니다.

NOT NULL도 생략하지 마세요. SQLite의 일반 테이블에서 TEXT PRIMARY KEY만 선언하면 NULL을 허용할 수 있습니다. 이번 검사에서도 NOT NULL을 뺀 별도 테이블에는 NULL 키 두 행이 들어갔습니다. SQLite 기본키 문서

여기까지 확인한 범위

확인한 것은 로컬 예약 중복 방지입니다. 실제 알림의 정확히 한 번 발송은 보장하지 않습니다.

예제의 :memory: 데이터는 연결을 닫으면 사라집니다. 재시작 후에도 예약을 기억하는 저장 구조는 별도로 마련해야 합니다. Python 연결 문서

이번 검사는 한 연결에서 순서대로 실행했습니다. 여러 연결·프로세스가 동시에 요청하는 상황, 파일 DB의 재시작, 외부 발송 API는 검증하지 않았습니다. 특히 발송은 성공했지만 결과를 기록하기 전에 프로그램이 종료되는 상황은 이 코드로 해결되지 않습니다.

오늘 할 일은 하나입니다. 첫 요청과 재시도의 ID를 나란히 놓고, 같은 작업에 같은 ID가 유지되는지 확인해 보세요.

반응형