crontab으로 DB 백업 자동화하기

2025. 7. 8. 18:59·프로젝트/빼곡

백엔드 개발자를 목표하다보면, 한번씩 듣게되는 무서운 이야기가 있다.

바로 데이터베이스를 날려버린 개발자의 괴담....!!!

물론 실무에서는 미숙한 개발자가 쉽게 DB를 날려버리지는 않게끔 권한을 짜뒀겠지만, 아무튼 무서운 이야기이다.

 

그리고 이외에도 DB엔 다양한 변수가 있을수있다. 대표적으로 최근 이슈였던 예스24의 랜섬웨어 감염으로 인한 장애가 있었다.

고객정보 등 핵심데이터를 암호화해 못쓰게 만들었다고...😮

 

 

아무튼 이런 문제의 예방도 중요하지만, 발생했을때 복구 방안 또한 중요할것이다.

그래서 나는 우선적으로 정기적인 DB백업 자동화를 도입하기로 했다

안전한 외부 서버에 데이터를 저장해 백업용도로 사용할 예정이다.

 

 


 

백업을 위한 다양한 방법

db백업을 외부에 저장하는 방식은 다음과같이 떠올릴 수 있었다.

 

  • mysqldump + 원격 전송 (rsync / scp 등)
    가장 기본적인 방식이다. mysqldump 명령어를 통해 DB를 SQL 스크립트 형태로 백업한 뒤, scp나 rsync를 이용해 외부 서버로 전송한다. 간단하지만 강력하며, shell 스크립트를 통해 자동화하기도 좋다.
  • S3 등의 클라우드 스토리지 업로드
    백업 데이터를 AWS S3, Google Cloud Storage, Azure Blob 등에 업로드해 두는 방식. 비용이 들긴 하지만 내구성과 안정성이 높아 실무에서 많이 활용된다. aws s3 cp 등의 CLI 도구로 쉽게 구현 가능하다.
  • Percona XtraBackup, MariaDB Backup 등 고급 툴 사용
    대용량 트랜잭션 DB에 적합한 오픈소스 툴. mysqldump보다 빠르며, 실시간 백업 및 복구 성능이 뛰어나다. 다만 학습 곡선이 존재하고 설정이 복잡할 수 있다.
  • Docker Volume 스냅샷 + 파일 동기화
    도커 기반의 서비스에서는 volume 자체를 압축하거나 스냅샷을 찍은 뒤 외부로 보내는 방식도 있다. 특히 restic, duplicity, borg 같은 툴과 함께 사용하면 증분 백업도 가능하다.

 

나는 이중에서도 가장 기본적인 방식인 1번방식을 사용해보고자 했다.

 

 

 

 

크론탭을 활용해 DB 백업 자동화하기

백업작업을 수동으로 하는것은 매우 귀찮으니...ㅎㅎ 크론탭을 활용해 매일 정해진 시간에 자동 백업되도록 구성했다.

 

크론탭 등록

# backup
30 18 * * * /usr/local/bin/db-backup.sh

 

우선 위와같이 크론탭에 등록하여, 매일 새벽 3시30분에 백업을 진행하는 스크립트를 실행했다(서버가 UTC시간이다)

핵심 로직은 /usr/local/bin/db-backup.sh 스크립트에 들어있다.

 

스크립트 작성

스크립트의 핵심로직은 다음과 같이 구성하였다.

 

(1) 환경변수 및 path 설정

(2) DB 덤프 수행

(3) rysnc를 통한 외부서버 전송

(4) 백업 알림 전송

 

순서대로 살펴보자.

 

(1) 환경변수 및 path 설정

source $HOME/.discord.env
source $HOME/.backup.env
  • cron 환경에서는 $PATH나 .env 파일이 무시되기 때문에, 스크립트 상단에서 절대경로로 .env 파일 2개를 명시적으로 불러오고 PATH도 수동으로 설정했다.

 

(2) DB 덤프 수행(Docker 컨테이너 내부)

