Skip to content

전송과 재시도 v0.5.0

SDK가 이벤트를 서버로 전송하는 HTTP 배치 구조, 엔벨로프 포맷, 재시도 정책, 버퍼 관리를 상세히 설명합니다.

HTTP 배치 구조

SDK는 이벤트를 개별로 전송하지 않고, **배치(batch)**로 묶어 한 번에 전송합니다.

요청 형식

POST {endpoint}/v1/events
Content-Type: application/json
Authorization: Bearer dk_live_...
User-Agent: @dicolytics/discord.js/0.5.0

응답 형식

json
// 202 Accepted
{
  "accepted": 48,
  "dropped": 2
}

accepted는 서버가 수락한 이벤트 수, dropped는 검증 실패로 버린 이벤트 수입니다.

엔벨로프 포맷

하나의 HTTP 요청에 담기는 JSON 구조입니다.

json
{
  "batchId": "01912345-6789-7abc-8def-0123456789ab",
  "sdk": {
    "name": "@dicolytics/discord.js",
    "version": "0.5.0"
  },
  "sentAt": "2025-01-15T12:00:00.000Z",
  "events": [
    {
      "id": "01912345-6789-7def-8abc-0123456789cd",
      "type": "interaction_slash",
      "ts": "2025-01-15T11:59:58.123Z",
      "guildId": "123456789012345678",
      "channelId": "234567890123456789",
      "userId": "987654321098765432",
      "data": {
        "commandName": "play rock",
        "interactionKind": "slash",
        "latencyMs": 42,
        "success": true,
        "shardId": 0
      }
    }
  ]
}

필드 설명

필드타입설명
batchIdstring전송 시도마다 새로 생성되는 UUIDv7
sdk.namestringSDK 패키지 이름 (@dicolytics/discord.js 또는 dicolytics-discord.py)
sdk.versionstringSDK 버전
sentAtstring전송 시각 (UTC ISO-8601)
eventsarray이벤트 배열

이벤트 필드

필드타입필수설명
idstring이벤트 고유 ID (UUIDv7, RFC 9562)
typestring이벤트 타입
tsstring이벤트 발생 시각 (UTC ISO-8601)
guildIdstring서버 ID
channelIdstring채널 ID
userIdstring사용자 ID
dataobject이벤트별 데이터 (타입에 따라 구조 다름)

이벤트 ID와 중복 제거

각 이벤트의 id는 UUIDv7 형식으로 생성됩니다. 재시도 시에도 동일한 id를 재사용하므로, 서버 측에서 중복 이벤트를 자동으로 제거할 수 있습니다.

배치 제한

항목제한
배치당 최대 이벤트 수500개
배치당 최대 크기1 MiB (1,048,576 바이트)

초과 시 동작

  • 큐에 500개 이상의 이벤트가 있으면 500개씩 분할하여 순차 전송합니다.
  • 직렬화된 배치가 1 MiB를 초과하면 반으로 분할하여 재시도합니다. 재귀적으로 분할합니다.
  • 단일 이벤트가 1 MiB를 초과하면 해당 이벤트는 폐기됩니다.

플러시 정책

조건동작
큐에 50개 이상 대기즉시 플러시
마지막 플러시 후 5초 경과타이머 기반 플러시
flush() 직접 호출즉시 플러시
프로세스 종료 (SIGINT/SIGTERM)최대 3초간 플러시

참고

플러시 중에 새로운 플러시가 요청되면 현재 전송이 완료될 때까지 대기합니다. 동시에 여러 HTTP 요청이 발생하지 않으며, 이벤트 순서가 보장됩니다.

재시도 정책

HTTP 응답 상태 코드에 따라 다르게 동작합니다.

상태 코드동작설명
2xx성공이벤트 수락 완료
301, 302전송 영구 비활성화리다이렉트 감지. endpoint를 최종 URL로 변경하라는 경고 출력
400배치 폐기잘못된 요청. 재시도해도 동일하므로 버림
401전송 영구 비활성화API 키 무효. 큐 전체 비우고 경고 출력
403재시도CDN/WAF의 일시적 차단일 수 있으므로 백오프 재시도
429Quiet Period레이트 리밋. Retry-After 헤더 준수
5xx재시도서버 오류. 지수 백오프 재시도
네트워크 오류재시도연결 실패, 타임아웃 등

