website: DDL 키워드만으론 못 잡는 DML 사각지대
원래 하려던 건 단순했다. 자동 롤백 로직이 추가형/삭제형 마이그레이션, 그리고 각각 성공/실패 케이스까지 총 4가지 시나리오에서 제대로 동작하는지 stage에서 하나씩 실측하는 작업이었다. 시나리오를 짜면서 "삭제형"을 뭘로 정의할지 보다가, 지금 로직이 `drop table`, `rename` 같은 DDL 키워드가 있는지만 보고 위험 여부를 판정한...
#320 조건부 자동 롤백 로직을 stage에서 실측 검증하다가, DROP/RENAME 같은 DDL 키워드만으로 "위험한 마이그레이션"을 판별하는 방식에 구멍이 있다는 걸 발견했다.
그 기준으로 기존 마이그레이션 히스토리를 쭉 훑어봤는데, V20260728115500 파일이 걸렸다. 내용은 INSERT OR IGNORE뿐이라 DDL 키워드가 하나도 없다. 그래서 지금 로직대로면 이건 "안전(추가형)"으로 분류된다. 이 파일 자체는 멱등한 INSERT라 실제로는 무해했지만, 문제는 그 자리에 만약 UPDATE나 DELETE가 있었다면 어떻게 되는가였다. DDL 키워드가 없으니 여전히 "안전"으로 분류되고, 그러면 배포 전 자동 백업도 안 뜨고 자동 롤백 트리거만 걸리는 조합이 그대로 실행됐을 거다. 스키마를 바꾸는 위험(호환성 문제)과 기존 행을 지우거나 바꾸는 위험(되돌릴 수 없는 데이터 손실)은 서로 다른 종류의 위험인데, 판별 로직은 그 둘을 하나로 뭉뚱그려 놓고 있었던 셈이다.
이걸 확인한 뒤 판단은 어렵지 않았다. update <표> set, delete from 같은 DML 패턴을 destructive 판정 조건에 추가하기로 했다. 다만 코드만 고치고 넘어가지 않고, 시나리오 E를 새로 추가해서 이 패턴이 stage에서 실제로 잡히는지까지 재검증한 뒤에 반영했다. 이미 한 번 사각지대를 코드 리뷰만으로 못 보고 지나쳤던 터라, 패턴을 추가하는 것 자체도 리뷰만으로 검증하고 끝내면 같은 실수를 반복할 여지가 있다고 봤다.
이번 일로 정리한 건, 자동화 규칙을 "이 신호가 있으면 위험"으로 설계할 때는 "이 신호가 없어도 위험한 경우가 있는가"를 실제 데이터에 대고 반드시 대조해봐야 한다는 것. 이번 경우엔 그 실제 데이터가 기존 마이그레이션 파일 전체였다. 코드 리뷰 단계에서는 이런 종류의 구멍이 잘 드러나지 않고, stage에서 진짜 시나리오를 하나씩 돌려보는 과정에서야 발견됐다.