turin.blog
← 전체 글로 돌아가기

practical debugging note

작은 VPS 백업 복구를 실제로 한 번 돌려본 회고

백업 파일이 있다는 사실만 믿고 있다가 임시 서버에서 복구 리허설을 해 보며 발견한 빠진 설정과 점검 순서를 적었습니다.

빠른 요약

백업이 있다는 말만으로는 부족했다 처음에는 매일 새벽 DB 덤프가 만들어지고 있으니 어느 정도 안심했다.

이 글에서 확인할 것
  • 백업이 있다는 말만으로는 부족했다
  • 리허설 순서
  • 파일보다 환경 변수가 더 오래 걸렸다
  • 리허설 뒤 바꾼 백업 메모
  • 남긴 결론

백업이 있다는 말만으로는 부족했다

처음에는 매일 새벽 DB 덤프가 만들어지고 있으니 어느 정도 안심했다. 그런데 서버 이전을 준비하면서 "이 파일로 진짜 복구가 되나?"라는 질문에 바로 답을 못 했다. 그래서 운영 서버를 건드리지 않고 임시 VPS 하나를 만들어 복구 리허설을 했다.

가장 당황한 부분은 덤프 파일 자체보다 주변 설정이었다. 데이터베이스는 올라왔는데 앱이 읽는 환경 변수 이름이 예전 문서와 달랐다.

리허설 순서

내가 사용한 흐름은 단순했다.

scp backup-2026-06-26.sql.gz user@temp-server:/tmp/
ssh user@temp-server
mkdir -p ~/restore-test
cd ~/restore-test

그 다음 컨테이너를 최소 구성으로 띄웠다.

gunzip -c /tmp/backup-2026-06-26.sql.gz > dump.sql
docker compose up -d db
docker compose exec -T db psql -U app app < dump.sql

복구가 끝났다고 바로 성공 처리하지 않고, 실제 앱이 필요한 테이블 수와 최근 데이터 몇 개를 확인했다.

docker compose exec db psql -U app app -c "select count(*) from posts;"
docker compose exec db psql -U app app -c "select created_at, title from posts order by created_at desc limit 3;"

파일보다 환경 변수가 더 오래 걸렸다

복구 중 발견한 빠진 항목은 세 가지였다.

  • .env.example에 운영에서만 쓰는 DATABASE_SSL 설명이 없었다.
  • 업로드 파일 경로를 DB 덤프와 별도로 보관해야 했다.
  • 새 서버의 타임존이 UTC라 로그 시간이 운영 기록과 어긋났다.

특히 업로드 파일은 DB 안에 경로만 있고 실제 파일은 볼륨에 있었다. 덤프만 잘 떠도 이미지가 깨질 수 있다는 뜻이다.

리허설 뒤 바꾼 백업 메모

백업 스크립트 옆에 복구 명령도 같이 적었다. 그리고 백업 성공 로그에 파일 크기만 남기지 않고, 마지막으로 복구 테스트한 날짜를 따로 기록하기로 했다.

du -h /backup/latest.sql.gz
ls -lh /backup/uploads-latest.tar.gz

남긴 결론

백업은 "언젠가 필요하면 쓰겠지"가 아니라 "새 서버에서 몇 분 안에 재현할 수 있는 절차"에 가까웠다. 작은 서비스라도 복구 리허설을 한 번 해 두면, 장애가 났을 때 검색부터 시작하지 않아도 된다.