개요

sqldef는 멱등적(idempotent) DB 스키마 관리 CLI 도구로, “원하는 스키마 상태”를 SQL로 선언하면 현재 DB와 비교하여 필요한 DDL을 자동 생성·실행합니다. 순차적 마이그레이션 파일 없이 schema.sql 하나로 스키마를 관리합니다.

  • 개발: k0kubun (Takashi Kokubun)
  • 언어: Go
  • 라이선스: MIT
  • GitHub: https://github.com/sqldef/sqldef
  • 지원 DB: MySQL, MariaDB, TiDB, PostgreSQL, SQL Server, SQLite3

핵심 개념

선언적 스키마 관리

기존 마이그레이션                  sqldef
──────────────                   ──────
001_create_users.sql             schema.sql (원하는 최종 상태)
002_add_email.sql                    ↓
003_add_index.sql                sqldef가 현재 DB와 비교
004_alter_column.sql                 ↓
    ↓                            필요한 DDL 자동 생성
순서대로 실행                         ↓
                                 실행 (멱등적)
  • 멱등성: 몇 번 실행해도 동일 결과 → 안전한 반복 실행
  • 선언적: “어떻게 변경하지?”가 아닌 “최종 상태가 뭐지?”만 정의
  • Terraform이 인프라에 하는 것을 DB 스키마에 적용한 개념

사용법

기본 사용

# 설치
brew install sqldef/tap/mysqldef   # MySQL
brew install sqldef/tap/psqldef    # PostgreSQL
brew install sqldef/tap/sqlite3def # SQLite
 
# 원하는 스키마 정의
cat > schema.sql << 'EOF'
CREATE TABLE users (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(255) NOT NULL,
    email VARCHAR(255) NOT NULL UNIQUE,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
 
CREATE TABLE posts (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    user_id BIGINT NOT NULL,
    title VARCHAR(255) NOT NULL,
    body TEXT,
    FOREIGN KEY (user_id) REFERENCES users(id)
);
EOF
 
# 스키마 적용 (MySQL)
cat schema.sql | mysqldef -u root -p password mydb
 
# PostgreSQL
cat schema.sql | psqldef -U postgres mydb
 
# SQLite
cat schema.sql | sqlite3def mydb.sqlite3

Dry Run (변경 미리보기)

# 실행하지 않고 생성될 DDL만 확인
cat schema.sql | mysqldef -u root mydb --dry-run
 
# 출력 예:
# ALTER TABLE users ADD COLUMN email VARCHAR(255) NOT NULL UNIQUE;
# CREATE TABLE posts (...);

스키마 내보내기

# 현재 DB 스키마를 SQL로 내보내기
mysqldef -u root mydb --export > current_schema.sql

동작 방식

schema.sql (원하는 상태)     현재 DB 스키마
        ↓                        ↓
    ┌─────────────────────────────┐
    │        sqldef (diff)         │
    │  파싱 → 비교 → DDL 생성      │
    └─────────────────────────────┘
                 ↓
    필요한 DDL 문 (ALTER, CREATE, DROP)
                 ↓
            DB에 실행

자동 생성되는 DDL 예시:

변경생성되는 DDL
컬럼 추가ALTER TABLE users ADD COLUMN email VARCHAR(255)
컬럼 삭제ALTER TABLE users DROP COLUMN old_field (—enable-drop-table)
타입 변경ALTER TABLE users MODIFY COLUMN name TEXT
인덱스 추가CREATE INDEX idx_email ON users(email)
테이블 생성CREATE TABLE posts (...)
테이블 삭제DROP TABLE old_table (—enable-drop-table)

옵션

옵션설명
--dry-runDDL 생성만 하고 실행하지 않음
--export현재 DB 스키마를 SQL로 출력
--enable-drop-tableDROP TABLE 허용 (기본: 비활성)
--skip-dropDROP 문 생성 스킵 (안전 모드)
--file스키마 파일 경로 지정

기존 마이그레이션 도구 vs sqldef

항목sqldefFlywayAlembicAtlasLiquibase
방식선언적순차적순차적선언적순차적
파일schema.sql 1개버전별 파일버전별 파일HCL/SQLchangelog
멱등성자동수동 관리수동 관리자동수동 관리
롤백역방향 DDL 자동down 파일 필요downgrade 필요자동rollback
데이터 마이그레이션XOOOO
프레임워크 통합X (CLI 전용)Java/SpringPython/SQLAlchemyGoJava
학습 곡선최저중간중간중간높음
언어GoJavaPythonGoJava

유사 도구

도구특징
AtlasHCL/SQL 선언적 스키마, sqldef 유사하지만 더 풍부한 기능
MigraPostgreSQL 전용, 스키마 diff → DDL
pgschemaPostgreSQL 선언적 스키마
pg_rollPostgreSQL 무중단 마이그레이션
SkeemaMySQL 선언적 스키마 (상용)

장점

  • 단순함: schema.sql 하나로 스키마 관리, 마이그레이션 파일 히스토리 불필요
  • 멱등성: CI/CD에서 반복 실행 안전
  • 표준 SQL: 별도 DSL 없이 일반 CREATE TABLE 문법
  • 경량: Go 단일 바이너리, 외부 의존성 없음
  • WebAssembly 데모: 브라우저에서 바로 테스트 가능

제한 사항

  • 데이터 마이그레이션 불가: 스키마(DDL)만 관리, 데이터 변환(DML)은 별도 처리 필요
  • 복잡한 마이그레이션: 컬럼 이름 변경 시 “삭제 + 생성”으로 처리 → 데이터 손실 위험
  • 프로덕션 주의: DROP 기본 비활성이지만, 대규모 ALTER는 테이블 잠금 발생 가능
  • 빈 DB에 최적: 데이터가 많은 프로덕션 DB에서는 신중한 dry-run 필수

사용 사례

용도적합도
새 프로젝트 스키마 관리최적
CI/CD 스키마 동기화최적
개발/테스트 환경 초기화최적
프로덕션 점진적 마이그레이션주의 필요
데이터 변환 포함 마이그레이션부적합 (별도 도구 병행)

관련 항목