FAQ / 문제 해결
자주 묻는 질문과 흔한 문제의 해결 방법을 카테고리별로 정리합니다.
SDK 설치와 연결
API 키를 분실했습니다
프로젝트 설정에서 기존 키를 폐기하고 새 키를 발급받으세요. 키를 폐기하면 약 60초 내에 기존 SDK 인스턴스의 전송이 중지됩니다 (401 응답 → 전송 영구 비활성화). 새 키로 SDK를 재설정한 후 봇을 재시작하세요.
SDK가 봇을 느리게 만들 수 있나요?
아닙니다. SDK는 절대 throw하지 않는 보장을 제공합니다.
- 모든 공개 메서드(
track,captureError,flush,shutdown)는 내부 오류를 무시합니다. - 이벤트 전송은 비동기 배치로 처리됩니다.
- 네트워크 실패 시에도 봇 동작에 영향을 주지 않습니다.
- 모든 타이머는
unref()처리되어 프로세스 종료를 방해하지 않습니다.
유일하게 예외를 던지는 경우는 createDicolytics() 호출 시 apiKey가 누락된 경우뿐입니다.
어떤 데이터가 수집되나요?
SDK가 수집하는 데이터를 카테고리별로 정리하면:
| 카테고리 | 수집 항목 | 수집하지 않는 것 |
|---|---|---|
| 상호작용 | 명령어 이름, 지연 시간, 성공 여부 | 명령어 인자 값 |
| 작업 | REST API 호출 종류, 건수 | 요청/응답 페이로드 |
| 이벤트 | 게이트웨이 이벤트 건수 (집계) | 개별 이벤트 내용 |
| 메시지 | 봇 발신 메시지 건수만 | 메시지 내용 절대 수집 안 함 |
| 오류 | 이름, 메시지(2KiB), 스택(8KiB) | 전체 오류 객체 |
| 서버 | 이름, 멤버 수, 로케일 | 채널 목록, 설정 등 |
참고
messageCreate 등 수신 메시지 이벤트는 건수만 집계합니다. 메시지 본문, 첨부 파일, 임베드 등의 내용은 SDK가 접근하지 않습니다.
전체 이벤트 목록은 이벤트 레퍼런스를 참고하세요.
disabledEvents로 이벤트를 끌 수 있나요?
네. disabledEvents 배열에 이벤트 타입 문자열을 추가하면 해당 타입의 자동 수집이 비활성화됩니다. EVENT_TYPES 상수를 사용하면 오타를 방지할 수 있습니다.
import { createDicolytics, EVENT_TYPES } from '@dicolytics/discord.js';
const analytics = createDicolytics(client, {
apiKey: '...',
disabledEvents: [
EVENT_TYPES.eventTypingStart,
EVENT_TYPES.eventPresenceUpdate,
EVENT_TYPES.guildSnapshot,
],
});from dicolytics import create_dicolytics
analytics = create_dicolytics(bot,
api_key="...",
disabled_events=[
"event_typing_start",
"event_presence_update",
"guild_snapshot",
],
)단, custom 타입은 비활성화할 수 없습니다. 커스텀 이벤트를 전송하지 않으려면 track()을 호출하지 않으면 됩니다.
샤딩 환경에서 어떻게 설정하나요?
ShardingManager를 사용하는 경우, 각 샤드 프로세스에서 SDK 인스턴스를 생성하면 됩니다. shardId는 자동으로 포함됩니다.
멀티클러스터 배포에서는 각 클러스터 프로세스에서 clusterId 옵션을 설정하세요. 자세한 내용은 멀티클러스터를 참고하세요.
대시보드
데이터가 표시되지 않습니다
다음 순서로 확인하세요.
- SDK 연결 확인:
debug: true옵션으로 콘솔 로그를 확인합니다. - API 키 확인: 콘솔에
invalid API key경고가 있는지 확인합니다. 401 응답 시 전송이 영구 비활성화됩니다. - 기간 확인: 대시보드의 기간 선택기가 SDK 연결 이후의 시간을 포함하는지 확인합니다.
참고
debug: true를 설정하면 SDK가 내부 동작을 console.warn으로 출력합니다. 전송 성공/실패, 큐 상태, 옵션 검증 결과 등을 확인할 수 있습니다.
탐색(Explore)에서 커스텀 이벤트 속성이 안 보입니다
props.* 필드로 필터링하려면 속성 값이 올바른 타입이어야 합니다.
- 권장: 문자열, 숫자, 불리언
- 비권장: 중첩 객체, 배열 (JSON으로 직렬화되지만 필터링 어려움)
또한, 커스텀 이벤트를 track()으로 전송한 후 대시보드에 반영되기까지 몇 초의 지연이 있을 수 있습니다.
기간을 변경해도 데이터가 같습니다
브라우저 캐시를 새로고침(Ctrl+Shift+R)하거나, 다른 기간을 선택한 뒤 다시 시도해 보세요. 문제가 지속되면 시크릿/프라이빗 브라우저 창에서 확인합니다.
데이터 수집
action이 안 잡혀요
가장 흔한 원인은 interaction.reply()를 사용하는 경우입니다.
참고
interaction.reply(), interaction.deferReply(), interaction.editReply(), interaction.followUp() 등은 Discord 웹훅 경로(/webhooks/...)를 사용합니다. SDK는 웹훅 경로를 패치하지 않으므로 이 호출들은 작업(action)으로 감지되지 않습니다.
**channel.send()**로 직접 메시지를 보내는 경우만 action_message_send로 감지됩니다.
// action으로 감지되지 않음
await interaction.reply('Hello!');
// action_message_send로 감지됨
await interaction.channel.send('Hello!');이것은 의도된 동작입니다. 상호작용 응답은 이미 상호작용 카테고리에서 추적되고 있으므로, 중복 계산을 방지합니다.
이벤트 수치가 이상하게 커요 / 작아요
discord_events 메트릭과 events 메트릭을 혼동하고 있을 가능성이 높습니다.
| 메트릭 | 의미 | 계산 방식 |
|---|---|---|
discord_events | 실제 게이트웨이 이벤트 건수 | sum(data.count) |
events | 집계 레코드 수 | count(*) |
예를 들어 1시간 동안 event_message_create가 분당 500건씩 발생했다면:
discord_events= 30,000 (실제 메시지 수: 500 x 60)events= 60 (60초마다 1건의 집계 레코드)
대시보드에서 실제 게이트웨이 이벤트 건수를 보려면 메트릭 셀렉터에서 **discord_events**를 선택하세요.
자세한 내용은 이벤트 데이터 모델을 참고하세요.
특정 게이트웨이 이벤트가 수집되지 않아요
SDK는 클라이언트에 활성화된 인텐트에 해당하는 이벤트만 수집합니다. 필요한 인텐트가 활성화되어 있는지 확인하세요.
| 이벤트 | 필요 인텐트 |
|---|---|
event_member_join/leave/update | GuildMembers (특권) |
event_message_create/update/delete | GuildMessages |
event_reaction_add/remove | GuildMessageReactions |
event_typing_start | GuildMessageTyping |
event_presence_update | GuildPresences (특권) |
event_ban_add/remove | GuildModeration |
특권 인텐트(GuildMembers, GuildPresences)는 Discord Developer Portal에서 별도로 활성화해야 합니다.
전체 인텐트 매핑은 이벤트 데이터 모델을 참고하세요.
unique_users/unique_guilds 수치가 부정확해요
이 메트릭은 HyperLogLog(HLL) 근사치입니다. 정확한 COUNT(DISTINCT)가 아니며, 약 +-2%의 오차가 있습니다. 특히 소규모 데이터셋에서는 오차 비율이 더 클 수 있습니다.
대시보드에서 이 수치 옆의 "근사치" 뱃지를 확인하세요. 자세한 내용은 메트릭과 차원을 참고하세요.
오류가 수집되지 않아요
자동으로 수집되는 오류와 수동으로 보고하는 오류를 구분하세요.
| 오류 타입 | 감지 방식 | 자동 여부 |
|---|---|---|
command_error | interaction.reply() 등의 reject/throw | 자동 |
error | captureError() 호출 | 수동 |
error | unhandledRejection | autoCapturePromiseRejections: true 필요 |
비즈니스 로직의 오류를 추적하려면 captureError()를 직접 호출하세요. 자세한 내용은 커스텀 이벤트를 참고하세요.
전송과 네트워크
429 레이트 리밋이 발생합니다
SDK가 Dicolytics 서버로부터 429 응답을 받으면 Quiet Period에 진입합니다. Retry-After 헤더 값(기본 300초) 동안 일반 이벤트 전송이 중지됩니다. heartbeat과 guild_snapshot은 계속 전송됩니다.
이벤트 볼륨이 매우 높은 경우:
disabledEvents로 불필요한 이벤트를 비활성화하세요.flushIntervalMs를 늘려 전송 빈도를 줄이세요.
자세한 내용은 전송과 재시도를 참고하세요.
endpoint 설정 후 전송이 안 됩니다
SDK는 HTTP 리다이렉트(301/302)를 따르지 않습니다. 리다이렉트가 감지되면 전송이 영구 비활성화됩니다.
endpoint에는 반드시 최종 URL을 지정하세요. http://를 사용하고 서버가 https://로 리다이렉트하는 경우에도 동일하게 비활성화됩니다.
// 잘못된 예시 (리다이렉트 발생 가능)
endpoint: 'http://analytics.example.com'
// 올바른 예시
endpoint: 'https://analytics.example.com'# 잘못된 예시 (리다이렉트 발생 가능)
endpoint="http://analytics.example.com"
# 올바른 예시
endpoint="https://analytics.example.com"