목록으로

Alembic 설정

시리즈, 입문
2024. 6. 25. PM 9:19:54
#alembic, #sqlalchemy, #마이그레이션

Alembic 마이그레이션 설정

(1) SQLAlchemy ORM 모델 인식

Alembic 마이그레이션의 대상을 지정 설정과 마이그레이션을 실행하는 함수는 alembic 디렉터리에 있는 env.py 파일에 있어요. 우리는 SQLModel을 이용해 SQLAlchemy ORM 모델을 만드니 모델 메타데이터는 SQLModel의 기반 클래스에 있고, 이걸 Alembic에 알려줘야 해요. 그래야 모델을 인식해서 마이그레이션 스크립트를 작성하거든요.

위 코드로 수정하여 다음과 같이 변경합니다.

SQLModel의 SQLModel 클래스를 상속해 정의한 모델은 SQLAlchemy의 선언형 모델에 등록되고, 이 정보를 바탕으로 Alembic은 마이그레이션 대상 모델을 인식해요. 그래서 SQLModel클래스를 상속해 정의한 모델이 있는 pudding_todo.apps.account.modelspudding_todo.apps.todo.models 모듈을 읽어들이는(import) 거지요. 그 다음에 SQLModel.metadata를 Alembic이 사용하도록 target_metadata 이름으로 연결하고요.

(2) 비동기 마이그레이션 수행

우리는 비동기 방식으로 데이터베이스를 다루며, 드라이버 역시 비동기 드라이버인 aiosqlite를 사용하죠. alembic.ini 파일에서 sqlalchemy.url의 값을 sqlite+aiosqlite:///pudding_todo.db 이라 설정한 것 기억하시죠? 그래서 마이그레이션 수행도 비동기로 실행해야 해요. 하지만 Alembic의 마이그레이션 함수는 동기 동작으로 작성되어 있어요. 이 함수를 비동기 함수로 동작하게 한 번 감쌀게요.

먼저 동기식으로 동작하는 원래 함수를 따로 분리할게요.

이 함수는 run_migrations_online() 함수 안에 있는 코드지요. 이번엔 run_migrations_online() 함수를 비동기로, 즉 코루틴(coroutine)으로 바꿉니다.

다 됐어요. 이제 마이그레이션을 실행하면 run_migrations_online() 비동기 함수(코루틴)가 실행되도록 코드를 고칩니다. env.py 파일 맨 아래에 있는 코드를 수정할게요.

run_migrations_online()가 코루틴이라 바로 직접 실행할 수 없기 때문에 asyncio.run()을 이용하는 거예요.

(3) 마이그레이션 스크립트 자동 생성과 수정

마이그레이션 수행 준비를 마쳤어요. 여태껏 만든 모델을 데이터베이스 테이블로 만드는 마이그레이션 스크립트를 생성해볼게요. alembic.ini 파일이 있는 경로에서 다음 명령어를 실행하세요.

그럼 다음과 같은 내용이 출력될 거예요.

revision 인자는 개정 사항을 마이그레이션으로 수행할 스크립트를 만드는 데 사용해요. --autogenerate는 현 데이터베이스 상태와 모델을 비교하여 변경사항을 자동 감지하여 마이그레이션 스크립트를 작성해주고요.

저는 마이그레이션 개정값이 bc5e07390c03으로 만들어졌는데, 이 값은 실행 환경, 실행할 때마다 달라져요. -m user_todo_tables는 마이그레이션에 대한 사람이 알아볼 메모를 남기는 거예요. 생략해도 되는데, 그러면 Alembic 마이그레이션 스크립트는 일련번호가 아닌 무작위 값으로 식별하기 때문에 마이그레이션 파일이름만으로는 무엇에 관한 마이그레이션인지 알아보기 어려워요. 그래서 메모를 남기는 걸 저는 권장해요. 이 메모는 파일명에 붙거든요.

화면에 출력된 텍스트를 잘 보면 user, todo_group, 그리고 todo 테이블을 감지해 추가했다고 나오죠? SQLModel.metadata에 인식되지 않으면 마이그레이션 단계에서도 모델을 감지하지 못해서 마이그레이션 스크립트 내용이 자동 생성되지 않아요.

생성된 마이그레이션 스크립트 파일은 alembic/versions 디렉터리에 있어요. Python 문법을 지원하는 코드 편집기로 열어보면 코드에 문제가 있다고 나와요.

user 테이블에 매핑된 User 모델 코드은 다음과 같은데요.

username 모델 필드에 대해 Alembic은 sqlmodel.sql.sqltypes.AutoString()을 모델필드형으로 인식했어요. created_at은 SQLAlchemy-Utc 패키지의 UtcDateTime를 지정해서 이 모델필드형을 사용하고요. 하지만 마이그레이션 스크립트엔 이들을 읽어들이지(import) 않고 있어요. Alembic import 해줘야 할 것까지 인식해서 자동으로 코드를 작성해주진 않거든요. 그래서 문제가 발생하기 때문에 직접 import 해줘야 해요.

SQLModel 이름공간(namespace)에 있는 모델필드형의 경우 SQLModel로 만드는 모델에서 빈번하게 사용하기 때문에 저는 마이그레이션 스크립트가 생성될 때 sqlmodel도 기본적으로 import 되도록 해요. 이런 마이그레이션 스크립트에 대한 템플릿이 Alembic에 존재하는데, 바로 alembic 디렉터리에 있는 script.py.mako 파일이예요. 이 파일을 손보겠습니다.

기존 코드를 수정한 건 없고 다음 두 줄을 추가했어요.

이제 Alembic으로 마이그레이션 스크립트를 자동생성하면 스크립트 파일에 위 두 줄이 포함돼요. 확인해볼까요? alembic/versions 디렉터리에 만들어진 마이그레이션 스크립트 파일을 삭제하고, 다시 alembic revision --autogenerate -m user_todo_tables 를 실행해보세요. 그럼 마이그레이션 수행에 문제 없는 스크립트 파일이 생성됩니다.

생성된 마이그레이션 스크립트로 실제 마이그레이션을 수행해볼게요.

현재까지 진행한 개정판까지 마이그레이션을 전개(upgrade)하는 명령어죠. 문제없이 수행하면 다음과 같은 수행 과정이 출력돼요.

여기까지 진행한 코드 커밋 : 5d88e2d

학습이 이뤄지고 있는지 확신이 안 서나요?
사수가 없나요?
효과적이고 효율적으로 학습하며 성장하는
자기만의 학습과 성장 체계를 만들 수 있습니다.
연사자들의 각양각색 학습과 성장 스토리로
여러분의 학습과 성장을 키워보세요.
푸딩캠프 뉴스레터를 구독하면 학습과 성장, 기술에 관해 요약된 컨텐츠를 매주 편하게 받아보실 수 있습니다.
목차