필사 모드: DB 마이그레이션 도구 2026 — Atlas·Bytebase·Skeema·Liquibase·Flyway·Prisma·Drizzle·gh-ost·pg-osc 심층 비교 (선언형 vs 명령형, 리뷰 워크플로, 온라인 DDL)
한국어프롤로그 — 마이그레이션 도구는 왜 여전히 어려운가
DB 스키마 변경은 소프트웨어에서 가장 위험한 작업 중 하나다. 코드 배포는 롤백이 쉽지만, `ALTER TABLE`은 한 번 실행되면 디스크 위의 사실이 된다. 큰 테이블에 잘못 락이 걸리면 서비스가 멈춘다.
그래서 **마이그레이션 도구**가 존재한다. 하지만 2026년 5월 현재 이 카테고리는 어느 때보다 분열되어 있다.
- **Liquibase**와 **Flyway**는 2010년대부터 자바 진영의 사실상 표준이었고, 지금도 엔터프라이즈에서는 디폴트다.
- **Prisma Migrate**·**Drizzle Kit**은 TypeScript 앱의 디폴트로 자리 잡았다. ORM과 한 묶음으로 와서 가장 매끄럽다.
- **Atlas (Ariga)**는 HCL 기반 declarative schema-as-code로 급속히 점유율을 늘리고 있다. **Schema Monitoring**·**Schema Lint**·**Versioned Migrations** 모두를 한 도구로.
- **Bytebase**는 리뷰 워크플로를 1급 시민으로 만들었다. 다중 DB·GitOps·AI 어시스턴트까지.
- **Skeema**는 MySQL 진영에서 가장 가벼운 declarative 도구로 살아남았고 Postgres도 들어왔다.
- 그리고 살아있는 큰 테이블에는 여전히 **gh-ost**·**pt-online-schema-change**·**pg-online-schema-change** 같은 온라인 DDL 도구가 필요하다.
이 글은 이 도구들을 **선언형 vs 명령형**, **리뷰 워크플로**, **드리프트 감지**, **다중 DB**, **AI 어시스턴스**, **온라인 DDL 안전성**의 축으로 비교한다. 실전 시나리오 — 칼럼 추가, NOT NULL 도입, 대형 테이블 백필, 롤링 리네임 — 를 각 도구로 풀어보고, 팀별 결정 프레임워크를 제시한다.
> 이 글은 패턴 가이드가 아니라 **도구 비교**다. 무중단 expand-contract 패턴 자체는 이미 별도 글에서 다뤘다(`2026-04-15 zero-downtime database migration` 참고). 여기서는 그 패턴을 **어느 도구로 어떻게 굴리는지**가 핵심이다.
1장 · 풍경 — 도구 지도
먼저 도구를 분류한다. 한 줄에 다 들어가지 않는다.
| 분류 | 도구 | 한 줄 요약 |
| --- | --- | --- |
| 선언형 schema-as-code | Atlas, Skeema, Drizzle Kit | "있어야 할 상태"를 적으면 diff를 만든다 |
| 명령형 migration-files | Liquibase, Flyway, Prisma Migrate, dbmate, Sqitch | "무엇을 바꿀지" 한 파일씩 직접 적는다 |
| 리뷰 워크플로 중심 | Bytebase, Atlas Cloud | PR·승인·롤백·실행을 한 화면에서 |
| 온라인 DDL (큰 테이블 전용) | gh-ost, pt-online-schema-change, pg-online-schema-change | 쉐도우 테이블 + 트리거 + cutover |
| 클라우드 매니지드 | Atlas Cloud, Bytebase Hub, Liquibase Hub | 실행 로그·승인·드리프트 감지 SaaS |
이 글의 초점은 굵게 표시된 도구들이다. **Atlas**·**Bytebase**·**Skeema**·**Liquibase**·**Flyway**·**Prisma Migrate**·**Drizzle Kit**, 그리고 온라인 DDL 도구들.
**왜 이 도구들인가**
- **Atlas** — 2024~2026 사이 가장 빠르게 자란 도구. HCL DSL + Go 단일 바이너리 + Schema Monitoring이 묶음. Terraform이 인프라에 한 일을 DB에 하고 있다는 평가.
- **Bytebase** — 리뷰 워크플로·승인·다중 DB의 사실상 표준. 2025년부터 AI 어시스턴트(SQL Review·자연어→SQL)가 합쳐졌다.
- **Skeema** — MySQL의 declarative 도구. 가볍고 빠르다. 2025년 들어 Postgres 지원 정식 도입.
- **Liquibase** — XML/YAML/JSON/SQL 모두 지원. 변경 로그·롤백 SQL을 명시적으로 적는 전통. 엔터프라이즈·은행권 사실상 표준.
- **Flyway** — 단순함의 미학. SQL 파일에 버전 번호 붙이고 끝. 2025년부터 polyglot 지원 확대.
- **Prisma Migrate**·**Drizzle Kit** — 각 ORM의 한 식구. 가장 매끄러운 통합.
- **gh-ost·pt-osc·pg-osc** — 위 도구들이 못 하는 일을 한다. 큰 테이블의 무중단 DDL.
2장 · 선언형 vs 명령형 — 가장 큰 분기점
DB 마이그레이션 도구 선택의 첫 분기점이다. **무엇을 적는가**가 다르다.
선언형 (declarative, schema-as-code)
**"있어야 할 상태"를 적는다.** 도구가 현재 DB와 비교해 diff를 만들고, 그 diff에 해당하는 DDL을 실행한다.
Atlas: schema.hcl — 있어야 할 상태
table "users" {
schema = schema.public
column "id" { type = bigint, null = false }
column "email" { type = varchar(255), null = false }
column "name" { type = varchar(100), null = true }
primary_key { columns = [column.id] }
index "users_email_uniq" {
unique = true
columns = [column.email]
}
}
- 장점: 스키마가 한 곳에 모인다. 코드 리뷰가 "스키마 자체"를 본다.
- 단점: 자동 diff가 안전하지 않을 수 있다. 도구가 만든 DDL을 사람이 다시 본다.
명령형 (imperative, migration-files)
**"무엇을 바꿀지"를 한 파일씩 적는다.** 각 파일은 한 번 실행되면 끝.
-- Flyway: V001__add_users_table.sql
CREATE TABLE users (
id BIGINT PRIMARY KEY,
email VARCHAR(255) NOT NULL UNIQUE,
name VARCHAR(100)
);
-- V002__add_users_created_at.sql
ALTER TABLE users ADD COLUMN created_at TIMESTAMPTZ DEFAULT now();
- 장점: 무엇이 도는지 사람이 정확히 안다. 롤백 SQL을 별도로 적을 수 있다.
- 단점: 스키마 전체 모양은 N개 파일을 머리로 합쳐야 안다. 충돌 머지·리네임이 어렵다.
어느 쪽이 우월한가
**둘 다 우월하지 않다.** 다만 2026년의 분위기는 분명하다:
- 신규 풀스택 팀은 **선언형**으로 시작하는 비율이 늘었다(Drizzle Kit·Atlas·Prisma `db push`).
- 엔터프라이즈·은행·관리 감독이 있는 곳은 여전히 **명령형**이 우세하다(Liquibase·Flyway). 감사 추적, 명시적 롤백 SQL이 컴플라이언스에 직결된다.
- **Atlas는 두 진영을 한 도구에 넣었다.** declarative `atlas schema apply`도, versioned `atlas migrate apply`도 있다.
3장 · Atlas — 부상하는 강자
3.1 무엇이 다른가
**Atlas**는 이스라엘의 Ariga 사가 만든 오픈 소스 DB 스키마 도구다. Go로 작성됐고, 단일 바이너리, HCL DSL, 그리고 cloud SaaS(Atlas Cloud)가 따라온다.
핵심은 세 가지.
1. **선언형과 명령형을 모두 지원**한다. `atlas schema apply`는 선언형, `atlas migrate diff` + `atlas migrate apply`는 명령형.
2. **Schema Monitoring**(2024년 도입) — production DB를 주기적으로 스냅숏 뜨고, 코드의 schema와 비교해 드리프트를 감지한다.
3. **Schema Lint·Schema Versioning** — `atlas migrate lint`로 위험 DDL(예: 비조건적 NOT NULL 도입)을 사전에 잡는다.
3.2 HCL 스키마
schema.hcl
schema "public" {
comment = "core application"
}
table "users" {
schema = schema.public
column "id" {
type = bigint
null = false
}
column "email" {
type = varchar(255)
null = false
}
column "created_at" {
type = timestamptz
null = false
default = sql("now()")
}
primary_key {
columns = [column.id]
}
index "users_email_uniq" {
unique = true
columns = [column.email]
}
}
`atlas schema apply --url "postgres://..." --to "file://schema.hcl"` 한 줄로 현재 DB를 이 상태로 맞춘다. 미리 보고 싶다면 `atlas schema diff`.
3.3 Schema Monitoring — 새 카테고리
Atlas Cloud의 가장 큰 차별점은 **드리프트 감지의 자동화**다. 누군가 production에서 직접 `ALTER TABLE`을 친 사실, 또는 hotfix migration이 staging에는 적용되고 production에는 적용 안 된 사실을 도구가 알려준다.
주기적으로 production을 스냅숏
atlas schema monitor \
--url "postgres://prod.../app" \
--token "$ATLAS_TOKEN" \
--interval 1h
드리프트가 있으면 Slack·이메일로 알림. 이건 Flyway·Liquibase·Prisma Migrate에는 없는 카테고리다.
3.4 Versioned Migrations + Lint
명령형 워크플로를 선호한다면 Atlas의 versioned mode를 쓴다.
1) 코드의 schema.hcl과 현재 migration history를 비교해 새 SQL 파일 생성
atlas migrate diff add_user_table \
--dir "file://migrations" \
--to "file://schema.hcl" \
--dev-url "docker://postgres/16/dev"
2) 위험 DDL이 있는지 lint
atlas migrate lint --dir "file://migrations" --latest 1
3) 적용
atlas migrate apply --dir "file://migrations" --url "$DB_URL"
`atlas migrate lint`는 다음 같은 패턴을 잡는다.
- 큰 테이블에 비조건적 `NOT NULL` 도입 (락 위험).
- 락을 길게 유지하는 인덱스 생성 (`CREATE INDEX` 비-`CONCURRENTLY`).
- 데이터 손실 위험 변경 (column drop, type narrowing).
3.5 누가 Atlas를 쓰면 좋은가
- HCL/Terraform 친화적이고, infra-as-code 멘탈 모델에 익숙한 팀.
- 다중 DB(Postgres, MySQL, MariaDB, SQLite, MS SQL, ClickHouse 일부) 한 도구로.
- 드리프트 감지가 필요한 멀티 환경(staging·prod)·멀티 인스턴스 팀.
- ORM과 무관하게 DB 진실의 원천을 코드에 두고 싶은 팀.
4장 · Bytebase — 리뷰 워크플로 1급 시민
4.1 무엇이 다른가
**Bytebase**는 중국 출신의 오픈 소스 + 상용 회사. 다른 도구들이 CLI를 중심에 두는 반면, Bytebase는 **GUI + 승인 워크플로**를 중심에 둔다.
개발자 → 변경 제안(PR-like Issue) → SQL Review(자동·사람)
→ DBA 승인 → 단계적 환경 적용(dev → staging → prod)
→ 자동 백업·롤백 스크립트 보존
- 다중 DB: MySQL·Postgres·TiDB·Snowflake·MongoDB·ClickHouse·SQL Server·Oracle·Spanner 등 25종 이상.
- GitOps 모드: GitHub/GitLab PR 머지로 트리거.
- 자동 SQL Review: 룰 기반(컬럼 명명·인덱스·길이 제한 등) + 2025년부터 LLM 기반.
4.2 AI 어시스턴트 (2025~2026)
Bytebase 3.x부터 추가된 기능.
- **자연어 → SQL**: "지난주 가입자 일별로 보여줘" 같은 요청을 SQL로.
- **SQL Review**: LLM이 위험 패턴(인덱스 없는 join, full scan, 락 위험)을 사람보다 빠르게 잡는다.
- **변경 영향 분석**: 이 마이그레이션이 영향 주는 쿼리·뷰·앱 코드 추정.
이 카테고리는 다른 도구들이 아직 깊게 못 따라왔다. Atlas도 자체 AI를 붙이고는 있지만 Bytebase가 가장 성숙하다.
4.3 누가 Bytebase를 쓰면 좋은가
- 다중 DB·다중 환경·여러 팀이 같이 쓰는 큰 조직.
- DBA가 정식으로 승인·리뷰하는 프로세스가 필요한 곳(금융·헬스케어).
- GUI를 통한 비-개발자 접근(데이터 분석가 등)이 필요한 곳.
- "마이그레이션 PR을 누가 머지했는가"를 감사 추적해야 하는 곳.
**누가 쓰지 말 것**: 1인 또는 소규모 팀. 오버킬이다. Drizzle Kit + Atlas migrate가 충분.
5장 · Skeema — MySQL 진영의 가벼운 declarative
**Skeema**는 단순함의 화신이다. MySQL용으로 시작했고 2025년에 Postgres 정식 지원.
schemas/
├─ app/
│ ├─ users.sql # CREATE TABLE users (...)
│ ├─ posts.sql
│ └─ .skeema # connection info
`*.sql` 파일에 **CREATE TABLE 문 그대로** 적는다. `skeema diff`·`skeema push`로 DB와 동기화.
- 장점: 다른 도구를 안 배워도 된다. SQL을 그대로 적는다. 빠르다. CI 친화적.
- 단점: Postgres 지원이 Atlas만큼 풍부하진 않다. enum·partial index·function·trigger 등 일부 객체 지원에 격차.
MySQL을 쓰면서 가벼운 도구를 원하면 가장 먼저 검토할 후보. Atlas와 비교해 학습 곡선이 거의 0이다.
6장 · Liquibase — 엔터프라이즈의 지속 가능한 선택
6.1 무엇이 다른가
**Liquibase**는 2006년부터 있다. 자바 진영의 표준이지만 자바 앱이 아닌 곳에서도 잘 쓰인다.
핵심 개념: **ChangeSet**. 변경 하나가 하나의 ChangeSet이고, 각각이 id·author·rollback SQL을 명시적으로 갖는다.
changelog.yaml
databaseChangeLog:
- changeSet:
id: 001-create-users
author: alice
changes:
- createTable:
tableName: users
columns:
- column: { name: id, type: BIGINT, constraints: { primaryKey: true } }
- column: { name: email, type: VARCHAR(255), constraints: { nullable: false, unique: true } }
- column: { name: name, type: VARCHAR(100) }
rollback:
- dropTable: { tableName: users }
`liquibase update`로 적용, `liquibase rollback`으로 되돌림. **명시적인 rollback SQL이 큰 차이점**이다.
6.2 2025~2026의 변화
- **Liquibase 5.x**(2025): 더 빠른 changelog 파싱, 새 reporting CLI.
- **Liquibase AI Advisor**: Liquibase Hub에서 LLM 기반 리뷰. Atlas Lint·Bytebase Review와 비슷한 방향.
- **PostgreSQL extension 지원 확대**: pg_partman·TimescaleDB·pgvector 등 익스텐션 친화 변경 지원.
6.3 누가 Liquibase를 쓰면 좋은가
- 자바·코틀린 백엔드 + Spring Boot. `spring-boot-starter-liquibase` 한 줄.
- 엔터프라이즈·은행·헬스케어 — 명시적 rollback과 감사 추적이 컴플라이언스 요건.
- 멀티 DB(Oracle·DB2 포함) — Atlas·Bytebase보다 Oracle·DB2 친화도가 높음.
- 변경 로그를 XML/YAML로 가지고 싶은 팀.
**약점**: XML/YAML은 SQL을 직접 쓸 때보다 장황하다. Drizzle Kit·Atlas와 비교해 신규 팀에는 무거울 수 있다.
7장 · Flyway — 단순함의 미학
**Flyway**는 더 단순하다. 파일 이름으로 버전을 매기고, SQL을 그대로 적는다.
db/migration/
├─ V1__create_users.sql
├─ V2__add_users_created_at.sql
└─ V3__add_users_email_index.sql
-- V2__add_users_created_at.sql
ALTER TABLE users ADD COLUMN created_at TIMESTAMPTZ DEFAULT now();
`flyway migrate`로 적용. **rollback은 별도 down 파일**(`U2__...`) 또는 새 forward migration으로 푼다.
7.1 2025~2026 변화
- **Flyway 11.x**(2025년 후반): Native compiled CLI(GraalVM), 더 빠른 startup.
- **Polyglot 친화 확대**: Node/Python 진영을 위한 공식 도커 이미지 정리·CI 가이드.
- **Flyway Teams/Enterprise**의 새 features: 대규모 마이그레이션 dry-run, undo 자동화.
7.2 누가 Flyway를 쓰면 좋은가
- 자바·Spring Boot의 디폴트. `spring-boot-starter-flyway` 한 줄.
- "SQL 그대로, 도구는 가볍게" 원하는 팀.
- 단순한 단일 DB(주로 Postgres·MySQL) 운영.
**약점**: rollback이 1급 시민이 아니다(community edition). 복잡한 변경에는 Liquibase가 더 강하다.
8장 · Prisma Migrate · Drizzle Kit — ORM과 한 묶음
8.1 Prisma Migrate
`schema.prisma`(declarative)와 `prisma migrate`(versioned)의 조합.
// schema.prisma
model User {
id Int @id @default(autoincrement())
email String @unique @db.VarChar(255)
name String? @db.VarChar(100)
createdAt DateTime @default(now()) @map("created_at")
@@map("users")
}
새 마이그레이션 생성 + 적용 (개발용)
npx prisma migrate dev --name add_user_table
프로덕션 적용
npx prisma migrate deploy
- 장점: ORM의 모델 정의가 곧 스키마. 한 곳에서 본다. 셰도우 DB로 안전한 diff 생성.
- 단점: 복잡한 객체(partial index, exclusion constraint, generated column 일부, custom domain)는 Prisma 모델로 표현 못 함 — `migration.sql`을 직접 편집해야 함.
8.2 Drizzle Kit
// schema.ts (드리즐 스키마)
export const users = pgTable('users', {
id: bigserial('id', { mode: 'bigint' }).primaryKey(),
email: varchar('email', { length: 255 }).notNull(),
name: varchar('name', { length: 100 }),
createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
}, (t) => ({
emailUniq: uniqueIndex('users_email_uniq').on(t.email),
}))
스키마와 DB를 비교해 SQL 파일 생성
npx drizzle-kit generate
적용
npx drizzle-kit migrate
- 장점: ORM과 분리된 가벼운 CLI. SQL 파일이 보수적이고 읽기 쉽다.
- 단점: 자동 diff가 100%는 아님 — 컬럼 리네임 등은 사람 보정 필요. 일부 객체(enum 변화, 복합 PK 변경) 가장자리.
8.3 ORM 마이그레이션 vs Atlas/Liquibase
- ORM 도구가 가장 매끄럽다 — 모델과 스키마가 한 곳.
- 그러나 DB가 ORM의 시야 밖 객체(extension, materialized view, custom function)를 많이 쓰면 ORM 마이그레이션만으로 부족.
- 그런 팀은 ORM은 read/write 타입용으로만 쓰고, 스키마는 Atlas/Liquibase로 따로 운영하는 패턴이 늘었다.
9장 · 온라인 DDL — 큰 테이블의 무중단
위 도구들의 공통점: **DB가 직접 `ALTER TABLE`을 실행한다는 가정**. 작은 테이블이면 문제없다. 그러나 1억 row 테이블에 새 컬럼을 추가하면? 대부분의 DDL이 메타데이터 락을 잡는다. MySQL은 8.0 이후 많은 DDL이 online이지만, 여전히 락 위험이 있는 변경이 있다. Postgres는 12+ 이후 많이 좋아졌지만 일부 변경은 여전히 ACCESS EXCLUSIVE 락.
그래서 **온라인 DDL 도구**가 필요하다.
9.1 gh-ost (MySQL)
GitHub이 만든 도구. **트리거를 쓰지 않고 binlog만 본다**. 부하가 낮다.
gh-ost \
--user=admin --password=*** --host=mysql.prod \
--database=app --table=users \
--alter="ADD COLUMN status VARCHAR(20) DEFAULT 'active'" \
--max-load=Threads_running=25 \
--critical-load=Threads_running=1000 \
--chunk-size=2000 \
--execute
작동: 쉐도우 테이블 생성 → 청크 단위 복사 → binlog로 누락 변경 따라잡기 → 짧은 락으로 cutover.
9.2 pt-online-schema-change (MySQL)
Percona Toolkit의 일부. gh-ost보다 오래됐고, **트리거 기반**이다.
pt-online-schema-change \
--alter="ADD COLUMN status VARCHAR(20) DEFAULT 'active'" \
--execute \
D=app,t=users,h=mysql.prod
장점: 더 오래 검증됐고 더 다양한 환경에서 돈다. 단점: 트리거가 INSERT/UPDATE/DELETE에 매번 따라붙어 부하가 있다.
9.3 pg-online-schema-change (Postgres)
상대적으로 후발 주자. shadow table + 트리거 + cutover 패턴을 Postgres에 맞췄다. Shopify·Stripe 등이 만든 도구들이 있고 (`pg-osc`·`pg_squeeze`·`pg_repack`), 활용도가 늘고 있다.
pg-osc run \
--dbname=app --table=users \
--alter="ADD COLUMN status TEXT DEFAULT 'active'" \
--copy-batch-size=10000
Postgres 자체가 `ALTER TABLE ... ADD COLUMN`(기본값 있는)을 12+에서 빠르게 처리하긴 하지만, **type change·NOT NULL 도입·인덱스 재구성** 같은 변경에는 여전히 도움이 된다.
9.4 Atlas/Bytebase + 온라인 DDL
도구 통합이 막 시작됐다.
- **Atlas**: `migrate lint`가 큰 테이블 변경을 경고. 실행은 여전히 외부 도구.
- **Bytebase**: 일부 변경을 자동으로 gh-ost로 라우팅하는 모드(엔터프라이즈).
- 대부분의 팀은 여전히 **'Atlas/Liquibase가 만든 SQL을 사람이 보고, 큰 테이블이면 gh-ost로 직접 실행'** 패턴.
10장 · 실전 시나리오 — 도구별 풀이
같은 변경을 도구별로 보면 차이가 극명하다. 시나리오 셋.
10.1 시나리오 A — 새 컬럼 추가 (`status`, 기본값 `'active'`)
**Flyway**
-- V012__add_users_status.sql
ALTER TABLE users ADD COLUMN status VARCHAR(20) DEFAULT 'active' NOT NULL;
**Liquibase**
- changeSet:
id: 012-add-users-status
author: bob
changes:
- addColumn:
tableName: users
columns:
- column:
name: status
type: VARCHAR(20)
defaultValue: 'active'
constraints: { nullable: false }
rollback:
- dropColumn: { tableName: users, columnName: status }
**Prisma Migrate** — `schema.prisma`에 `status String @default("active")` 추가 후 `prisma migrate dev`.
**Drizzle Kit** — `schema.ts`에 `status: varchar('status', { length: 20 }).default('active').notNull()` 추가 후 `drizzle-kit generate`.
**Atlas (declarative)** — `schema.hcl`에 `column "status"` 블록 추가, `atlas schema apply`.
**Atlas (versioned)** — 위와 같이 `schema.hcl` 수정 후 `atlas migrate diff add_status` → SQL 파일 자동 생성.
**큰 테이블이라면** — Postgres 12+는 기본값 있는 컬럼 추가도 빠르지만, MySQL 8.0 이전이거나 매우 큰 테이블이면 gh-ost로 실행한다. Atlas Lint가 사전 경고.
10.2 시나리오 B — 기존 컬럼에 NOT NULL 도입 (백필 후)
가장 위험한 패턴 중 하나. 잘못하면 락이 길게 걸린다.
**안전한 순서 (expand-contract 패턴 변형)**:
1. 컬럼은 이미 있고 nullable. 백필 SQL을 batch로 실행 (`UPDATE ... WHERE id BETWEEN ... AND ...`).
2. application 코드가 더 이상 NULL을 쓰지 않게 수정·배포.
3. `NOT NULL` constraint를 추가 — Postgres 12+에서는 `NOT VALID` + `VALIDATE CONSTRAINT` 패턴으로 락 시간 최소화.
**Flyway** — 위 1~3을 각각 V-파일로 나누어 적는다.
**Liquibase** — `addNotNullConstraint`. 백필은 `sql` change 또는 별도 ChangeSet.
**Atlas** — `schema.hcl`에서 `null = true`를 `null = false`로 바꾼다. **`atlas migrate lint`가 데이터가 있다면 경고**한다(unsafe DDL).
**Prisma/Drizzle Kit** — 자동 diff는 `ALTER TABLE ... ALTER COLUMN ... SET NOT NULL`만 만든다. 백필은 사람이 별도 migration SQL로 추가해야 안전.
**Bytebase** — 자동 SQL Review가 "백필 없이 NOT NULL을 도입하려고 함"을 잡는다(룰을 켰다면).
10.3 시나리오 C — 컬럼 리네임 (`name` → `display_name`)
가장 골치 아픈 패턴. 자동 diff 도구들이 잘 못 잡는다 — drop + add로 인식한다.
**모든 도구의 공통 안전한 순서 (롤링 리네임)**:
1. `display_name` 추가. 트리거 또는 dual-write로 `name` ↔ `display_name` 동기화.
2. application을 `display_name`만 읽고 쓰게 변경·배포.
3. 한참 후 — `name` 컬럼 제거.
**Flyway·Liquibase** — 위 1~3을 각각 명시적으로 적는다.
**Atlas (declarative)** — `schema.hcl`에서 컬럼 이름을 바꾸면 도구는 기본적으로 drop + add로 본다. **rename hint**를 명시적으로 적어야 함:
column "display_name" {
type = varchar(100)
null = true
comment = "renamed from name"
}
그리고 atlas migrate diff 시 --rename old_to_new 같은 힌트 필요
**Prisma/Drizzle** — 자동으로 drop + add를 만든다. 데이터 손실 위험. **반드시 마이그레이션 SQL을 손으로 수정**해 `ALTER TABLE ... RENAME COLUMN`으로 바꾼다. ORM의 `@map`/`varchar('display_name')` 매핑으로 코드 이름은 따로 유지.
**교훈**: 리네임은 어떤 도구든 자동 diff에 100% 맡기지 않는다. 사람의 확인이 필수.
11장 · 7축 비교 — 한눈에
11.1 선언형 vs 명령형
| 도구 | 선언형 | 명령형 |
| --- | --- | --- |
| Atlas | O (`schema apply`) | O (`migrate diff/apply`) |
| Skeema | O | X |
| Drizzle Kit | O (스키마) | O (생성된 SQL) |
| Prisma Migrate | O (`db push`, dev) | O (`migrate deploy`) |
| Liquibase | X | O |
| Flyway | X | O |
| Bytebase | 일부 | O |
11.2 다중 DB 지원
| 도구 | Postgres | MySQL | SQLite | Oracle | SQL Server | 기타 |
| --- | --- | --- | --- | --- | --- | --- |
| Atlas | O | O | O | 일부 | O | ClickHouse 일부 |
| Bytebase | O | O | O | O | O | 25종 이상 |
| Liquibase | O | O | O | O | O | DB2·Snowflake 등 |
| Flyway | O | O | O | O | O | 다수 |
| Skeema | O | O | X | X | X | - |
| Prisma | O | O | O | X | O | MongoDB 제한 |
| Drizzle | O | O | O | X | X | D1·LibSQL 등 |
11.3 리뷰 워크플로
| 도구 | 빌트인 리뷰 | 자동 lint | LLM 리뷰 |
| --- | --- | --- | --- |
| Bytebase | O (GUI) | O | O |
| Atlas Cloud | O | O | 일부 |
| Liquibase Hub | O | O | O (Advisor) |
| Flyway Enterprise | 일부 | 일부 | 도입 중 |
| 나머지 (CLI) | X (Git PR로 대체) | X | X |
11.4 드리프트 감지
| 도구 | 자동 드리프트 감지 | 비고 |
| --- | --- | --- |
| Atlas (Cloud) | O | 가장 성숙 |
| Bytebase | O | GUI에서 |
| Liquibase | 일부 | history table 기반 |
| Flyway | 일부 | history table 기반 |
| Skeema·Prisma·Drizzle | 제한 | 도구 실행 시점에만 |
11.5 AI 어시스턴스 (2026)
| 도구 | AI 기능 |
| --- | --- |
| Bytebase | 자연어→SQL, SQL Review, 변경 영향 분석 |
| Atlas | Migration lint + 일부 AI 추천 |
| Liquibase | Hub Advisor (LLM 리뷰) |
| 나머지 | 외부 도구(Copilot, Cursor)에 의존 |
11.6 온라인 DDL 통합
| 도구 | 직접 지원 | 안전한 lint | gh-ost 라우팅 |
| --- | --- | --- | --- |
| gh-ost·pt-osc·pg-osc | (도구 본인) | - | - |
| Atlas | X | O (Lint) | X (수동) |
| Bytebase Enterprise | 일부 | O | O |
| Liquibase | X | 일부 | X |
| 나머지 | X | X | X |
11.7 ORM 통합 매끄러움
| 도구 | TypeScript ORM | Java/Kotlin | Python | Go |
| --- | --- | --- | --- | --- |
| Prisma Migrate | 최고(자체) | - | - | - |
| Drizzle Kit | 최고(자체) | - | - | - |
| Atlas | 좋음(Atlas + ORM) | 좋음(Atlas + JPA) | 좋음(Atlas + SQLAlchemy) | 최고 (Atlas 본가) |
| Liquibase | 보통 | 최고 (Spring) | 좋음 | 보통 |
| Flyway | 보통 | 최고 (Spring) | 좋음 | 보통 |
| Skeema | 보통 | 보통 | 보통 | 보통 |
12장 · 팀별 결정 프레임워크
도구 결정의 첫 번째는 도구의 우월성이 아니라 **팀의 모양**이다.
12.1 1~3인 풀스택 팀 (TS/Next.js)
- **Prisma Migrate** 또는 **Drizzle Kit** 단독으로 충분.
- ORM과 마이그레이션이 한 묶음이라 학습·운영 비용 최소.
- 셰도우 DB가 필요한 Prisma의 dev 워크플로가 부담이면 Drizzle Kit.
- 추가 안전망 — Atlas Cloud free tier로 드리프트 감지만 붙이는 정도.
12.2 10~30인 다중 팀, TS 메인 (스타트업)
- **Drizzle Kit** + **Atlas (lint + 드리프트 감지)** 조합이 늘었다.
- Bytebase는 아직 오버킬.
- GitOps 모드: PR에 `drizzle-kit generate` 결과 SQL이 들어가고, CI에서 `atlas migrate lint`.
12.3 50인+ 다중 DB 다중 서비스 (mid-stage 스타트업)
- **Bytebase** + **Atlas** 또는 **Bytebase** + **Liquibase**.
- 다중 DB 지원·승인 워크플로가 필요한 단계.
- DBA 또는 platform 팀이 정식으로 마이그레이션 게이트키퍼.
12.4 자바·Spring Boot 위주 엔터프라이즈
- **Flyway** (단순한 변경 위주) 또는 **Liquibase** (롤백·감사 중요).
- 추가로 **Atlas** 또는 **Bytebase**를 멀티 DB·드리프트 감지용으로 얹는 패턴도 늘었다.
12.5 큰 테이블이 핵심 (10억 row+)
- 어떤 마이그레이션 도구를 쓰든, 큰 테이블 변경은 **gh-ost**·**pt-osc**·**pg-osc**로 분리.
- Bytebase Enterprise의 자동 라우팅 또는 수동 실행.
- 마이그레이션 도구는 lint·dry-run에서 큰 테이블 변경을 미리 잡아 경고해야 함.
12.6 멀티 클라우드·멀티 DB 엔진 (Postgres + MySQL + Snowflake 등)
- **Bytebase** 또는 **Liquibase** — 가장 폭넓은 엔진 지원.
- Atlas도 멀티 DB 지원이지만 Oracle·DB2·Snowflake 같은 곳은 Liquibase가 더 성숙.
13장 · 안티 체크리스트
피해야 할 패턴들.
1. **두 개의 마이그레이션 도구를 한 DB에 동시에 운영** — Prisma Migrate가 만든 `_prisma_migrations`과 Flyway의 `flyway_schema_history`가 동시에 존재. 진실의 원천이 둘.
2. **자동 diff를 100% 신뢰** — 컬럼 리네임은 drop + add로 인식된다. 사람이 본다.
3. **rollback 없이 destructive change** — `DROP COLUMN`을 production 직전에 머지하고, 문제 생기면 백업에서 복원? 안 된다. expand-contract로 풀어야.
4. **큰 테이블에 비조건적 DDL** — 락이 길게 걸린다. `NOT NULL` 도입 전 백필 + `NOT VALID` 패턴.
5. **드리프트를 감지 안 하는 production** — 누군가 `ALTER TABLE`을 직접 친 사실을 1년 뒤에 알면 늦다.
6. **CI에서 마이그레이션 lint 없음** — `atlas migrate lint` 또는 Liquibase/Bytebase 룰. 사람 리뷰가 만능이 아니다.
7. **dev/staging/prod 사이 스키마 불일치 방치** — 한 환경에서만 hotfix 적용. 다음 마이그레이션이 어디서 깨질지 모름.
14장 · 실전 권장 워크플로 (참고용)
작은 팀, TS 스택을 가정한 한 가지 권장 워크플로.
1. **스키마는 Drizzle 코드** (또는 Prisma schema). ORM과 한 묶음.
2. **마이그레이션 SQL은 자동 생성 + 사람 리뷰**. `drizzle-kit generate` 또는 `prisma migrate dev`로 생성된 SQL 파일을 PR로.
3. **CI에서 `atlas migrate lint` 또는 비슷한 lint** — 위험 DDL 사전 차단.
4. **production은 `migrate deploy`** (Prisma) 또는 `drizzle-kit migrate`. 셰도우 DB 사용.
5. **Atlas Cloud(또는 동등)로 드리프트 감지** — 누가 직접 친 ALTER를 잡는다.
6. **큰 테이블 변경은 gh-ost/pg-osc로 분리** — 마이그레이션 파일은 placeholder만 남기고, 실제 변경은 runbook에 적힌 외부 도구로.
7. **expand-contract 패턴 의무화** — destructive change는 절대 한 PR로 가지 않는다.
엔터프라이즈라면 위에 **Bytebase의 승인 게이트**가 추가된다. 자바 진영이라면 **Liquibase**가 1, 2번을 대체한다.
에필로그 — 도구는 정책의 표현이지 정책 자체가 아니다
DB 마이그레이션 도구 선택은 **"declarative냐 imperative냐"의 종교 전쟁이 아니다.** 팀이 무엇을 보호하려고 하는지의 함수다.
- 작은 팀, 빠른 반복 — declarative·ORM 통합(Drizzle Kit·Prisma·Atlas).
- 엔터프라이즈·감사 — imperative·명시적 rollback(Liquibase·Flyway).
- 다중 DB·다중 팀 — 리뷰 워크플로(Bytebase) + lint(Atlas).
- 큰 테이블 — 마이그레이션 도구와 별도로 온라인 DDL 도구(gh-ost·pg-osc).
2026년 5월의 풍경에서 가장 큰 변화는 두 가지다.
1. **Atlas의 부상** — declarative + lint + 드리프트 감지를 한 도구로 묶어 점유율을 빠르게 늘리고 있다. Terraform이 인프라에 한 일을 DB에 하고 있다는 평가가 과장은 아니다.
2. **AI 어시스턴스가 카테고리** — Bytebase·Liquibase Hub·Atlas 모두 LLM 기반 리뷰·자연어 변환을 붙였다. 마이그레이션 lint는 더 이상 룰 기반만이 아니다.
결정 체크리스트
- 팀 규모는? — 1~3인이면 ORM 마이그레이션, 50인+면 Bytebase.
- 멀티 DB·멀티 환경인가? — Yes면 Atlas·Bytebase·Liquibase.
- 자바/스프링 위주인가? — Yes면 Flyway·Liquibase.
- 큰 테이블이 있는가? — Yes면 어떤 도구든 gh-ost·pg-osc 추가.
- 드리프트 감지가 필요한가? — Yes면 Atlas Cloud 또는 Bytebase.
- 컴플라이언스(감사·rollback)가 핵심인가? — Yes면 Liquibase.
- 학습 곡선 최소화? — ORM의 자체 마이그레이션 도구.
안티 패턴 요약
1. 자동 diff를 100% 신뢰.
2. 한 DB에 두 마이그레이션 도구 공존.
3. rollback 없이 destructive change.
4. 큰 테이블에 비조건적 NOT NULL.
5. CI에서 마이그레이션 lint 없음.
6. 드리프트 감지 없는 production.
7. 환경 간 스키마 불일치 방치.
다음 글 예고
다음 글 후보: **Atlas 한 달 써본 후기 — HCL이 정말 SQL보다 좋은가**, **gh-ost vs pt-online-schema-change 실측 — 1억 row 테이블에서**, **Bytebase + GitHub Actions로 만드는 DB 변경 자동화 파이프라인**.
> "스키마는 사실이고, 마이그레이션은 그 사실을 옮기는 길이다. 도구는 길을 안전하게 만들어 줄 뿐, 길 자체를 대신 걸어주진 않는다."
— DB 마이그레이션 도구 2026, 끝.
참고 / References
- [Atlas — Modern DB Migration](https://atlasgo.io/)
- [Atlas GitHub — ariga/atlas](https://github.com/ariga/atlas)
- [Atlas Schema Monitoring](https://atlasgo.io/monitoring)
- [Atlas Migrate Lint](https://atlasgo.io/versioned/lint)
- [Bytebase 공식](https://www.bytebase.com/)
- [Bytebase GitHub](https://github.com/bytebase/bytebase)
- [Bytebase SQL Review Rules](https://www.bytebase.com/docs/sql-review/review-policy/overview/)
- [Skeema — Declarative MySQL/Postgres schema management](https://www.skeema.io/)
- [Skeema GitHub](https://github.com/skeema/skeema)
- [Liquibase 공식](https://www.liquibase.com/)
- [Liquibase GitHub](https://github.com/liquibase/liquibase)
- [Flyway 공식](https://flywaydb.org/)
- [Flyway GitHub](https://github.com/flyway/flyway)
- [Prisma Migrate Documentation](https://www.prisma.io/docs/orm/prisma-migrate)
- [Drizzle Kit Documentation](https://orm.drizzle.team/docs/kit-overview)
- [gh-ost — GitHub's online schema migration for MySQL](https://github.com/github/gh-ost)
- [pt-online-schema-change — Percona Toolkit](https://docs.percona.com/percona-toolkit/pt-online-schema-change.html)
- [pg-osc — Postgres online schema change](https://github.com/shayonj/pg-osc)
- [pg_repack — Reorganize tables in PostgreSQL](https://github.com/reorg/pg_repack)
- [Sqitch — Sane database change management](https://sqitch.org/)
- [dbmate — Database migration tool](https://github.com/amacneil/dbmate)
- [PostgreSQL Wiki — Locking](https://wiki.postgresql.org/wiki/Lock_Monitoring)
- [GitHub Engineering — gh-ost: triggerless schema changes](https://github.blog/engineering/databases/gh-ost-triggerless-online-schema-migration-tool-for-mysql/)
현재 단락 (1/415)
DB 스키마 변경은 소프트웨어에서 가장 위험한 작업 중 하나다. 코드 배포는 롤백이 쉽지만, `ALTER TABLE`은 한 번 실행되면 디스크 위의 사실이 된다. 큰 테이블에 잘못...