복구봇 DB 설계와 운영 가이드

2026년 5월 13일·8개 메시지

이 글은 디스코드 봇 복구용 데이터베이스를 디스호스트 같은 호스팅에 두고 운영할 때 발생할 수 있는 문제와 실무적인 해결책을 정리한 내용이다. 저장 용량·성능 한계에 대응하는 최적화 방법과 MongoDB를 이용한 자동 삭제·압축 전략을 중심으로 설명한다.

증상

디스코드 봇이 수집하는 복구 관련 로그·유저 데이터가 빠르게 쌓여 호스팅 인스턴스의 디스크를 채운다. 결과적으로 DB 성능 저하, 쓰기 지연, 인스턴스 재시작 시 데이터 손실 위험, 백업 실패 같은 문제가 발생한다. 특히 대용량 파일(첨부, 스냅샷)을 같이 저장하면 문제가 급격히 악화된다.

원인

디스호스트 같은 범용 호스팅 인스턴스는 디스크 용량과 I/O가 제한적이다. 로그성 데이터는 계속 증가하는 특성이 있어 적절한 보존 정책이 없으면 용량이 빠르게 소모된다. 또한 스키마·인덱스 설계가 비효율적이면 불필요한 중복 저장과 느린 쿼리가 발생한다. 대용량 바이너리(첨부)는 DB에 직접 저장하면 공간과 성능 부담이 커진다.

해결 방법

1단계: 요구량 산정 및 아키텍처 결정

  • 우선 하루/주/월 단위로 생성되는 레코드 수와 평균 레코드 크기를 추정해 총 저장량을 계산한다.
  • 첨부나 스냅샷 같은 큰 데이터는 DB가 아닌 오브젝트 스토리지(S3 호환)로 분리하고 DB에는 URL/메타만 저장한다.
  • 디스호스트 환경에 DB를 직접 두는 대신 외부 매니지드 DB(MongoDB Atlas 등)를 고려한다. 매니지드 서비스는 자동 백업·스케일링·모니터링에서 이점이 있다.

2단계: MongoDB 사용 및 보존 정책 적용

  • MongoDB가 스키마 유연성과 TTL 기능 때문에 복구봇 로그 저장에 수월하다. 다음은 TTL 인덱스를 만들어 자동으로 오래된 데이터를 삭제하는 예시:
// MongoDB shell
db.recoveryLogs.createIndex({ createdAt: 1 }, { expireAfterSeconds: 60*60*24*30 }) // 30일 보관
  • Mongoose 예시(스키마에 createdAt와 TTL 설정):
const mongoose = require('mongoose');

const logSchema = new mongoose.Schema({
  userId: String,
  action: String,
  data: Object,
  createdAt: { type: Date, default: Date.now, index: true }
});

logSchema.index({ createdAt: 1 }, { expireAfterSeconds: 60*60*24*30 }); // 30일
module.exports = mongoose.model('RecoveryLog', logSchema);
  • 대용량 로그는 capped collection 또는 배치 합치기(aggregation)로 압축 저장한다:
db.createCollection("recentLogs", { capped: true, size: 104857600 }); // 100MB 제한

3단계: 저장 최적화와 운영 자동화

  • 불필요한 필드는 제거하고 중복을 줄여 레코드 크기를 줄인다. 인덱스는 필요한 컬럼에만 생성한다.
  • 쓰기 부하가 높다면 배치 쓰기(BulkWrite)로 묶어 처리해 IOPS를 줄인다.
  • 중복 탐지와 이벤트 필터링으로 동일 데이터 반복 저장을 막는다.
  • 오래된 데이터는 아카이브 정책을 적용해 저비용 스토리지로 내보내고, 필요 시 복원하도록 자동화 스크립트를 만든다.
  • 모니터링: 디스크 사용량, I/O, 연결수, 큐 지연을 모니터링하고 임계치에 알람 설정한다.

4단계: 백업·복구 및 테스트

  • 정기 증분 백업과 온디맨드 백업을 설정하고 복원 테스트를 주기적으로 수행한다.
  • 재해 복구 시나리오(호스팅 장애, DB 손상)를 문서화하고 역할 분담을 정해둔다.

마무리

디스코드 봇의 복구 DB를 디스호스트 같은 범용 호스팅에 그대로 쌓는 것은 용량·I/O 한계 때문에 위험이 크다. MongoDB의 TTL, capped collection, 외부 오브젝트 스토리지 분리, 배치 최적화와 같은 전략을 적용하면 안정적으로 운영할 수 있다.