백업은 파일이 아니라 복구 능력이다
백업을 해 두었다는 말은 안심할 근거가 되지 않는다. 중요한 질문은 따로 있다.
원하는 시점의 데이터를 복구할 수 있는가?
복구에 얼마나 걸리는가?
복구한 데이터가 업무적으로 믿을 만한가?
장애 중에도 사용자가 감당할 수 있는 수준으로 서비스를 유지할 수 있는가?
데이터베이스 운영에서 백업은 보험에 가깝다. 보험은 사고가 난 뒤 실제로 보상받을 수 있어야 의미가 있다. 백업도 마찬가지다. 파일이 존재하는 것보다, 정해진 절차로 복구해 서비스에 다시 연결할 수 있는지가 중요하다.
개발자는 백업을 인프라 팀의 일로만 넘기기 쉽다. 하지만 어떤 데이터가 얼마나 중요하고, 어느 시점까지 되돌려도 되는지, 복구 중 어떤 기능을 막아야 하는지는 애플리케이션을 아는 사람이 함께 결정해야 한다. 주문, 결제, 포인트, 정산 데이터는 단순히 서버를 되살리는 문제가 아니라 사용자의 돈과 신뢰를 다루는 문제다.
AI 생성 이미지
백업 방식의 차이
가장 기본은 전체 백업이다. 특정 시점의 데이터베이스 전체를 복사한다. 이해하기 쉽고 복구 절차도 비교적 단순하다. 대신 데이터가 커질수록 백업 시간, 저장 공간, 네트워크 비용이 커진다. 매일 새벽 전체 백업을 수행하는 방식은 작은 서비스에서는 충분할 수 있지만, 수백 GB나 수 TB 단위 데이터베이스에서는 부담이 커진다.
증분 백업은 마지막 백업 이후 변경된 부분만 저장한다. 저장 공간과 백업 시간을 줄일 수 있지만, 복구할 때는 기준이 되는 전체 백업과 이후 증분 백업들을 순서대로 적용해야 한다. 복구 절차가 길어지고 중간 백업 하나가 손상되면 복구가 어려워질 수 있다.
여기서 한 단계 더 나아가면 시점 복구가 있다. PostgreSQL의 WAL, MySQL의 binlog처럼 데이터 변경 로그를 보관해 두었다가 특정 시점까지 재생하는 방식이다. 예를 들어 오전 3시에 전체 백업을 만들고, 이후 변경 로그를 계속 보관했다면 오전 10시 17분 30초 상태로 복구할 수 있다.
시점 복구는 운영 사고에서 특히 중요하다. 장애는 디스크 고장처럼 하드웨어 문제로만 발생하지 않는다. 잘못된 배포가 모든 상품 가격을 0원으로 바꾸거나, 관리자가 실수로 고객 데이터를 삭제할 수도 있다. 이때 단순히 최신 백업으로 복구하면 이미 잘못된 변경까지 포함될 수 있다. 사고 직전 시점으로 되돌릴 수 있어야 한다.
실무에서는 보통 다음 조합을 사용한다.
주기적인 전체 백업
그 사이의 증분 백업 또는 스토리지 스냅샷
WAL/binlog 같은 변경 로그 보관
별도 리전에 복사된 백업 파일
중요한 것은 백업 방식 자체보다 복구 경로다. "어떤 파일을 어떤 순서로 적용하면 어느 시점까지 복구되는가"가 명확해야 한다.
RPO와 RTO로 결정하기
백업 주기는 감으로 정하면 안 된다. 기준은 RPO와 RTO다.
RPO는 Recovery Point Objective의 약자로, 장애가 났을 때 감당할 수 있는 최대 데이터 손실 시간을 뜻한다. RPO가 5분이면 최악의 경우 최근 5분 데이터 손실까지 허용한다는 의미다. RPO가 0에 가까울수록 더 자주 동기화하거나 더 강한 복제·로그 보존 전략이 필요하다.
RTO는 Recovery Time Objective의 약자로, 장애 후 서비스를 다시 사용할 수 있게 만드는 데 허용되는 최대 시간을 뜻한다. RTO가 30분이면 30분 안에 복구를 완료하거나 최소한 핵심 기능을 사용할 수 있어야 한다.
예를 들어 블로그 댓글 데이터는 RPO 1시간, RTO 4시간이어도 비즈니스가 감당할 수 있다. 반면 결제 승인 데이터는 RPO 수 초, RTO 수 분을 요구할 수 있다. 이 둘에 같은 백업 전략을 적용하면 한쪽은 과잉 투자이고, 다른 한쪽은 위험하다.
RPO와 RTO는 다음 질문으로 구체화할 수 있다.
최근 몇 분 또는 몇 시간의 데이터를 잃어도 되는가?
장애 중 읽기 기능만 제공해도 되는가?
주문 생성은 막아도 주문 조회는 열어야 하는가?
복구 후 사용자에게 어떤 보정 절차가 필요한가?
수동 처리로 버틸 수 있는 업무와 절대 멈추면 안 되는 업무는 무엇인가?
백업 주기는 RPO를 만족해야 한다. 복구 자동화와 대기 서버 구성은 RTO를 만족해야 한다. 전체 백업을 하루 한 번만 만들고 변경 로그를 보관하지 않는다면 RPO는 최대 24시간에 가깝다. 반대로 로그를 계속 보관하더라도 복구 절차가 복잡해 실제 복구에 6시간이 걸린다면 RTO는 6시간이다.
장애 대응은 원인보다 피해 제한이 먼저다
장애가 발생하면 원인을 찾고 싶어진다. 하지만 운영 중 첫 번째 목표는 원인 분석이 아니라 피해 제한이다. 특히 데이터베이스 장애에서는 잘못된 쓰기를 계속 허용하면 복구 범위가 커진다.
일반적인 대응 순서는 다음과 같다.
장애 범위와 증상을 확인한다.
위험한 쓰기를 중단하거나 읽기 전용으로 전환한다.
현재 데이터 상태와 로그를 보존한다.
장애 조치 또는 복구 중 어느 경로를 선택할지 결정한다.
복구 후 데이터 정합성을 확인한다.
서비스를 단계적으로 재개한다.
예를 들어 리더 데이터베이스가 응답하지 않는다면 팔로워를 새 리더로 승격하는 장애 조치를 고려할 수 있다. 이때 중요한 것은 복제 지연이다. 팔로워가 리더의 마지막 변경까지 모두 따라잡지 못했다면 일부 커밋이 사라질 수 있다. 장애 조치는 빠른 서비스 재개에 유리하지만, 데이터 유실 가능성을 확인해야 한다.
반대로 애플리케이션 버그로 잘못된 UPDATE가 실행된 상황이라면 단순 장애 조치가 답이 아닐 수 있다. 복제본에도 같은 잘못된 변경이 이미 반영되었을 가능성이 높기 때문이다. 이 경우에는 시점 복구, 부분 복구, 보정 쿼리, 감사 로그 분석이 필요하다.
읽기 전용 전환은 피해를 줄이는 실용적인 방법이다. 주문 생성, 결제, 포인트 사용처럼 데이터 변경이 큰 기능을 잠시 막고, 상품 조회나 주문 내역 조회처럼 읽기 기능만 제공할 수 있다. 모든 기능을 즉시 닫는 것보다 사용자 불편을 줄이면서 데이터 오염을 막을 수 있다.
복구 후에는 데이터베이스가 실행된다는 사실만 확인해서는 안 된다. 업무 정합성을 확인해야 한다.
결제는 성공했는데 주문이 없는 데이터가 있는가?
주문 상태와 배송 상태가 모순되지 않는가?
재고가 음수인 상품이 있는가?
포인트 적립·사용 합계가 사용자 잔액과 맞는가?
유니크해야 하는 값이 중복되지 않았는가?
이 검증 쿼리는 장애가 난 뒤 즉석에서 만들면 늦다. 중요한 업무 규칙은 평소에 점검 쿼리로 준비해 두는 편이 좋다.
백업 보안도 운영의 일부다
백업 파일은 운영 데이터의 복사본이다. 운영 데이터에 개인정보, 결제 정보, 내부 관리 정보가 들어 있다면 백업에도 그대로 들어 있다. 그래서 백업은 보안 예외가 아니라 더 엄격히 관리해야 할 대상이다.
먼저 암호화가 필요하다. 백업 파일은 저장 시 암호화하고, 전송할 때도 안전한 채널을 사용해야 한다. 클라우드 스토리지에 백업을 올린다면 버킷 공개 설정, 접근 정책, 키 관리 권한을 함께 확인해야 한다. 데이터베이스 서버 접근 권한이 없는 사람이 백업 파일을 내려받을 수 있다면 보안 구조가 무너진 것이다.
접근 권한은 최소화해야 한다. 백업을 생성하는 권한, 백업을 삭제하는 권한, 백업을 복구하는 권한은 분리하는 편이 안전하다. 특히 랜섬웨어나 계정 탈취 상황에서는 공격자가 원본 데이터뿐 아니라 백업까지 삭제하려 할 수 있다. 중요한 백업은 삭제 보호, 버전 관리, 별도 계정 보관, 다른 리전 복사를 고려해야 한다.
보관 기간도 정책으로 정해야 한다. 백업을 오래 보관하면 오래된 사고를 복구할 수 있지만, 개인정보 보관 부담과 유출 위험이 커진다. 반대로 너무 짧게 보관하면 늦게 발견된 데이터 오염에 대응할 수 없다. 예를 들어 잘못된 정산 로직이 2주 뒤에 발견된다면 최근 7일 백업만으로는 원인을 추적하기 어렵다.
백업 정책에는 다음 항목이 포함되어야 한다.
백업 대상 데이터베이스와 제외 대상
전체 백업과 증분 백업의 주기
변경 로그 보관 기간
백업 파일 암호화 방식
백업 접근 권한과 승인 절차
백업 보관 위치와 리전
삭제 보호와 보관 만료 정책
복구 테스트 주기
이 목록은 문서로 끝나면 안 된다. 실제 인프라 설정과 일치해야 한다.
복구 리허설이 절차를 현실로 만든다
장애 대응 문서는 대부분 정상 상황에서 작성된다. 하지만 실제 장애 상황에서는 사람이 당황하고, 권한이 없고, 명령어가 오래되었고, 예상보다 데이터가 크다. 그래서 복구 리허설이 필요하다.
복구 리허설은 운영 데이터를 임의로 덮어쓰는 작업이 아니다. 격리된 환경에 최신 백업을 복원하고, 애플리케이션을 연결해 핵심 기능이 동작하는지 확인하는 훈련이다. 이 과정에서 문서와 현실의 차이가 드러난다.
자주 발견되는 문제는 다음과 같다.
백업 파일은 있지만 복호화 키를 찾을 수 없다.
복구 계정 권한이 부족하다.
WAL이나 binlog 일부가 누락되었다.
복구 명령은 맞지만 데이터 크기 때문에 RTO를 초과한다.
애플리케이션 설정이 운영 DB 주소에 고정되어 있다.
복구 후 인덱스 재생성이나 통계 갱신을 빼먹었다.
정합성 검증 쿼리가 준비되어 있지 않다.
리허설에서는 시간을 재야 한다. 전체 백업을 내려받는 데 걸린 시간, 복원 시간, 변경 로그 적용 시간, 검증 시간, 애플리케이션 연결 전환 시간을 각각 기록한다. 그래야 문서상의 RTO가 실제로 가능한지 판단할 수 있다.
또한 복구 절차는 한 사람의 기억에 의존하면 안 된다. 담당자가 휴가 중이거나 퇴사했을 때도 실행 가능해야 한다. 명령어, 필요한 권한, 확인해야 할 지표, 중단해야 할 배치 작업, 사용자 공지 기준까지 실행 순서로 정리해 두어야 한다.
개발자가 준비해야 할 것
백업과 복구는 데이터베이스 관리자만의 일이 아니다. 애플리케이션이 복구 가능한 구조여야 한다.
먼저 중요한 변경에는 감사 로그를 남겨야 한다. 누가, 언제, 어떤 값을, 무엇에서 무엇으로 바꿨는지 알 수 있으면 전체 복구 대신 부분 보정이 가능하다. 모든 사고가 데이터베이스 전체 복원으로 해결되는 것은 아니다. 오히려 일부 테이블이나 일부 사용자 데이터만 복구해야 하는 경우가 많다.
둘째, 외부 시스템과의 관계를 고려해야 한다. 데이터베이스를 오전 10시 상태로 되돌렸는데 결제 PG, 메시지 큐, 검색 인덱스, 캐시는 현재 상태라면 시스템 사이에 불일치가 생긴다. 복구 후 재동기화할 대상과 순서를 미리 정해야 한다.
셋째, 멱등성을 설계해야 한다. 복구 후 실패한 작업을 다시 처리할 때 같은 요청이 두 번 실행될 수 있다. 주문 생성, 쿠폰 발급, 포인트 적립처럼 중복 실행이 위험한 작업은 멱등성 키나 유니크 제약으로 보호해야 한다.
마지막으로, 장애 모드를 기능별로 나누어야 한다. 모든 장애에서 전체 서비스를 내릴 필요는 없다. 데이터베이스 쓰기가 불안정하면 읽기 전용 모드, 일부 테이블만 문제가 있으면 해당 기능만 차단, 복제 지연이 크면 최신성이 중요한 화면만 리더에서 읽는 식으로 선택지를 준비할 수 있다.
좋은 백업 전략은 조용할 때 만들어지고, 리허설을 통해 검증되며, 장애 중에는 단순한 절차로 실행된다. 백업의 목표는 파일을 많이 쌓아 두는 것이 아니다. 데이터 손실을 허용 범위 안으로 줄이고, 서비스를 예측 가능한 시간 안에 다시 세우는 것이다.
이 노트는 보도·비평·교육·연구 목적으로 작성되었습니다. 저작권 문의가 있으시면 에서 알려주세요.