앱을 교체하기 전에 후보 JAR의 SQL이 운영 DB에 적용된 마이그레이션과 같은지 확인하고 싶었습니다. 적용할 마이그레이션이 없으면 배포 도구는 Flyway를 실행하지 않습니다. 그때도 이미 적용한 SQL이 바뀌었는지 가려내려면 JAR의 파일에서 Flyway 이력과 같은 방식으로 체크섬을 계산해야 했습니다.

SQL 읽기 방식 맞추기

프로젝트에서 사용한 Flyway는 파일을 UTF-8로 읽고, 첫 줄의 BOM과 각 줄의 줄바꿈 문자를 제외한 바이트를 순서대로 CRC32에 넣었습니다. 그래서 LF를 CRLF로 바꾸거나 마지막 줄바꿈을 빼도 체크섬이 같습니다. 줄 끝의 공백은 SQL을 읽는 줄에 그대로 남아 계산에 들어갑니다.

배포 도구에서는 CRLF, LF, CR만 줄 경계로 처리했습니다. Python의 splitlines()는 수직 탭 같은 문자도 줄 경계로 보므로 Java에서 읽는 결과와 어긋날 수 있습니다. 계산한 CRC32의 상위 비트가 켜져 있으면 2**32를 빼서 Flyway가 기록하는 부호 있는 32비트 정수와 비교했습니다.

이력과 경계 사례 대조

운영에서 기록한 V1부터 V18까지 18개의 체크섬은 각 SQL 파일에서 계산한 값과 모두 일치했습니다. 이를 픽스처로 남겼고, 같은 두 줄의 SQL에 BOM과 CRLF를 넣거나 끝의 줄바꿈을 빼도 값이 같은지 별도로 검사했습니다. 같은 파일에 후행 공백 한 칸을 더한 경우에는 다른 값이 나왔습니다. 배포 도구는 적용 이력의 체크섬과 후보가 다르면 앱을 교체하기 전에 멈춥니다.

위험한 SQL 변경에 대한 승인에는 별도로 파일 바이트 전체의 SHA-256을 사용합니다. Flyway 이력과의 대조는 Flyway가 같은 마이그레이션으로 보는지를 확인하고, 승인 해시는 검토한 파일과 배포 후보의 바이트가 일치하는지를 확인합니다. 체크섬 호환성의 근거는 당시 사용한 Flyway와 운영 이력입니다. Flyway 버전을 바꿀 때는 같은 대조를 다시 할 수 있습니다.