개요

데이터베이스 마이그레이션은 스키마 변경, 데이터 이전, 버전 관리 등 데이터베이스의 진화를 체계적으로 관리하는 과정입니다. 애플리케이션이 성장함에 따라 마이그레이션 전략의 중요성은 기하급수적으로 커집니다. 이 글에서는 현대적 마이그레이션 전략과 주요 도구들을 비교 분석합니다.

핵심 개념

상태 기반 vs 변경 기반: 마이그레이션 도구는 크게 두 가지 철학으로 나뉩니다. 상태 기반(Declarative)은 원하는 최종 상태를 선언하면 도구가 차이를 계산하여 적용합니다(예: Prisma, Atlas). 변경 기반(Imperative)은 순차적인 변경 스크립트를 작성하고 실행합니다(예: Flyway, Alembic).

제로 다운타임 마이그레이션: 프로덕션 환경에서 서비스 중단 없이 스키마를 변경하는 전략입니다. Expand-Contract 패턴이 가장 널리 사용됩니다. 먼저 새 스키마를 추가(Expand)하고, 애플리케이션을 점진적으로 전환한 뒤, 기존 스키마를 제거(Contract)합니다.

블루-그린 마이그레이션: 두 개의 데이터베이스를 운영하여 마이그레이션 실패 시 즉시 롤백할 수 있는 전략입니다. 비용이 높지만 가장 안전한 방법입니다.

Shadow Database: Prisma가 사용하는 패턴으로, 마이그레이션 생성 시 임시 데이터베이스를 만들어 마이그레이션을 검증한 후 삭제합니다.

실전 예제

주요 마이그레이션 도구의 사용 예제를 비교합니다.

-- Flyway (변경 기반) - V2__add_user_email_index.sql
-- 파일 이름 규칙: V{version}__{description}.sql
CREATE INDEX CONCURRENTLY idx_users_email
  ON users (email);

-- 롤백 스크립트: U2__add_user_email_index.sql
DROP INDEX CONCURRENTLY IF EXISTS idx_users_email;
// Prisma (상태 기반) - schema.prisma
model User {
  id        Int      @id @default(autoincrement())
  email     String   @unique
  name      String?
  posts     Post[]
  profile   Profile?
  createdAt DateTime @default(now()) @map("created_at")

  @@index([email])
  @@map("users")
}

// 마이그레이션 생성: npx prisma migrate dev --name add_email_index
// Prisma가 자동으로 SQL 마이그레이션 파일 생성
# Alembic (변경 기반) - Python SQLAlchemy 생태계
# alembic revision --autogenerate -m "add user email index"

def upgrade():
    op.create_index(
        'idx_users_email',
        'users',
        ['email'],
        unique=False,
        postgresql_concurrently=True
    )

def downgrade():
    op.drop_index('idx_users_email', table_name='users')
-- Atlas (상태 기반) - HCL 또는 SQL 스키마 정의
-- schema.hcl
-- table "users" with index "idx_users_email"
-- atlas schema apply --url "postgres://..." --to "file://schema.hcl"

활용 팁

  • CONCURRENTLY 사용: PostgreSQL에서 인덱스 생성 시 CREATE INDEX CONCURRENTLY를 사용하면 테이블 락 없이 인덱스를 생성할 수 있습니다. 프로덕션 환경에서 필수입니다.
  • NOT NULL 추가 시 주의: 기존 컬럼에 NOT NULL 제약을 추가할 때는 먼저 기본값을 설정하고, 기존 NULL 데이터를 업데이트한 후, 제약을 추가하세요.
  • 대용량 테이블 컬럼 추가: PostgreSQL에서 DEFAULT 값이 있는 컬럼 추가는 12 이상에서 즉시 완료됩니다(메타데이터만 변경). 하지만 NOT NULL + DEFAULT 조합은 주의가 필요합니다.
  • 마이그레이션 테스트: CI/CD 파이프라인에서 마이그레이션을 자동 테스트하세요. 빈 DB에 전체 마이그레이션 적용, 프로덕션 스냅샷에 최신 마이그레이션 적용 두 가지를 모두 테스트합니다.
  • Supabase 마이그레이션: supabase db diff로 로컬 변경사항을 마이그레이션 파일로 생성하고, supabase db push로 원격에 적용할 수 있습니다.

마무리

마이그레이션 도구의 선택은 팀의 규모, 기술 스택, 그리고 운영 환경에 따라 달라집니다. 작은 팀에서는 Prisma의 선언적 접근이 생산적이고, 대규모 팀에서는 Flyway나 Alembic의 명시적 변경 관리가 안전합니다. 어떤 도구를 선택하든, 제로 다운타임 마이그레이션 전략을 반드시 함께 수립하시기 바랍니다.