Alembic과 Django 마이그레이션으로 데이터베이스 스키마 변경 관리
Lukas Schneider
DevOps Engineer · Leapcell

소개
웹 개발 및 데이터 기반 애플리케이션의 세계에서 데이터베이스 구조는 거의 정적이지 않습니다. 애플리케이션이 발전함에 따라 기본 데이터 모델도 발전하므로 테이블, 열, 제약 조건 등의 변경이 필요합니다. 이러한 데이터베이스 스키마 변경을 우아하고 안정적으로 관리하는 것은 중요한 과제입니다. 강력한 메커니즘 없이는 업데이트 배포가 악몽이 될 수 있으며, 데이터 손실, 애플리케이션 중단 또는 개발, 스테이징, 운영 환경 간의 불일치를 초래할 수 있습니다. 바로 이때 데이터베이스 마이그레이션 도구가 필수적이 됩니다. Python 생태계에는 이 문제를 해결하는 두 가지 주요 도구가 있으며, SQLAlchemy와 함께 자주 사용되는 Alembic과 Django 프레임워크의 필수적인 부분인 Django 마이그레이션입니다. 이 글에서는 이러한 도구가 개발자가 데이터베이스 스키마를 효과적으로 관리할 수 있도록 하는 방법, 원칙, 구현 및 실제 적용 사례를 살펴봅니다.
스키마 변경 관리 도구 이해
Alembic과 Django 마이그레이션의 구체적인 내용을 살펴보기 전에 데이터베이스 스키마 변경과 관련된 몇 가지 핵심 개념을 이해하는 것이 중요합니다.
스키마 마이그레이션: 스키마 마이그레이션은 데이터베이스 구조를 변경하는 일련의 작업입니다. 여기에는 새 테이블 생성, 열 추가 또는 제거, 데이터 유형 수정, 인덱스 추가 또는 제약 조건 변경 등이 포함될 수 있습니다.
마이그레이션 스크립트: 이것은 스키마 변경의 프로그래밍 방식 표현입니다. 일반적으로 upgrade
함수(변경 사항 적용)와 downgrade
함수(변경 사항 되돌리기)의 두 가지 주요 부분으로 구성됩니다. 이를 통해 스키마 버전을 앞뒤로 이동할 수 있습니다.
마이그레이션 기록: 적용된 모든 마이그레이션의 기록으로, 일반적으로 데이터베이스 자체 내의 특수 테이블에 저장됩니다. 이 기록을 통해 마이그레이션 도구는 데이터베이스의 현재 상태와 적용하거나 되돌려야 하는 마이그레이션을 결정할 수 있습니다.
멱등성: 이상적으로는 마이그레이션이 멱등해야 합니다. 즉, 여러 번 적용해도 한 번 적용한 것과 동일한 결과를 얻습니다. 항상 엄격하게 달성 가능하지는 않지만, 도구는 이를 우아하게 처리하려고 합니다.
SQLAlchemy용 Alembic
Alembic은 SQLAlchemy ORM과 함께 사용하는 경량 데이터베이스 마이그레이션 도구입니다. 데이터베이스에 구애받지 않도록 설계되었으며 SQLAlchemy가 지원하는 모든 데이터베이스 백엔드를 지원합니다. Alembic은 마이그레이션 스크립트를 생성하는데, 이는 순수 Python 파일이므로 매우 유연하고 강력합니다.
원칙 및 구현:
Alembic은 현재 SQLAlchemy 모델( MetaData
객체로 표현됨)과 현재 데이터베이스 스키마 상태(또는 이전 버전의 모델)를 비교하여 작동합니다. 마이그레이션을 생성하면 Alembic은 차이점을 감지하고 해당 차이점을 연결하는 Python 코드를 생성하려고 시도합니다.
Alembic 마이그레이션 스크립트의 핵심은 upgrade()
및 downgrade()
라는 두 함수로 구성됩니다.
# 일반적인 Alembic 마이그레이션 스크립트 """사용자 테이블 추가 Revision ID: abcdef123456 Revises: Create Date: 2023-10-27 10:00:00.000000 """ from alembic import op import sqlalchemy as sa # revision identifiers, used by Alembic. revision = 'abcdef123456' down_revision = None branch_labels = None depends_on = None def upgrade(): op.create_table( 'users', sa.Column('id', sa.Integer, primary_key=True), sa.Column('name', sa.String(50), nullable=False), sa.Column('email', sa.String(100), unique=True), sa.Column('created_at', sa.DateTime, server_default=sa.text('now()')) ) def downgrade(): op.drop_table('users')
주요 명령:
alembic init <directory>
: 새 Alembic 환경을 초기화합니다.alembic revision --autogenerate -m "Add users table"
: 현재 모델과 데이터베이스를 비교하여 새 마이그레이션 스크립트를 생성합니다.alembic upgrade head
: 최신 리비전까지 모든 보류 중인 마이그레이션을 적용합니다.alembic downgrade -1
: 가장 최근에 적용된 마이그레이션을 되돌립니다.
적용 시나리오:
Alembic은 Flask, FastAPI, Pyramid와 같은 프레임워크 또는 독립 실행형 데이터 처리 스크립트에서의 웹 애플리케이션 여부에 관계없이 SQLAlchemy를 광범위하게 사용하는 프로젝트에 이상적입니다. 스크립트 수정을 허용하는 유연성 덕분에 개발자는 마이그레이션 프로세스를 세밀하게 제어할 수 있으며, 이는 복잡한 데이터 변환이나 레거시 데이터베이스 처리 시 중요할 수 있습니다.
Django 마이그레이션
Django 마이그레이션은 Django 웹 프레임워크의 통합 기능으로, Django 모델의 스키마 변경을 처리하기 위해 특별히 설계되었습니다. Django의 ORM 및 모델 정의 시스템과 깊이 연결되어 있습니다.
원칙 및 구현:
Django의 마이그레이션 시스템은 Django 모델의 변경 사항을 감지하고 해당 변경 사항을 데이터베이스에 적용되는 마이그레이션 파일로 변환하여 작동합니다. Alembic의 직접적인 데이터베이스 스키마 비교와 달리, Django는 주로 현재 models.py
상태를 마지막으로 생성된 마이그레이션 파일과 비교합니다.
Django 마이그레이션 파일도 Python 파일이지만, 구조는 더 선언적이며 작업에 중점을 둡니다.
# 일반적인 Django 마이그레이션 스크립트 # (myapp/migrations/0001_initial.py) from django.db import migrations, models class Migration(migrations.Migration): initial = True dependencies = [ ] operations = [ migrations.CreateModel( name='User', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('name', models.CharField(max_length=50)), ('email', models.EmailField(max_length=100, unique=True)), ('created_at', models.DateTimeField(auto_now_add=True)), ], ), ]
주요 명령:
python manage.py makemigrations <app_name>
: 모델에서 감지된 변경 사항을 기반으로 새 마이그레이션 파일을 생성합니다.python manage.py migrate <app_name> <migration_name>
: 데이터베이스에 마이그레이션을 적용합니다. 인수를 지정하지 않으면 모든 앱에 대해 모든 보류 중인 마이그레이션을 적용합니다.python manage.py showmigrations
: 모든 마이그레이션과 해당 적용 상태를 나열합니다.python manage.py sqlmigrate <app_name> <migration_name>
: 마이그레이션이 실행할 원시 SQL을 표시합니다.
적용 시나리오:
Django 마이그레이션은 Django 프레임워크를 기반으로 구축된 모든 프로젝트에 대한 자연스러운 선택입니다. Django의 ORM, 관리자 패널 및 개발 워크플로와 원활하게 통합됩니다. 선언적 특성은 일반적인 변경에 대한 스키마 진화를 단순화하며, 더 복잡한 시나리오의 경우 개발자는 마이그레이션 파일 내에 사용자 지정 RunPython
또는 RunSQL
작업을 작성할 수 있습니다.
결론
Alembic과 Django 마이그레이션 모두 데이터베이스 스키마 변경이라는 문제를 효과적으로 해결하지만, 서로 다른 생태계와 철학을 가지고 있습니다. SQLAlchemy와의 통합을 통해 Alembic은 특정 프레임워크 외부에서 ORM을 사용하는 프로젝트를 위한 매우 유연하고 강력한 솔루션을 제공하며, 개발자에게 마이그레이션 프로세스를 세밀하게 제어할 수 있도록 합니다. 반면에 Django 마이그레이션은 Django 프레임워크 내에서 긴밀하게 통합되고 의견이 분명한 접근 방식을 제공하여 Django 애플리케이션의 스키마 관리를 단순화합니다. 둘 중 하나를 선택하는 것은 프로젝트의 기술 스택과 특정 요구 사항에 달려 있습니다. 어떤 도구를 사용하든 안정적인 마이그레이션 전략을 채택하는 것은 데이터 무결성을 유지하고 원활한 애플리케이션 배포를 보장하는 데 필수적입니다.