지수 백오프

재시도 가능한 오류(403, 5xx, 네트워크 오류)에는 full-jitter 지수 백오프를 적용합니다.

delay = random() * min(BACKOFF_MAX, BACKOFF_BASE * 2^(attempt - 1))
상수
BACKOFF_BASE1,000ms (1초)
BACKOFF_MAX30,000ms (30초)
최대 시도 횟수5회

예시 (최대 지연):

  • 1차 재시도: 최대 1초
  • 2차 재시도: 최대 2초
  • 3차 재시도: 최대 4초
  • 4차 재시도: 최대 8초
  • 5차 재시도: 최대 16초

5회 시도 후에도 실패하면 해당 배치는 폐기됩니다.

429 Quiet Period

서버가 429 응답을 반환하면 SDK는 Quiet Period에 진입합니다.

항목
기본 Quiet Period300초 (5분)
Retry-After 헤더 있을 때헤더 값 사용
최대 Quiet Period86,400초 (24시간)

참고

Quiet Period 동안 일반 이벤트(상호작용, 작업, 커스텀 등)는 큐에 쌓이지만 전송되지 않습니다. 단, heartbeatguild_snapshot은 예외적으로 계속 전송됩니다. 이는 봇의 온라인 상태와 서버 정보를 대시보드에서 계속 확인할 수 있도록 하기 위함입니다.

버퍼 관리

항목
최대 버퍼 크기5,000건
초과 시 동작가장 오래된 이벤트부터 폐기
정상 복구 시자동으로 전송 재개
버퍼 초과는 언제 발생하나요?

정상적인 네트워크 환경에서는 5,000건에 도달하기 어렵습니다. 네트워크 장애, 서버 다운, 429 Quiet Period가 길어질 때 발생할 수 있습니다. 버퍼가 가득 차면 새로운 이벤트를 위해 오래된 이벤트를 폐기합니다.

전송 비활성화

다음 상황에서 SDK의 전송 기능이 영구적으로 비활성화됩니다. 봇을 재시작해야 전송이 재개됩니다.

상황원인
401 응답API 키가 무효하거나 만료됨
301/302 응답endpoint가 리다이렉트되는 URL임

비활성화 시 큐가 비워지고 경고 로그가 출력됩니다. 이후 track() 등의 호출은 정상 동작하지만 이벤트가 전송되지는 않습니다.

종료 시 동작

프로세스 종료 시 SDK는 마지막 이벤트를 보존하기 위해 다음과 같이 동작합니다.

시그널동작
SIGINT최대 3초간 플러시 → 다른 핸들러 없으면 시그널 재전달
SIGTERM최대 3초간 플러시 → 다른 핸들러 없으면 시그널 재전달
beforeExit최대 3초간 플러시
shutdown() 직접 호출리스너 해제 → 최대 3초간 플러시

타이머 unref

SDK의 모든 내부 타이머는 unref()로 설정됩니다. SDK 타이머만으로는 Node.js 프로세스가 유지되지 않으므로, 다른 활성 작업이 없으면 프로세스가 정상 종료됩니다.

상수 요약

상수설명
FLUSH_AT_EVENTS50이 수만큼 큐에 쌓이면 즉시 플러시
DEFAULT_FLUSH_INTERVAL_MS5,000타이머 기반 플러시 주기
MAX_BUFFERED_EVENTS5,000큐 최대 크기
MAX_BATCH_EVENTS500배치당 최대 이벤트 수
MAX_BATCH_BYTES1,048,576배치당 최대 크기 (1 MiB)
MAX_SEND_ATTEMPTS5최대 재시도 횟수
BACKOFF_BASE_MS1,000백오프 기본값
BACKOFF_MAX_MS30,000백오프 최대값
DEFAULT_RETRY_AFTER_SECONDS300429 기본 Quiet Period
DEFAULT_REQUEST_TIMEOUT_MS10,000HTTP 요청 타임아웃
SHUTDOWN_FLUSH_TIMEOUT_MS3,000종료 시 플러시 타임아웃

관련 문서

Dicolytics — Discord bot analytics