BABY DAY 운영 중 수유 그래프와 카드에서 이상한 시간이 보이기 시작했다. 단순한 화면 표시 문제처럼 보일 수도 있었지만, 여러 기록의 종료 시간이 함께 달라진 흔적이 보여 먼저 데이터 문제로 취급했다.
이때 가장 먼저 한 일은 새 코드를 만드는 것이 아니었다.
실제 사고 범위를 어떻게 좁혔나
운영 기록과 이전 상태를 비교하면서 최초 이상 흔적을 9월 24일 12:30 부근으로 좁혔다. 이 시점이 잡히자 “전체 DB가 망가졌다”가 아니라 특정 시간 이후 어떤 레코드가 달라졌는지를 비교할 수 있었다.
복구 절차도 한 번에 전체 사용자에게 적용하지 않았다. 먼저 내 계정 데이터로 원래 값과 복구 결과를 대조했고, 같은 기준으로 영향을 받은 다른 사용자 한 명의 데이터도 추가로 복원했다.
이 과정에서 화면이 정상으로 보이는지만 확인하지 않고, 그래프에 쓰이는 값과 원본 레코드를 함께 봤다. UI가 정상처럼 보여도 원본 시간이 잘못되어 있으면 다음 통계나 평균 계산에서 다시 문제가 생길 수 있기 때문이다.
화면 버그와 데이터 변경은 대응 순서가 다르다
UI 계산이 잘못됐다면 코드를 고쳐 다시 배포하면 된다. 하지만 저장된 원본 값이 바뀌었다면 새 배포만으로 과거 기록이 돌아오지 않는다.
그래서 먼저 확인한 것은 세 가지였다.
- 언제부터 이상한 값이 나타났는지
- 어떤 사용자와 어떤 기록 범위가 영향을 받았는지
- 백업이나 이전 상태에서 원래 값을 복원할 수 있는지
최초 이상 시점을 좁히고 나니 전체 데이터베이스를 되돌리는 대신 영향을 받은 범위만 다룰 수 있었다.
전체 롤백보다 선택 복구가 안전할 때가 있다
운영 데이터에는 문제 발생 이후 사용자가 새로 입력한 정상 기록도 함께 쌓인다. 무조건 데이터베이스 전체를 과거 시점으로 되돌리면 그 정상 기록까지 잃을 수 있다.
그래서 백업을 기준으로 원래 값을 비교한 뒤 필요한 사용자와 레코드만 선택적으로 복구했다.
복구 작업 자체도 바로 실행하지 않고, 어떤 값이 어떻게 바뀌는지 먼저 확인한 뒤 승인된 범위에서 진행했다.
원인을 찾기 전 추가 쓰기를 줄였다
데이터 이상이 발생한 상태에서 여러 수정본을 연달아 운영에 배포하면 원인과 결과를 분리하기 더 어려워진다.
그래서 원인이 정리될 때까지 운영 쓰기와 자동 반영을 보수적으로 다루고, 로컬 검증과 운영 배포를 분리했다.
이 사건 이후 운영 작업에서 다음 항목을 더 중요하게 보게 됐다.
- 데이터 변경 작업은 대상 범위를 먼저 출력한다
- 백업이 있다는 사실보다 실제 복원이 가능한지 확인한다
- 전체 롤백과 선택 복구의 손실 범위를 비교한다
- 운영 데이터 수정은 명시적인 승인 뒤에 실행한다
- 복구 뒤에는 그래프와 원본 레코드를 함께 확인한다
서비스가 실제 기록을 보관하기 시작하면 “버그를 고쳤다”만으로는 충분하지 않다.
잘못 바뀐 데이터가 있다면 사용자가 믿을 수 있는 상태로 되돌리는 것까지가 수정의 일부라는 걸 다시 확인한 사건이었다.
이 사고 이후 운영 반영 자체를 별도 작업으로 다루게 된 과정은 BABY DAY 운영 배포에 승인 게이트를 둔 이유에서 이어진다.