백업과 복구
데이터를 만드는 것이 백업이 아닙니다. 되살려 봐야 백업입니다. 그 차이는 사고 후에야 드러납니다. PostgreSQL 의 도구·정책·리허설을 정리합니다.
목차
데이터를 만드는 것이 백업이 아닙니다. 되살려 봐야 백업입니다. 그 차이는 사고 후에야 드러납니다. PostgreSQL 의 도구·정책·리허설을 정리합니다.
1. 백업의 종류
PostgreSQL 백업은 두 갈래로 나뉩니다.
| 종류 | 형식 | 도구 | 특징 |
|---|---|---|---|
| Logical | SQL · 커스텀 아카이브 | pg_dump · pg_dumpall · pg_restore |
테이블·스키마 단위 가능. 버전·아키텍처 이식 가능. 큰 DB 에 시간이 오래 걸립니다. |
| Physical | 데이터 디렉토리 파일 복사 | pg_basebackup · 파일 시스템 스냅샷 + WAL |
복구가 빠릅니다. 동일 메이저 버전·동일 아키텍처에서만 호환됩니다. |
logical 은 운영 백업의 기본입니다. physical 은 PITR 의 베이스를 만드는 자리에서 자주 등장합니다.
2. pg_dump · pg_dumpall · pg_restore
pg_dump 는 한 DB 의 logical 백업을 만듭니다. SQL 텍스트로도, 커스텀 아카이브(-Fc)·디렉토리 형식(-Fd) 으로도 출력할 수 있습니다.
pg_dump -Fc -d mydb -f mydb.dump
pg_restore -d mydb_new mydb.dump
-Fc 는 압축·병렬 복원·선택 복원이 가능해 운영에서 가장 자주 권장되는 형식입니다.
pg_dumpall 은 클러스터 전체를 묶어 받습니다. role · tablespace · 모든 DB 가 한 번에 들어가는 대신 데이터는 SQL 텍스트로만 나옵니다. pg_restore 는 pg_dump 의 커스텀·디렉토리 형식을 복원하며 -j 로 병렬 복원이 됩니다.
3. WAL 아카이빙
PostgreSQL 은 모든 변경을 트랜잭션 로그(WAL) 에 먼저 씁니다. 이 로그를 별도 저장소로 계속 옮겨 보관하면 어느 시점의 풀 백업 + WAL 누적으로 임의 시점의 상태를 다시 만들 수 있습니다.
설정의 핵심은 셋입니다.
wal_level = replica
archive_mode = on
archive_command = 'cp %p /mnt/wal-archive/%f'
archive_library 로 갈음할 수도 있습니다. 이렇게 보관된 WAL 이 PITR 의 입력입니다.
4. PITR — Point-In-Time Recovery
PITR 의 흐름은 6 단계입니다.
① 베이스 백업(pg_basebackup) 주기적 생성
② WAL 아카이브 빈틈없이 보관
③ 사고 시: 베이스 백업을 빈 데이터 디렉토리에 복원
④ recovery.signal 파일 생성 + restore_command 설정
⑤ recovery_target_time (또는 _lsn · _xid) 으로 도달 시점 지정
⑥ Postgres 시작 → WAL 재생 → 목표 도달 시 정지
베이스 백업의 시점에서 출발하므로 베이스가 멀수록 재생이 길어집니다. 베이스 백업 주기·WAL 보존 정책이 RPO·RTO 를 결정합니다.
- RPO (Recovery Point Objective) — 허용 가능한 데이터 손실. WAL 전송 주기·지연이 영향.
- RTO (Recovery Time Objective) — 복구에 허용 가능한 시간. 베이스 빈도·하드웨어·WAL 양이 영향.
PITR 자체가 RPO 를 0 에 가깝게 만들지는 않습니다. 동기 복제 standby 가 추가로 필요한 자리도 있습니다.
5. 운영 도구
직접 archive_command 를 묶어 운영하기보다 도구를 쓰는 편이 흔합니다.
pgBackRest — C 로 작성. 병렬 압축·증분 백업·암호화·S3 호환 저장소를 직접 지원합니다. 운영의 정공법으로 가장 자주 추천됩니다.
Barman — EnterpriseDB 후원. Python 기반. 풀·증분·WAL 스트리밍 모두 지원합니다.
WAL-G — Citus·Yandex 가 시작. WAL 압축·암호화·클라우드 저장소(S3 · GCS · Azure Blob) 친화. 운영 표면이 작은 점이 강점입니다.
클라우드 매니지드 — Amazon RDS · Aurora · Cloud SQL · Azure Database 는 자동 백업·PITR 을 매니지드로 제공합니다. 운영자는 보관 기간·복원 절차에 집중하면 됩니다. 한계는 복원 결과가 새 인스턴스가 되는 점·플랫폼 잠금입니다.
6. 3-2-1 보관 규칙
전통적인 백업 보관 권고입니다.
- 3 개의 사본
- 2 가지 매체 (로컬 디스크 + 객체 저장소 등)
- 1 개는 오프사이트 (다른 리전·다른 클라우드·물리적 다른 장소)
원격 사본의 의미는 데이터센터 장애·랜섬웨어 같은 광범위 사고에서 드러납니다.
보관 기간은 보통 일일 1430 일 · 주간 812 주 · 월간 12 개월 · 연간 3~7 년 (법규·계약에 따라). 쌓인 백업은 비용이라 정책을 코드로 자동 정리하는 편이 안전합니다.
7. 암호화 · 키 관리
- 전송 중: TLS.
- 저장 시: 서버측 암호화 또는 클라이언트측 GPG · age.
- 키 관리: KMS · Vault · 클라우드 Key Service.
복원 리허설 단계에서 키 접근 권한까지 같이 점검합니다. 키를 잃으면 암호화 백업은 복원할 수 없습니다.
8. 복원 리허설
가장 흔한 사고는 "백업은 있는데 복원이 안 됐다" 입니다. 정기적인 리허설로 막습니다.
① 다른 환경에 베이스 백업 + WAL 로 PITR
② 결과 DB 의 행 수·체크섬 검증
③ 애플리케이션 스모크 테스트
④ 소요 시간 기록 → RTO 검증
리허설 자체를 자동화한 운영 사례도 흔합니다.
9. 복제는 백업이 아닙니다
streaming replication 은 장애 조치의 도구입니다. logical replication 은 메이저 버전·스키마 이전의 도구입니다. 둘 다 백업은 아닙니다.
사용자가 의도적으로 또는 실수로 데이터를 지우면 복제본도 같이 지워집니다. 시점 복구 능력은 PITR 가 가지고 있습니다. 디스크 스냅샷(EBS · ZFS) 은 빠른 백업·복원이 강점이지만 일관성 있는 스냅샷을 위해서는 pg_backup_start / pg_backup_stop (PostgreSQL 15+) 흐름이 필요합니다.
10. 자주 걸리는 자리
pg_dump 만 가지고 만족하기 — DB 가 커지면 dump · restore 가 시간 단위로 늘어집니다. PITR 에는 부적합합니다.
WAL 아카이브 누락 구간 — archive_command 가 일시적으로 실패하면 PITR 가 끊깁니다. 모니터링이 필수입니다.
백업 완료 알람만 보고 안심하기 — 알람은 "파일이 만들어졌다" 만 알려줄 수도 있습니다. 무결성 검사·복원 리허설로 보완합니다.
버전·플랫폼 호환 — physical 백업은 같은 메이저 버전·같은 아키텍처에서만 복원됩니다. logical 백업은 그 가정이 느슨합니다.
확장(extension) 의존 — 복원 환경에 같은 extension 이 없으면 실패합니다. 환경 빌드 단계에 명시합니다.
재해 시점의 권한 부재 — 평소에 백업 접근 권한이 사람에게 닫혀 있어 사고 시 복구가 막히는 경우가 있습니다. 사람·역할 분리·비상 절차 문서화가 필요합니다.
하고픈 말
백업은 만들기보다 되살리기 어렵습니다. 도구를 고르는 시간보다 리허설에 시간을 더 씁니다. PITR 까지 갈지 일일 dump 로 충분할지는 RPO 가 결정해 줍니다.
Next
- multi-pg-pool-orchestration
- postgres-deep
PostgreSQL Backup and Restore · Continuous Archiving and PITR · pgBackRest 공식 · WAL-G GitHub 를 참고합니다.
data 카테고리의 다른 글
카테고리 전체 보기 →관련 글
검색을 ILIKE·pg_trgm·마이그레이션으로 최적화하기
콘텐츠 검색은 제목·설명·slug·lesson 본문에서 ILIKE '%검색어%'를 사용한다. 검색어를 escape하고 길이를 제한하는 것은 안전성 계약이고, wildcard 앞뒤 때문에 일반 B-tree 인덱스는 이 쿼리를 충분히 돕지 못한다.
통합 테스트의 마이그레이션 replay를 fail-closed로 만들기
통합 테스트가 스키마를 만들지 못했는데도 entity 테스트를 계속하면 실패가 지연되어 원인을 잃는다. 마이그레이션 디렉터리 누락, SQL 파일 0개, 파일 읽기 실패, 개별 SQL 오류는 모두 테스트 bootstrap 실패다.
기대 멤버 집합의 완전성 검증과 원자 upsert
묶음 결과는 행 하나가 아니라 같은 batch key에 속한 기대 멤버 전체로 판정해야 합니다. 일부 행만 존재하는 상태를 완료로 오인하지 않는 읽기·쓰기 계약을 설명합니다.
콘텐츠 초기화 동시 실행을 막는 PostgreSQL advisory lock
콘텐츠 DB 초기화는 테이블 생성·스키마 보정·정적 시드·notes/courses 업서를 순서대로 묶습니다. 운영자가 버튼을 두 번 누르거나 console replica가 겹치면, 각 단계가 멱등이어도 두 파이프라인이 중간 상태를 서로 읽을 수 있습니다.