mysqldump -u$MYSQL_USER -p$MYSQL_PASSWORD --single-transaction --quick $DB | gzip > "$DUMP_FILE"
  • docker exec를 통해 MySQL 컨테이너 내부에서 직접 SHOW DATABASES로 대상 DB를 추출한다.
  • mysqldump로 각각 SQL 덤프를 수행하고 .sql.gz로 압축 저장한다.
  • information_schema, mysql, sys 같은 시스템 DB는 제외했다.

 

 

(3) rysnc를 통한 외부서버 전송

rsync -az -e "ssh" "$DUMP_DIR/" "backup-server:$REMOTE_DUMP_DIR"
  • 외부 백업 서버에 ssh로 접속하여 날짜별 디렉토리를 생성
  • rsync -az를 사용해 효율적으로 압축 전송
  • 실패 시 알림을 보내고 스크립트를 종료하여 알 수 없는 상태를 방지
 

 

(4) 백업 알림 전송

curl -X POST -H "Content-Type: application/json" -d "{\"content\": \"$MESSAGE\"}" "$DISCORD_WEBHOOK_URL"
  • 각 단계마다 현재 상태를 Discord Webhook으로 전송해 실시간 모니터링이 가능하도록 했다.
  • 성공/실패 여부도 바로 확인 가능하다.

 

더보기

(CF) 스크립트 전문

# ─────────────────────────────
# 0. 공통 로그 파일 지정
# ─────────────────────────────
LOG_FILE="/tmp/db-debug.log"
exec >> "$LOG_FILE" 2>&1
echo -e "\n===== [$(date)] DB 백업 스크립트 시작 ====="

# ─────────────────────────────
# 1. 환경 변수 불러오기 (절대 경로로!)
# ─────────────────────────────
ENV1="$HOME/.discord.env"
ENV2="$HOME/.backup.env"

if [[ -f "$ENV1" && -f "$ENV2" ]]; then
  source "$ENV1"
  source "$ENV2"
else
  echo "환경 파일을 찾을 수 없습니다."
  exit 1
fi

# ─────────────────────────────
# 2. PATH 설정 (cron용)
# ─────────────────────────────
export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"

# ─────────────────────────────
# 3. 디스코드 전송 함수
# ─────────────────────────────
function send_discord() {
  local MESSAGE="$1"
  echo "[DISCORD] $MESSAGE"
  curl -s -H "Content-Type: application/json" \
    -X POST -d "{\"content\": \"$MESSAGE\"}" \
    "$DISCORD_WEBHOOK_URL" > /dev/null || echo "Discord 전송 실패"
}

# ─────────────────────────────
# 4. 백업 디렉토리 설정
# ─────────────────────────────
TODAY=$(date +%F)
DUMP_DIR="$LOCAL_DUMP_BASE_DIR/$TODAY"
mkdir -p "$DUMP_DIR"

# ─────────────────────────────
# 5. MySQL DB 덤프
# ─────────────────────────────
send_discord "**[$TODAY] DB 백업 시작**"
send_discord "(1) DB 덤프 시작"

echo "[INFO] Docker 컨테이너: $MYSQL_CONTAINER_NAME"
DB_LIST=$(docker exec "$MYSQL_CONTAINER_NAME" \
  mysql -u"$MYSQL_USER" -p"$MYSQL_PASSWORD" -e "SHOW DATABASES;" | \
  grep -Ev "Database|information_schema|performance_schema|mysql|sys") || {
    echo "DB 목록 조회 실패"
    send_discord "DB 목록 조회 실패"
    exit 1
}

for DB in $DB_LIST; do
  DUMP_FILE="$DUMP_DIR/${DB}.sql.gz"
  echo "[mysqldump] dumping $DB → $DUMP_FILE"
  docker exec "$MYSQL_CONTAINER_NAME" \
    sh -c "mysqldump -u$MYSQL_USER -p$MYSQL_PASSWORD --single-transaction --quick $DB" \
    | gzip > "$DUMP_FILE" || echo "덤프 실패: $DB"
done

send_discord "(2) DB 덤프 완료"

