Contents
see List백업 파일이 있어도 복구가 느리면 장애 대응은 실패한다
PostgreSQL 백업은 파일을 한 번 생성하는 작업으로 끝나지 않는다. 실제 장애에서는 어느 시점의 데이터를 되살릴지, 다른 서버에 얼마나 빨리 복원할지, 애플리케이션 연결을 어떤 순서로 열지까지 정해져 있어야 한다. 특히 운영 DB를 단순 SQL 파일 하나로만 보관하면 대용량 복구 시간, 권한 누락, 확장 모듈 누락, 복원 중 충돌을 확인하기 어렵다. 백업 정책은 데이터의 중요도에 따라 논리 백업과 물리 백업을 분리하고, 복구 연습으로 유효성을 검증하는 방식이 안전하다.
이 문서는 일반적인 업무 시스템에서 많이 쓰는 pg_dump와 pg_restore 중심의 논리 백업 절차를 다룬다. 개별 데이터베이스의 테이블, 스키마, 데이터, 권한을 이관하거나 특정 시점의 전체 데이터를 되살릴 때 적합하다. 서버 전체 장애 뒤 시점 복구가 필요한 환경은 WAL 아카이빙과 기본 백업을 별도로 설계해야 하며, 이 절차만으로 대체하면 안 된다.
백업 목표부터 정한다: RPO와 RTO
백업 설계를 시작할 때는 기술보다 복구 목표를 먼저 합의한다. RPO는 허용 가능한 데이터 손실 범위다. 매일 새벽 백업만 있다면 당일 입력 데이터는 잃을 수 있다. RTO는 서비스가 다시 동작하기까지 허용되는 시간이다. 백업 파일이 작아도 복원 인덱스 생성에 세 시간이 걸린다면 RTO가 짧은 서비스에는 맞지 않는다.
- 업무 DB의 전체 논리 백업은 하루 1회 이상, 별도 저장소로 복사한다.
- 변경량이 큰 시스템은 WAL 기반 시점 복구 또는 복제본을 함께 검토한다.
- 백업 보관 기간, 암호화, 접근 권한, 삭제 정책을 문서화한다.
- 월 1회 이상 비운영 서버에서 실제 복구 시간을 측정한다.
백업 서버와 운영 서버에 같은 장애가 발생할 수 있으므로, 백업 파일은 운영 디스크와 다른 저장소에 둬야 한다. 또한 데이터만 복원하면 로그인 계정이나 확장 기능에서 막힐 수 있다. 역할 정보는 pg_dumpall의 globals-only 옵션으로 별도 보관하거나, 역할 생성 절차를 형상 관리하는 편이 좋다.
권장 형식: custom 백업과 역할 백업을 분리한다
pg_dump의 custom 형식은 압축된 아카이브를 만들고 pg_restore에서 테이블 또는 스키마 단위 선택 복구가 가능하다. 일반 텍스트 SQL보다 병렬 복원이 가능하며, 복구 목록을 확인하기도 편하다. 아래 예시는 데이터베이스 appdb와 전역 역할을 날짜별 파일로 백업하는 기본 스크립트다. 실행 계정에는 DB 접속 정보가 노출되지 않도록 .pgpass 파일을 사용하고 권한을 0600으로 제한한다.
#!/usr/bin/env bash
set -euo pipefail
BACKUP_DIR=/var/backups/postgresql
TODAY=$(date +%F)
mkdir -p "$BACKUP_DIR"
pg_dump --dbname=appdb --format=custom --compress=6 --file="$BACKUP_DIR/appdb-$TODAY.dump"
pg_dumpall --globals-only --file="$BACKUP_DIR/globals-$TODAY.sql"
pg_restore --list "$BACKUP_DIR/appdb-$TODAY.dump" > "$BACKUP_DIR/appdb-$TODAY.contents.txt"
find "$BACKUP_DIR" -type f -mtime +14 -delete마지막 pg_restore --list는 아카이브가 읽히는지 빠르게 확인하는 용도다. 이것만으로 데이터가 완전하다고 판단할 수는 없지만, 빈 파일이나 손상된 파일을 조기에 발견하는 데 도움이 된다. 보관 파일 삭제는 업무 요구사항에 맞춰 기간을 조정하고, 원격 저장이 끝난 뒤에만 실행해야 한다. 운영 데이터가 포함된 덤프는 파일 권한과 저장소 접근 권한을 최소화한다.
복구는 새 데이터베이스에서 먼저 검증한다
장애 상황에서 곧바로 원본 데이터베이스를 덮어쓰면 원인 분석과 재시도 기회를 잃는다. 가능하면 새 데이터베이스에 복원하고 애플리케이션 점검을 거친 다음 전환한다. 기존 DB를 다시 만들어야 한다면 접속 중인 세션을 먼저 차단하고, 대상 이름과 백업 날짜를 두 번 확인한다. 운영 반영 전에는 해당 시스템의 변경 동결 여부도 확인해야 한다.
# 역할과 권한을 먼저 복원한다
psql --dbname=postgres --file=/var/backups/postgresql/globals-2026-08-03.sql
# 검증용 데이터베이스 생성
createdb appdb_restore_check
# 4개 작업으로 병렬 복원, 오류 발생 시 즉시 중단
pg_restore --dbname=appdb_restore_check --jobs=4 --exit-on-error --verbose /var/backups/postgresql/appdb-2026-08-03.dump
# 기본 검증
psql --dbname=appdb_restore_check -c "SELECT count(*) FROM information_schema.tables WHERE table_schema = 'public';"병렬 복원은 custom 또는 directory 형식에서만 가능하며, 서버 CPU와 스토리지 여유를 고려해 작업 수를 정한다. 지나치게 큰 --jobs 값은 운영 서버의 디스크 I/O를 포화시킬 수 있다. 복원 로그는 남겨 두고, 실패한 객체가 확장 모듈인지 권한인지 이미 존재하는 객체인지 분류한다. 필요한 확장이 설치되지 않은 환경에서는 CREATE EXTENSION 권한과 운영체제 패키지도 함께 확인해야 한다.
복구 검증은 행 수 비교만으로 끝내지 않는다
테이블 행 수는 기본 확인 항목이지만, 업무 데이터의 정확성을 보장하지는 않는다. 핵심 테이블의 최대 등록 시각, 최근 주문 번호, 합계 금액, 시퀀스의 현재 값, 주요 인덱스 상태를 함께 점검한다. 애플리케이션이 사용하는 DB 계정으로 로그인해 읽기와 쓰기 테스트를 실행하면 권한 누락을 빨리 찾을 수 있다. 대용량 테이블은 전체 해시 비교 대신 기간별 집계나 샘플 쿼리로 검증 범위를 정할 수 있다.
SELECT
max(created_at) AS latest_created_at,
count(*) AS order_count,
coalesce(sum(total_amount), 0) AS order_total
FROM orders;
SELECT last_value, is_called
FROM orders_id_seq;복구 후에는 통계 정보가 충분하지 않아 초기 쿼리가 느려질 수 있다. 대규모 복원 뒤에는 서비스 부하가 낮은 시간에 ANALYZE를 수행하고, 애플리케이션 헬스체크와 핵심 화면을 확인한 뒤 트래픽을 연다. 복구 절차의 실제 소요 시간과 누락된 설정은 다음 백업 정책에 반영한다.
운영 체크리스트
- 백업 파일이 운영 서버 밖의 저장소에 복사됐는지 확인한다.
- 역할, 권한, 확장 모듈 복원 절차가 별도로 준비돼 있는지 확인한다.
- 최근 백업을 새 DB에 복원해 파일과 복구 시간을 검증한다.
- 핵심 테이블의 건수, 최신 시각, 합계, 시퀀스, 애플리케이션 권한을 확인한다.
- WAL 시점 복구가 필요한 업무인지 RPO와 RTO 기준으로 재검토한다.
좋은 백업은 파일 개수가 아니라 검증된 복구 절차로 판단한다. 백업 생성, 원격 보관, 복원 연습, 결과 기록을 하나의 운영 작업으로 연결하면 실제 장애에서 판단 시간을 크게 줄일 수 있다.
database
| No | 작성일 | Title |
|---|---|---|
| 2112 | 2026. 02. 11. | Supabase 실전 활용 가이드: PostgreSQL의 새로운 패러다임 |
| 2090 | 2026. 01. 13. | mariadb(mysql) vs Oracle vs PostgreSQL: 종합 비교 가이드 |
| 2003 | 2025. 11. 30. | Oracle Hint 사용법 - 옵티마이저 제어하기 |
| 2002 | 2025. 11. 30. | Connection Pool 설정 가이드 - HikariCP |
| 2001 | 2025. 11. 30. | 데이터베이스 백업과 복구 전략 |
| 2000 | 2025. 11. 30. | MongoDB 기초 - Document DB 시작하기 |
| 1999 | 2025. 11. 30. | Redis 캐싱 전략 - Cache Aside, Write Through, Write Behind |
| 1998 | 2025. 11. 30. | 트랜잭션 격리 수준 이해하기 |
| 1997 | 2025. 11. 30. | SQL 쿼리 최적화 10가지 팁 |
| 1996 | 2025. 11. 30. | 데이터베이스 정규화와 반정규화 전략 |