Contents
see List개요
데이터베이스 마이그레이션은 스키마 변경, 데이터 이전, 버전 관리 등 데이터베이스의 진화를 체계적으로 관리하는 과정입니다. 애플리케이션이 성장함에 따라 마이그레이션 전략의 중요성은 기하급수적으로 커집니다. 이 글에서는 현대적 마이그레이션 전략과 주요 도구들을 비교 분석합니다.
핵심 개념
상태 기반 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의 명시적 변경 관리가 안전합니다. 어떤 도구를 선택하든, 제로 다운타임 마이그레이션 전략을 반드시 함께 수립하시기 바랍니다.
database
| No | 작성일 | Title |
|---|---|---|
| 3380 | 2026. 08. 20. | PostgreSQL 느린 조회를 진단하는 방법: EXPLAIN ANALYZE와 복합 인덱스 실전 가이드 |
| 3348 | 2026. 08. 11. | PostgreSQL 잠금 대기 줄이기: 트랜잭션 범위와 lock_timeout 설정 실전 가이드 |
| 3316 | 2026. 08. 03. | PostgreSQL 백업 복구 실전 가이드: pg_dump·pg_restore로 장애 복구 절차 만들기 |
| 3284 | 2026. 07. 26. | PostgreSQL 인덱스가 있는데도 느린 쿼리 해결하기: EXPLAIN ANALYZE와 복합 인덱스 설계 |
| 3254 | 2026. 07. 18. | PostgreSQL 잠금 대기 진단 가이드: pg_stat_activity로 블로킹 쿼리 찾고 장애 줄이기 |
| 3202 | 2026. 07. 09. | PostgreSQL 백업 복구 검증 가이드: pg_dump와 psql로 실제 복원까지 확인하기 |
| 3170 | 2026. 07. 01. | MySQL 느린 쿼리 원인 찾기: EXPLAIN과 복합 인덱스 점검 가이드 |
| 3116 | 2026. 06. 23. | PostgreSQL 트랜잭션 충돌 줄이기: 잠금 순서와 짧은 재시도로 데드락 대응하기 |
| 3058 | 2026. 06. 15. | PostgreSQL JSONB 조회 튜닝: GIN 인덱스와 생성 컬럼으로 느린 검색 줄이기 |
| 2971 | 2026. 06. 07. | MySQL/MariaDB 복합 인덱스 설계: 느린 목록 조회를 줄이는 WHERE·ORDER BY 점검법 |