洪民憙 (홍민희) 블로그

이하의 글은 2011년에 쓴 것입니다. 오래된 글인 만큼, 현재의 생각과 전혀 다른 내용도 많이 포함되어 있고, 당시와는 상황이 많이 달라진 점도 있습니다. 또한, 그 당시에 잘못 알려졌던 정보도 포함되어 있을 수 있습니다. 어찌됐든 저는 제 오래된 글이 회자되는 것을 저어합니다. 읽기에 앞서 양해를 부탁드립니다.

sqlalchemy-migrate의 문제점

SQLAlchemy는 자체적인 스키마 마이그레이션 도구를 제공하지 않는다. SQLAlchemy 최고의 단점인데 1.0 아니라고 지금까지 조금도 제공하지 않고 있다.

대신 sqlalchemy-migrate라는 확장 도구가 사실상의 표준 마이그레이션 도구로 널리 사용되고 있는데, 나 역시 별 수 없이 이걸 쓰고 있다. 하지만 실무에서 사용하기에는 여러가지 크고 작은 문제점이 존재한다. 그 가운데 치명적인 몇 가지 문제점만 나열해 보겠다.

  1. 마이그레이션 과정에 트랜잭션을 걸지 않아서 원자적으로 작동하지 않는다. 당연히 원자적으로 작동할 거라고 기대하고 별 생각 없이 마이그레이션 스크립트를 짰다가는 데이터에 눈에 쉽게 띄지도 않는 비정합 오류가 실무에서 생길 수 있다. 꼭 실무가 아니더라도 개발 환경에서도 마이그레이션 스크립트에서 오류가 나면 롤백이 되지 않아서 어중간하게 변하다 만 스키마를 붙잡고 고생을 해야 한다. 당연히 이런 상황을 피해가려면 매 스크립트마다 손수 트랜잭션 블럭을 만들어서 그 안에다 마이그레이션 스크립트를 작성해야 하는데, 이렇게 해도 문제는 있으니, 중간에 오류가 나도 버전 넘버는 소리 없이 증감한다는 것.

  2. 애초에 SQLAlchemy의 스키마 정의 API는 마이그레이션을 염두한 디자인이 아니다. 그래서 명령적이라기 보다는 선언적인 특성을 더 많이 갖고 있는데, sqlalchemy-migrate는 SQLAlchemy의 API를 멍키패치(monkey patch)해서 마이그레이션용 메서드를 추가하기 때문에 명령적인 무언가를 해야할 경우 제약 사항이 매우 많다. 마이그레이션은 선언보다는 명령에 가깝다는 점을 감안하면 정말 잘못된 디자인 결정이라고밖에 말할 수 없다. 예를 들어 기존에 있던 테이블을 지우고 같은 이름으로 새로운 테이블을 만드는 것은 굉장히 쉽게 되어야 할텐데도 sqlalchemy-migrate에서는 workaround 없이 달성할 수 없다. 메타데이터에 이미 같은 이름으로 테이블이 선언되어 있다는 식의 오류가 나기 때문이다.

  3. 커맨드라인 인터페이스와 Python API가 뭉뚱그려져 있다. 그래서 기본적으로 제공되는 커맨드라인 인터페이스를 쓰는 대신 프로젝트에 원래 존재하는 스크립트에 서브커맨드로 추가해서 사용하거나 하는게 생각보다 많이 힘들다. 일단 제대로 된 API를 사용하는 게 아니라 문서화되지 않은 함수들과 구현 세부사항에 의존하는 부수 효과를 마구마구 이용해야 한다.

이 외에도 자잘하게 정말 짜증나는 것들이 좀 있는데 당장 생각나는 것은 이렇게 셋 정도. 혹시라도 sqlalchemy-migrate를 쓰려는 다른 분들이 있다면 부디 이 글 읽고 삽질할 시간을 조금이나마 줄이길 바란다.