Discord 서버 4,000개 지켜보기: Grafana, PostHog, 그리고 그것들이 보여 준 것
트래픽의 절반을 조용히 만들어 낸 반복 작업, 하루 300만 건의 쓸모없는 요청, 1분 만에 끝난 공격. 우리 모니터링이 보는 것과 일부러 보지 않는 것을 이야기해요.

AlphaCloud는 4,000개를 조금 넘는 Discord 서버에서 돌아가고, 네 개의 샤드에 나뉘어 있어요. 샤드는 네 개의 프로세스로, 각각 서버의 일부를 맡고, 모두 같은 API와 통신해요.
이 정도 규모에서는 문제가 무언가를 망가뜨리는 방식으로 드러나는 일이 드물어요. 훨씬 더 자주, 모든 게 작동은 하는데 원래보다 더 비싸고, 더 느리고, 더 시끄럽게 작동해요. 그래서 2026년 9월에 모니터링을 다시 만들었어요. 이 글은 그게 어떤 모습인지, 그리고 처음 몇 주 동안 무엇을 보여 줬는지 이야기해요.
두 가지 도구, 두 가지 질문
Grafana는 이 질문에 답해요: 봇은 무엇을 하고 있나요? 봇과 API는 지표를 Prometheus에 보내고(요청, 응답 시간, 오류율, Discord 응답, AI 사용량), 로그는 Loki로 가요. 서버 노드마다 자체 스택이 있고, Grafana는 인터넷이 아니라 사설 네트워크를 통해서만 접속할 수 있어요.
PostHog는 이 질문에 답해요: 사람들은 우리 웹사이트에서 무엇을 경험하나요? 페이지 조회, 브라우저 오류, 로딩 시간, 그리고 동의한 경우에는 세션 녹화까지요. PostHog는 쿠키 배너에서 동의한 뒤에만 시작돼요.
이렇게 나눈 건 일부러예요. Grafana는 기계를 보고, PostHog는 화면을 봐요. 둘을 도구 하나에 억지로 넣으면, 서버 로그에 사용자 데이터가 섞이거나 제품 분석에 서버 부하가 섞여요.
무엇을 찾아냈나요
트래픽의 절반을 만든 반복 작업
종료 시간이 있는 투표는 백그라운드 작업이 닫아요. 이 작업은 1분마다 만료된 게 있는지 확인해요. 그런데 이걸 모든 서버마다 하나씩 따로 했어요. 샤드당 약 1,000개 서버에 샤드가 네 개니, 초당 약 70건의 요청이 나왔고, 거의 전부 "만료된 것 없음"이라는 답이었어요.
이걸 알아챈 건 Grafana에서 봇이 API로 보내는 요청을 경로별로 나눠 봤을 때였어요: 이 엔드포인트 하나가 전체 트래픽의 절반이 넘었어요. 모든 게 작동했어요. 다만 아무도 요청하지 않은 부하를 지고 있었을 뿐이에요.
이제 각 샤드는 1분에 한 번 "만료된 투표가 있는 서버가 어디예요?"라고 묻고, 그 서버에 대해서만 자세한 내용을 가져와요. 분당 약 4,200건이던 요청이 4건 정도로 줄었어요.
300만 번의 "설정되지 않음"
같은 패턴, 다른 곳이에요: 여러 모듈(지원 기록, 부재, 팀 목록, 봇 통계, 뉴스레터)이 반복 작업에서 모든 서버의 설정을 주기적으로 읽었어요. 대부분의 서버에서는 해당 모듈이 아예 설정되어 있지 않으니, 답은 "찾을 수 없음"이었어요. 하루에 약 300만 번이요.
해결책은 평범해요: "설정되지 않음"을 이제 30분 동안 기억해요. 이게 안전한 이유는 이 모듈들이 모두 웹 패널에서 저장되는 순간 봇에 업데이트를 보내기 때문이에요. 그래서 모듈을 설정했는데 30분을 기다려야 하는 일은 없어요.
Discord의 장애는 우리 버그가 아니에요
우리 팀 오류 채널은 실패한 모든 작업을 고유 참조 번호까지 붙여 "Runtime Error"로 올렸어요. 여기에는 Discord 자체가 서버 오류로 응답한 순간도 포함됐어요. 그건 우리 쪽 버그도 아니고 우리가 고칠 수 있는 것도 아닌데, 채널에서는 진짜 결함과 똑같아 보였어요.
이제 이런 경우는 경고로 기록되고, 멤버에게는 버그 신고 링크 대신 몇 초 후에 다시 시도하라고 안내해요. 메시지의 절반이 오류가 아닌 오류 채널은 결국 아무도 읽지 않게 돼요. 그러면 진짜 오류를 놓쳐요.
1분 동안 이어진 공격
9월 말의 어느 오후, 우리 홈페이지에 1분 안에 50만 건이 조금 넘는 요청이 여러 나라에서 동시에 들어왔어요. 대부분은 우리 서버에 닿기 전에 막혔고, 1분 뒤에는 트래픽이 정상으로 돌아왔어요.
우리가 이걸 본 건 무언가 멈췄기 때문이 아니에요. 그 숫자가 차트의 나머지와 맞지 않았기 때문이에요. 그게 모니터링의 진짜 역할이에요: 모든 게 불타고 있을 때 경보를 울리는 게 아니라, 평소와 맞지 않는 곳을 보여 주는 거예요.
우리 모니터링이 일부러 보지 않는 것
여기서는 규칙이 대시보드만큼 중요해요:
- 로그에 방문자 IP 주소를 남기지 않아요. 개인정보 처리방침에서 약속한 내용이라, 두 군데에서 지워요: 접근 로그를 쓸 때, 그리고 저장하기 전에 한 번 더요.
- 지표에 서버, 사용자, 메시지 ID를 넣지 않아요. 모든 지표는 대략적인 속성(모듈, 상태 분류, 샤드)으로만 나뉘어요. 데이터를 보호하고, 지표 데이터베이스도 작게 유지돼요.
- 세션 녹화는 여러분의 콘텐츠가 아니라 우리 화면을 보여 줘요. 우리 번역 파일에 있는 문구와 정확히 일치하는 텍스트만 읽을 수 있게 남아요. 서버, 채널, 사용자 이름, 입력값, 미리보기는 가려져요. 허용된 텍스트 목록을 불러오지 못하면 전부 가려져요.
- 웹사이트에서는 모든 것이 동의한 뒤에만 작동해요. 그래서 거기 나오는 숫자는 최솟값이기도 해요. 실제 페이지 조회 수는 네트워크 제공업체의 익명 합계를 봐요.
자세한 내용은 개인정보 처리방침에 있어요.
우리가 얻은 것
비싼 건 고장 난 게 아닌 경우가 많아요. 위에서 찾은 것 중 오류를 낸 건 하나도 없었어요. 부하, 비용, 소음을 냈을 뿐이고, 측정하지 않으면 그중 어느 것도 보이지 않아요.
서버마다 물어보는 방식은 확장되지 않아요. 큰 발견 두 개는 같은 패턴이었어요: 모든 서버를 돌면서 하나하나 따로 묻는 반복 작업이요. 답은 거의 언제나, 같은 질문을 모두에게 한 번만 묻는 거예요.
경보는 드물어야 경보예요. 그래서 팀을 호출하는 건 Grafana뿐이고, 그것도 누군가 개입해야 하는 일에만 그래요. PostHog의 새로운 오류 유형은 핑 없이 채널에 올라가요.
직접 Discord 서버를 운영하고 있고, 여기서 언급한 모듈을 보고 싶다면: 투표, 지원 기록, 부재는 웹 패널에 있고, 문서에 설명되어 있어요.
더 많은 글
AI 제공업체가 모델을 종료했을 때
모델 교체, 오류 없이 돌아온 빈 답변, 그리고 갑자기 몇 배로 뛴 청구서. 무엇이 고장 났는지, 그리고 원인이 왜 그렇게 보이지 않았는지 이야기해요.
비하인드2,000개가 넘는 Discord 서버에서 봇을 운영하며 배운 것
코드를 쓸 때 생각하는 것과 실제 규모에서 다르게 작동하는 네 가지를 이야기해요.
비하인드AlphaCloud가 거의 모든 기능을 무료로 두는 이유
대부분의 Discord 봇은 가장 유용한 기능을 구독 뒤에 잠가 둬요. 우리는 일부러 그러지 않아요. 그리고 그건 생각보다 너그러움과는 별 관계가 없어요.