Designing the Restore Procedure
한국어 원문으로 표시합니다.
한 줄 요약
복구는 순서와 검증이 전부다. 그리고 그 순서를 실제로 밟아 시간을 재기 전까지 RTO 는 숫자가 아니라 희망사항이다.
왜 이게 필요했나
백업을 잘 만들어 두고도 복구에서 실패하는 이유는 대개 절차 문제다.
- 어떤 백업을 써야 하는지 모른다 (전체? 증분? 어느 세대?)
- 복원 순서를 틀린다 (증분을 먼저 풀거나 순서를 뒤집는다)
- 복원 위치를 잘못 잡아 현재 시스템을 덮어쓴다
- 복원은 됐는데 서비스가 안 뜬다 (권한, SELinux, UID 매핑)
어떻게 동작하나
안전한 복원 순서
# 1. 임시 경로로 먼저 푼다 — 절대 바로 덮어쓰지 않는다
mkdir -p /restore/check
tar -xzf /backup/full-2026-08-20.tar.gz -C /restore/check
# 2. 내용을 확인한다
find /restore/check -type f | wc -l
diff -r /restore/check/etc/nginx /etc/nginx | head -40
# 3. 필요한 것만 옮긴다
rsync -aHAX --numeric-ids /restore/check/etc/nginx/ /etc/nginx/
임시 경로를 거치는 것이 핵심이다. -C / 로 바로 푸는 것은 되돌릴 수 없는 작업이다.
증분 복원의 순서
전체 → 증분 0 → 증분 1 → ... 순서를 반드시 지켜야 한다. tar 의 --listed-incremental 로 만든 증분은 삭제 정보까지 담고 있어서, 순서를 어기면 있어야 할 파일이 사라진다.
tar --listed-incremental=/dev/null -xzf full.tar.gz -C /restore/
tar --listed-incremental=/dev/null -xzf inc0.tar.gz -C /restore/
tar --listed-incremental=/dev/null -xzf inc1.tar.gz -C /restore/
복원 시 --listed-incremental=/dev/null 을 쓰는 것이 관례다. 스냅샷 파일을 갱신하지 않겠다는 뜻이다.
선택 복원
전체를 풀 필요 없이 특정 파일만 꺼낼 수 있다.
tar -tzf backup.tar.gz | grep nginx.conf
tar -xzf backup.tar.gz -C /restore/ src/conf/nginx.conf
tar -xzf backup.tar.gz -C /restore/ --strip-components=1 src/conf/
--strip-components=N 은 앞쪽 경로 요소 N 개를 제거하고 푼다. 아카이브 구조와 복원 위치가 다를 때 쓴다.
시간 재기
RTO 를 확인하려면 실제로 재야 한다.
START=$(date +%s)
# ... 복구 절차 전체 ...
END=$(date +%s)
echo "복구 소요: $((END - START))초"
여기에 포함되어야 하는 것은 아카이브 추출 시간만이 아니다. 백업 저장소에서 파일을 가져오는 시간, 검증 시간, 서비스 기동 시간, 정합성 확인 시간이 전부 들어가야 실제 RTO 다. 실무에서 RTO 를 못 지키는 원인 1위는 추출이 느려서가 아니라 네트워크로 백업을 가져오는 시간이다.
복원 후 검증
- 파일 개수와 총 크기가 기대와 맞는가
- 권한과 소유자가 맞는가 (
--numeric-ids를 썼는가) - 서비스가 기동하는가
- 애플리케이션의 정합성 검사를 통과하는가
백업이 있다는 것과 복구할 수 있다는 것
백업이 성공했다는 로그는 파일이 만들어졌다 는 뜻일 뿐입니다. 세 가지를 확인해야 "복구할 수 있다" 고 말할 수 있습니다.
- 읽을 수 있는가 — 압축이 깨지지 않았고 암호 키가 살아 있는가.
- 완전한가 — 필요한 것이 다 들어 있는가(스키마·데이터·시퀀스·확장).
- 시간 안에 되는가 — 실제로 복원해 보면 예상보다 훨씬 오래 걸립니다.
세 번째가 자주 무너집니다. 500GB 를 복원하는 데 6시간이 걸리는데 RTO 가 1시간 이라면, 그 백업은 재해 복구에 쓸 수 없습니다. RTO 를 지키려면 복제본이나 스냅숏이 필요합니다 — 논리 백업은 마지막 방어선이지 첫 수단이 아닙니다.
| 방식 | 복원 시간 | 복구 지점 | 쓰는 곳 |
|---|---|---|---|
| 논리 덤프(pg_dump) | 느림(시간) | 덤프 시점 | 이전, 부분 복원 |
| 물리 백업 + WAL | 보통(분~시간) | 임의 시점 | 재해 복구 |
| 스토리지 스냅숏 | 빠름(분) | 스냅숏 시점 | 빠른 되돌리기 |
| 읽기 복제본 승격 | 가장 빠름(초) | 거의 실시간 | 고가용성 |
리허설에서 실제로 재는 것
"복구가 됐다" 로 끝내지 않고 숫자를 남깁니다.
## 복구 리허설 2026-09-06
- 대상: labhub-prod DB (실 용량 142GB)
- 백업 시각: 2026-09-05 12:30 KST
- 복원 목표 시점: 2026-09-05 18:00 KST (PITR)
| 단계 | 걸린 시간 |
|---|---|
| 백업 내려받기 | 21분 |
| 기본 백업 복원 | 47분 |
| WAL 재생 (5.5시간분) | 33분 |
| 서비스 기동·검증 | 9분 |
| **합계 (RTO 실측)** | **1시간 50분** |
- 검증: 행 수 대조 3개 표 일치, 최근 주문 10건 육안 확인, 애플리케이션 기동 성공
- 발견: WAL 아카이브에 12분 구멍(2026-09-05 14:02~14:14) — 아카이빙 재시도 설정 필요
- RPO 실측: 12분 (목표 5분 미달 — 개선 필요)
발견 항목이 없는 리허설은 리허설을 안 한 것과 비슷합니다. 처음 해 보면 거의 언제나 무언가 나옵니다.
언제 하는가
- 분기마다 한 번 이 최소선입니다. 그 사이에 스키마·용량·인프라가 바뀝니다.
- 백업 방식이나 저장소를 바꾼 직후 에 반드시 합니다.
- 새 사람이 왔을 때 그 사람이 절차서만 보고 해 봅니다. 절차서에 빠진 것이 이때 드러납니다.
그리고 리허설은 운영과 격리된 곳 에서 합니다. 운영 DB 에 복원하는 순간 그것은 리허설이 아니라 사고입니다.
현장에서 만나는 모습
"복원은 됐는데 서비스가 안 뜬다." 원인 후보가 정해져 있다. UID/GID 매핑, SELinux 컨텍스트, 파일시스템 기능 차이(ACL 미지원), 커널/라이브러리 버전 차이. --numeric-ids 와 --selinux 가 앞의 둘에 대한 대비다.
복원 문서가 복원 담당자의 노트북에만 있다. 그 노트북이 없는 상황이 곧 복구가 필요한 상황일 수 있다.
다음 실습에서 할 것
앞에서 만든 백업 세트로 복구 리허설을 수행한다. 안전한 순서로 복원하고, 원본과 비교하고, 선택 복원과 증분 순서 복원까지 하고, 시간을 재서 RTO 충족 여부를 판정한다.