#!/bin/bash # 이 파일이 하는 일: 백업 파일로 DB를 되돌린다. # # 학습 포인트 — "복원해 본 적 없는 백업은 백업이 아니다." # 백업 스크립트를 짜두고 안심하다가, 정작 사고가 났을 때 복원이 안 되는 일이 실제로 자주 있다. # (덤프가 비어 있었거나, 복원 명령을 아무도 몰랐거나, 권한이 없었거나…) # 그래서 백업 스크립트를 만들면 복원 스크립트도 같이 만들고, 한 번은 실제로 돌려봐야 한다. # # 사용법: # ./restore-db.sh # 백업 목록 보기 # ./restore-db.sh mirim-2026-07-17_030000.sql.gz # 그 파일로 복원 set -euo pipefail BUCKET="awesomedev-mirim-backup-apne2" CONTAINER="mirim-postgres" DB_NAME="mirim" DB_USER="mirim" BACKUP_DIR="/home/ec2-user/backups" # 인자가 없으면 어떤 백업이 있는지 보여주고 끝낸다. if [ $# -eq 0 ]; then echo "=== 서버 로컬 백업 ===" ls -lh "$BACKUP_DIR"/mirim-*.sql.gz 2>/dev/null || echo " (없음)" echo "" echo "=== S3 백업 (최근 10개) ===" aws s3 ls "s3://${BUCKET}/postgres/" | tail -10 || echo " (없음)" echo "" echo "사용법: $0 <파일이름>" echo " 예: $0 mirim-2026-07-17_030000.sql.gz" exit 0 fi FILENAME="$1" LOCAL_PATH="${BACKUP_DIR}/${FILENAME}" # 로컬에 없으면 S3에서 받아온다. if [ ! -f "$LOCAL_PATH" ]; then echo "로컬에 없어 S3에서 내려받습니다: ${FILENAME}" aws s3 cp "s3://${BUCKET}/postgres/${FILENAME}" "$LOCAL_PATH" fi # ⚠️ 되돌릴 수 없는 작업 앞에는 반드시 확인을 세운다. # 학습 포인트: rm -rf, DROP TABLE, 복원처럼 "되돌리기 어려운 명령"은 # 사람이 한 번 더 눈으로 확인하게 만든다. 자동화의 예외를 두는 지점이다. echo "" echo "⚠️ 현재 DB(${DB_NAME})의 데이터를 백업 시점으로 되돌립니다." echo " 파일: ${FILENAME}" echo " 지금 DB에만 있는 최신 데이터(학생 진도·제출물)는 사라집니다." read -p "정말 진행할까요? (yes 입력): " CONFIRM if [ "$CONFIRM" != "yes" ]; then echo "취소했습니다." exit 0 fi # 복원 전에 "지금 상태"를 한 번 더 백업해 둔다 — 복원이 잘못됐을 때 돌아올 자리. # 학습 포인트: 복원도 실수할 수 있다. 되돌리기의 되돌리기를 준비해 두는 것이 프로다. SAFETY="${BACKUP_DIR}/before-restore-$(date +%Y-%m-%d_%H%M%S).sql.gz" echo "복원 전 현재 상태를 저장합니다: ${SAFETY}" docker exec "$CONTAINER" pg_dump -U "$DB_USER" -d "$DB_NAME" | gzip > "$SAFETY" # 복원: 기존 스키마를 지우고 덤프를 그대로 흘려 넣는다. # 학습 포인트: pg_dump 결과는 그냥 SQL 문장 모음이라, psql에 파이프로 먹이면 그대로 재현된다. echo "복원 중..." docker exec -i "$CONTAINER" psql -U "$DB_USER" -d "$DB_NAME" -c "DROP SCHEMA public CASCADE; CREATE SCHEMA public;" > /dev/null gunzip -c "$LOCAL_PATH" | docker exec -i "$CONTAINER" psql -U "$DB_USER" -d "$DB_NAME" > /dev/null echo "복원 완료 ✅" echo "확인:" docker exec "$CONTAINER" psql -U "$DB_USER" -d "$DB_NAME" -t -c \ "SELECT ' 사용자 '||count(*)||'명' FROM users UNION ALL SELECT ' 퀴즈문항 '||count(*)||'건' FROM quiz_question;" echo "" echo "백엔드를 재시작하세요: cd ~/mirim-app/deploy && docker compose -f docker-compose.prod.yml restart backend"