# ─────────────────────────────
# 6. 원격 rsync 전송
# ─────────────────────────────
REMOTE_DUMP_DIR="$REMOTE_DUMP_DIR_BASE/$TODAY"
echo "[rsync] 전송: $DUMP_DIR → backup-server:$REMOTE_DUMP_DIR"

ssh backup-server "mkdir -p $REMOTE_DUMP_DIR" || {
  echo "원격 디렉토리 생성 실패"
  send_discord "원격 디렉토리 생성 실패"
  exit 1
}

send_discord "(3) rsync 전송 시작"

if rsync -az -e "ssh" "$DUMP_DIR/" "backup-server:$REMOTE_DUMP_DIR"; then
  send_discord "(4) rsync 전송 완료"
else
  echo "rsync 실패"
  send_discord "(4) rsync 실패"
  exit 1
fi

send_discord "🎉 DB 백업 완료 🎉"
echo "===== [$(date)] DB 백업 완료 ====="

 


 

 

 

이렇게 매일 새벽 DB를 자동으로 백업하는 시스템을 구축할 수 있었다!

또 이렇게 구축해놓고 보니 백업은 정말 선택이 아닌 필수임을 느꼈다ㅎㅎ 실제 프로덕션을 운영하다보니 사용자 데이터 관리에 있어 항상 불안함을 가지고 살았는데, 백업DB가 있다고 생각하니 마음이 훨씬 놓였다.

또, cron과 shell 스크립트만으로도 간단하지만 확장성있게 구성할 수 있음을 느꼈고, 백업 현황을 디스코드 알림을 통해 확인 할 수 있게 만든점이 효용성 측면에서 좋다고 느끼게 되었다.

 

시스템을 운영함에 있어 예방만큼 중요한것은 복구다. 실수를 100% 막을수는 없지만, 복구를 통해 언제나 만족스러운 서비스를 만드는것이 개발자의 책임이라고 생각한다. 향후엔 증분 백업 도입이나 백업파일 암호화 등 보다 효율적인 시스템을 추가해볼 계획이다ㅎㅎ

 

 

 

'프로젝트 > 빼곡' 카테고리의 다른 글

Nginx 리버스 프록시 구현을 통해 엔드포인트 분리하기  (0) 2025.06.04
Metabase로 애널리틱스 대시보드 구축하기  (1) 2025.05.22
Bean일까 Util일까, CookieUtil 리팩토링하기  (1) 2025.03.08
빼곡 스토어 출시! 그리고 개선방향(feat.코드리뷰)  (1) 2025.03.08
Spring 명시적 Null값으로 부분 업데이트(PATCH) 구현하기  (9) 2025.01.02
'프로젝트/빼곡' 카테고리의 다른 글
  • Nginx 리버스 프록시 구현을 통해 엔드포인트 분리하기
  • Metabase로 애널리틱스 대시보드 구축하기
  • Bean일까 Util일까, CookieUtil 리팩토링하기
  • 빼곡 스토어 출시! 그리고 개선방향(feat.코드리뷰)
▹ 서현서현
▹ 서현서현
좋아하는걸 마음껏하는 백엔드 개발자😎
  • ▹ 서현서현
    Circus
    ▹ 서현서현
  • 전체
    오늘
    어제
    • 분류 전체보기 (35)
      • 회고 (2)
      • 프로젝트 (22)
        • 빼곡 (11)
        • SEMENTO (2)
        • FindDog (1)
        • 척척약사 (1)
        • 차곡차곡 (2)
        • 원더웨이 (3)
        • 트래블 캐리어 (2)
      • 알고리즘 (4)
      • 기타 (2)
      • CS (4)
        • Spring (2)
        • 대규모 시스템 설계 (2)
  • 링크

    • 👾 Github
    • 🧩 Algorithm
  • 공지사항

    • 블로그를 이전했습니다 💖
  • 인기 글

  • hELLO· Designed By정상우.v4.10.1
▹ 서현서현
crontab으로 DB 백업 자동화하기
상단으로

티스토리툴바