백업 전략: full/incremental, logical/physical, snapshot, 보존 정책
백업 파일은 복구 능력이 아니다
"매일 새벽 3시에 백업이 돌아요"는 운영 현장에서 자주 듣는 말이다. 그 백업이 실제로 복구에 쓰일 수 있는지 — 어떤 시점으로, 몇 분 안에, 어디에서 — 는 별개의 질문이다.
AWS Well-Architected가 강조하는 것처럼, 백업 자동화만큼 중요한 것은 주기적 복구 테스트다. 백업이 성공해도 restore가 실패하는 경우는 실무에서 드물지 않다. 백업 파일이 손상됐거나, restore 절차가 문서화되지 않았거나, 복구 후 검증을 안 해본 경우다.
이 장에서는 백업 방식의 종류와 트레이드오프를 정리하고, PITR을 위한 WAL/binlog 연계 방식, 보존 정책, 복구 테스트까지 다룬다.
백업의 두 축: 논리적 vs 물리적
백업 도구를 고를 때 가장 먼저 결정해야 하는 것은 논리적 백업과 물리적 백업 중 어느 것을 주 백업으로 쓸지다.
출력: SQL 스크립트 또는 커스텀 포맷
백업 속도: 중간
복구 속도: 느림 (INSERT 재실행)
크기: 상대적으로 작음
이식성: 높음 (버전 간 마이그레이션) ✓ 부분 복구, 특정 테이블만 추출 가능
✗ 수백 GB이면 복구에 수 시간 소요
✗ PITR 단독 지원 어려움
출력: 데이터 파일 바이너리 복사본
백업 속도: 빠름 (hot backup, 논블로킹)
복구 속도: 빠름 (파일 복사 후 복구 적용)
크기: 큼 (데이터파일 전체)
이식성: 낮음 (동일 버전/아키텍처) ✓ 대용량 DB의 유일한 현실적 선택
✓ WAL/binlog와 결합해 PITR 가능
✗ 메이저 버전 업그레이드 시 사용 불가
소규모/개발 DB → 논리적 백업으로 충분할 수 있음
규모별 복구 시간 비교
Percona 벤치마크에 따르면 500GB 데이터베이스를 복구할 때 mysqldump는 복구에 10시간 이상 소요되지만, XtraBackup을 쓰면 1시간 이내가 가능하다. RTO가 4시간인 서비스라면 mysqldump만으로는 RTO를 맞출 수 없다.
| 도구 | 500GB 백업 시간 | 500GB 복구 시간 | PITR 지원 |
|---|---|---|---|
| mysqldump | ~2시간 | ~10시간 | binlog 수동 적용 필요 |
| XtraBackup (full) | ~30분 | ~1시간 | binlog 자동 연계 |
| XtraBackup (incremental) | ~5분/일 | 전체: ~1시간 + 증분 적용 | 동일 |
| pg_dump | ~1–2시간 | ~4–8시간 | 단독 불가 |
| pg_basebackup + WAL | ~30분 | ~30분 + WAL replay | 기본 지원 |
| pgBackRest (incremental) | ~5분/일 | 빠름 (병렬) | 완전 지원 |
Full vs Incremental vs Differential
물리적 백업 안에서도 방식이 나뉜다.
Full backup: 전체 데이터파일을 복사하는 완전한 독립 백업이다. 복구 시 가장 단순하다(이 파일 하나만 있으면 된다). 단점은 크기와 시간이다.
Incremental backup: 마지막 full 또는 마지막 incremental 이후 변경된 페이지만 복사한다. 백업 시간과 크기는 줄지만, 복구 시 full + 모든 incremental을 순서대로 적용해야 한다.
Differential backup: 마지막 full 이후 변경된 전체를 복사한다. Incremental보다 크지만 복구 시에는 full + 마지막 differential만 있으면 된다.
(Mon 이후) → Wed Diff
(Mon 이후)
실무에서 가장 많이 쓰는 패턴은 주 1회 Full + 매일 Incremental이다. Full은 주말 트래픽이 낮은 시간에 실행하고, 나머지 6일은 incremental로 처리한다.
PITR: 특정 시점으로 돌아가기
Incremental backup이 "어제까지의 변경"을 복구한다면, PITR(Point-in-Time Recovery)는 "어제 오후 2시 34분 22초까지의 변경"을 복구할 수 있다. 실수로 DELETE 문을 잘못 실행한 직전 시점으로 정확히 복구하는 데 쓰인다.
PITR은 base backup + 연속 로그 스트림으로 구성된다.
↓
WAL / binlog 생성
일요일 02:00 Incremental
월~토 02:00 binlog / WAL
실시간 스트리밍
mysqlbinlog --stop-datetime="2026-06-26 14:33:00"PostgreSQL:
recovery_target_time = '2026-06-26 14:33:00'
MySQL PITR 요구사항
-- binary log가 활성화되어 있어야 한다
SHOW VARIABLES LIKE 'log_bin';
-- ON이어야 함
-- binlog 보존 기간 확인 (MySQL 8.0+)
SHOW VARIABLES LIKE 'binlog_expire_logs_seconds';
-- RPO보다 충분히 길어야 함 (예: 7일 = 604800)XtraBackup은 백업 완료 시 xtrabackup_binlog_info 파일에 백업 완료 시점의 binlog 파일명과 포지션을 기록한다. 복구 시 이 정보를 기준으로 binlog를 순서대로 apply한다.
PostgreSQL PITR 요구사항
-- WAL 아카이빙이 활성화되어 있어야 한다
SHOW archive_mode; -- on 이어야 함
SHOW wal_level; -- replica 이상이어야 함
-- 복구 설정 (postgresql.conf 또는 recovery.conf)
-- restore_command = 'cp /backup/wal/%f %p'
-- recovery_target_time = '2026-06-26 14:33:00'
-- recovery_target_action = 'promote'pgBackRest는 pg_basebackup의 기능에 병렬 복원, 증분 백업, S3/GCS 직접 연동, 보존 정책 자동화까지 지원하여 프로덕션 환경에서 사실상 표준 도구다.
스냅샷 백업
스냅샷 백업은 스토리지 레이어에서 볼륨의 시점 이미지를 순간 생성하는 방식이다. AWS EBS Snapshot, GCP Persistent Disk Snapshot, LVM Snapshot이 대표 예다.
장점:
- 거의 순간적으로 완료 (수 분 이내)
- 데이터베이스 에이전트 없이 인프라 수준에서 실행 가능
- 물리적 백업보다 DB 설정이 간단
한계:
- PITR이 안 된다. 스냅샷 생성 시점으로만 돌아갈 수 있다.
- DB가 스냅샷 중 I/O 일관성을 보장하지 않을 수 있다 (pre-freeze/post-thaw 처리 필요).
- MySQL:
FLUSH TABLES WITH READ LOCK또는 InnoDB hot backup이 병행되어야 일관된 스냅샷 가능 - PostgreSQL:
pg_start_backup()/pg_stop_backup()호출로 일관성 보장 필요 (PostgreSQL 15 이하), 15+에서는pg_backup_start()
실무에서는 물리적 백업 + 스냅샷을 함께 쓰는 경우가 많다. 물리적 백업은 PITR용으로, 스냅샷은 빠른 시스템 복구용으로 구분한다.
보존 정책: GFS와 3-2-1
GFS(Grandfather-Father-Son) 보존 정책
GFS는 세 계층의 보존 기간을 정의해 스토리지를 효율적으로 사용하는 가장 널리 쓰이는 방식이다.
| 계층 | 백업 | 보존 기간 | 스토리지 |
|---|---|---|---|
| Son (일별) | 매일 incremental | 7–14일 | 로컬 / hot 스토리지 |
| Father (주별) | 주 1회 full | 4–6주 | warm 스토리지 |
| Grandfather (월별) | 월 1회 full | 12–24개월 | cold 스토리지 / 오프사이트 |
예: 토요일 full 백업 → father로 승격
해당 주의 son들은 순차 삭제
월말 father → grandfather로 승격GFS를 쓰면 "어제 데이터"는 빠르게, "6개월 전 데이터"는 cold에서 꺼내는 구조로 비용과 복구 가용성을 균형 있게 유지할 수 있다.
3-2-1 규칙
GFS와 함께 자주 언급되는 3-2-1 규칙은 오프사이트 보호를 강제한다.
= 총 3벌의 데이터
(EBS + S3 / 로컬 + 클라우드)
다른 리전 / 사이트
보존 기간 결정 기준
보존 기간은 비즈니스와 합의해야 하는 값이다. 일방적으로 DBA가 정하면 안 된다.
| 기준 | 예시 |
|---|---|
| RPO 요구사항 | RPO 5분이면 binlog/WAL 보존도 5분 이내 전송 |
| 규제 요건 | 개인정보보호법, 금융/의료 규정에 따른 최소 보존 기간 |
| 논리적 손상 탐지 시간 | 버그 배포 후 데이터 오염을 몇 주 뒤에 발견할 수 있다 |
| 스토리지 비용 | cold 스토리지 단가 × 예상 증분 크기 |
함정: "30일 보관"이라고 정했더니 논리적 손상이 45일 뒤에 발견됐다. 이런 경우 30일 보관 정책은 복구 불가능을 의미한다. 규정 준수 이외의 이유로 보존 기간을 정할 때는 "이 DB에서 데이터 이상을 탐지할 수 있는 최대 경과 시간"을 기준으로 잡는 것이 더 안전하다.
복구 테스트: 가장 자주 빠지는 단계
"백업은 있는데 복구는 해봤나요?"라는 질문에 "아직요"라는 답이 나오는 경우가 많다.
복구 테스트 없는 백업은 미검증 가설이다.
복구 테스트 절차
1. 격리된 환경(staging, 별도 인스턴스)에서 진행 — 프로덕션에 절대 restore하지 않는다
2. 백업 저장소에서 파일 다운로드 (속도 측정 포함)
3. DB 엔진에 restore 실행
MySQL: xtrabackup --copy-back ...
PostgreSQL: pgBackRest restore --stanza=...
4. 복구 완료 후 검증
- checksum 비교 (mysqldump --tables 또는 pg_dump 일부)
- row count 확인 (핵심 테이블 3–5개)
- 애플리케이션 smoke test (읽기/쓰기 각 1개)
5. PITR 테스트
- 특정 시점까지 복구 후 해당 시점 데이터가 맞는지 확인
6. 시간 기록: 다운로드 N분, restore N분, 검증 N분 → 실제 RTO 측정권장 주기: Tier-1 DB는 월 1회 전체 복구 테스트, Tier-2는 분기 1회. 자동화가 가능하면 매주 staging restore + checksum 검증 파이프라인을 구성한다.
실전 백업 아키텍처 예시
아래는 MySQL 프로덕션 환경의 일반적인 백업 구성이다.
매일 02:00: XtraBackup incremental → S3 (압축·암호화)
매주 일 02:00: XtraBackup full → S3 (GFS father 보존 4주)
매월 1일 02:00: 해당 주 full → S3 Glacier (GFS grandfather 보존 12개월)
실시간: binlog → S3 (5분 단위 flush, 7일 보존)
검증: 매주 월 04:00 staging 인스턴스에 auto-restore + row count 확인
알림: 백업 실패 → PagerDuty P2
restore 검증 실패 → PagerDuty P1PostgreSQL의 경우 pgBackRest를 쓰면 이 구성을 단일 도구로 관리할 수 있다.
운영 체크리스트
백업 구성 확인
- [ ] 백업 방식(논리/물리)과 RTO 요구사항이 맞는가?
- [ ] PITR이 필요한가? → binlog(MySQL) / WAL archive(PostgreSQL) 활성화 여부
- [ ] binlog/WAL 보존 기간이 RPO보다 충분히 긴가?
- [ ] 백업 파일이 암호화되는가?
- [ ] 오프사이트 또는 다른 리전에 복사본이 있는가?
- [ ] GFS 또는 명시적 보존 정책이 자동화되어 있는가?
- [ ] 백업 실패 알림이 있는가?
복구 준비 확인
- [ ] restore 절차가 문서화되어 있는가?
- [ ] 마지막으로 실제 복구 테스트를 한 날짜를 아는가?
- [ ] 테스트에서 측정한 실제 RTO가 요구사항보다 짧은가?
- [ ] PITR 테스트를 포함한 복구 검증을 했는가?
- [ ] restore 환경(인스턴스, 네트워크, 권한)이 사전에 준비되어 있는가?
기억할 문장
백업의 목적은 파일을 만드는 것이 아니라 특정 시점으로 복구하는 능력을 유지하는 것이다. 백업 성공 알림이 복구 성공을 보장하지 않는다. 복구 테스트 없이는 백업이 있다고 말할 수 없다.
다음 장에서는 복구 전략의 핵심인 RTO/RPO, PITR 설계, 복구 리허설, 복구 후 검증까지 더 깊이 다룬다.
References
- AWS Well-Architected Framework, Reliability Pillar — Back up data — https://docs.aws.amazon.com/wellarchitected/latest/reliability-pillar/back-up-data.html
- Percona Blog, Backup/Restore Performance: mysqldump vs XtraBackup — https://www.percona.com/blog/backup-restore-performance-conclusion-mysqldump-vs-mysql-shell-utilities-vs-mydumper-vs-mysqlpump-vs-xtrabackup/
- Percona XtraBackup, Point-in-Time Recovery — https://docs.percona.com/percona-xtrabackup/8.0/point-in-time-recovery.html
- PostgreSQL Documentation, Continuous Archiving and PITR — https://www.postgresql.org/docs/current/continuous-archiving.html
- pgBackRest User Guide — https://pgbackrest.org/user-guide.html
- Nakivo, GFS Backup Retention Policy Explained — https://www.nakivo.com/blog/gfs-retention-policy-explained/
- Backblaze Blog, What Is the Grandfather-Father-Son Approach? — https://www.backblaze.com/blog/better-backup-practices-what-is-the-grandfather-father-son-approach/
- Crunchydata Blog, Introduction to Postgres Backups — https://www.crunchydata.com/blog/introduction-to-postgres-backups