마이그레이션
번역일: 2026년 6월 20일
마이그레이션
소개
마이그레이션은 데이터베이스를 위한 버전 관리 시스템이라고 생각하면 됩니다. 팀원들이 애플리케이션의 데이터베이스 스키마를 코드로 정의하고 공유할 수 있게 해줍니다. 소스 컨트롤에서 변경 사항을 받아온 뒤 "로컬 DB에 직접 컬럼 추가해줘"라고 팀원에게 말해야 했던 경험이 있다면, 마이그레이션이 해결하는 문제가 무엇인지 잘 아실 겁니다.
Laravel의 Schema 파사드는 Laravel이 지원하는 모든 데이터베이스에서 테이블과 컬럼을 생성·수정할 수 있는 데이터베이스 독립적인 API를 제공합니다. 마이그레이션은 일반적으로 이 파사드를 사용해 테이블과 컬럼을 정의합니다.
마이그레이션 생성
make:migration Artisan 명령어로 마이그레이션 파일을 생성할 수 있습니다. 생성된 파일은 database/migrations 디렉터리에 저장되며, 파일명에는 타임스탬프가 포함되어 Laravel이 마이그레이션 실행 순서를 결정할 수 있습니다.
php artisan make:migration create_flights_tableLaravel은 마이그레이션 이름에서 테이블 이름과 새 테이블 생성 여부를 추론합니다. 이름에서 테이블명을 파악할 수 있으면 생성된 파일에 해당 테이블명이 미리 채워집니다. 자동으로 추론되지 않는 경우에는 파일을 열어 직접 지정하면 됩니다.
생성 위치를 직접 지정하려면 --path 옵션을 사용하세요. 지정한 경로는 애플리케이션 루트를 기준으로 한 상대 경로입니다.
NOTE
마이그레이션 스텁 파일은 스텁 퍼블리싱을 통해 커스터마이징할 수 있습니다.
마이그레이션 스쿼싱
애플리케이션을 개발하다 보면 마이그레이션 파일이 수백 개까지 쌓일 수 있습니다. database/migrations 디렉터리가 복잡해진다면, 모든 마이그레이션을 하나의 SQL 파일로 합칠 수 있습니다. schema:dump 명령어를 실행하세요.
php artisan schema:dump# 현재 스키마를 덤프하고 기존 마이그레이션 파일을 모두 삭제...php artisan schema:dump --prune이 명령어를 실행하면 Laravel이 database/schema 디렉터리에 스키마 파일을 생성합니다. 파일명은 사용 중인 데이터베이스 커넥션 이름을 따릅니다. 이후 마이그레이션을 실행할 때, 아직 실행된 마이그레이션이 없다면 Laravel은 해당 스키마 파일의 SQL을 먼저 실행한 뒤 스키마 덤프에 포함되지 않은 나머지 마이그레이션을 순서대로 실행합니다.
테스트에서 로컬 개발 시와 다른 데이터베이스 커넥션을 사용한다면, 해당 커넥션에 대한 스키마 파일도 별도로 덤프해야 테스트에서 DB를 올바르게 구성할 수 있습니다.
php artisan schema:dumpphp artisan schema:dump --database=testing --prune스키마 파일은 소스 컨트롤에 커밋해 두세요. 새로운 팀원이 프로젝트에 합류했을 때 초기 데이터베이스 구조를 빠르게 구성할 수 있습니다.
WARNING
마이그레이션 스쿼싱은 MariaDB, MySQL, PostgreSQL, SQLite 데이터베이스에서만 지원되며, 각 데이터베이스의 커맨드라인 클라이언트를 사용합니다.
마이그레이션 구조
마이그레이션 클래스는 up과 down 두 메서드로 구성됩니다. up 메서드는 테이블, 컬럼, 인덱스를 추가하는 데 사용하고, down 메서드는 up에서 수행한 작업을 되돌립니다.
두 메서드 안에서 Laravel 스키마 빌더를 사용해 테이블을 생성하고 수정할 수 있습니다. Schema 빌더에서 사용 가능한 모든 메서드는 테이블 생성 문서를 참고하세요. 다음은 flights 테이블을 생성하는 마이그레이션 예시입니다.
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* 마이그레이션 실행
*/
public function up(): void
{
Schema::create('flights', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('airline');
$table->timestamps();
});
}
/**
* 마이그레이션 되돌리기
*/
public function down(): void
{
Schema::drop('flights');
}
};마이그레이션 커넥션 지정
마이그레이션이 애플리케이션의 기본 데이터베이스 커넥션이 아닌 다른 커넥션을 사용해야 한다면, 마이그레이션 클래스의 $connection 프로퍼티를 설정하세요.
/**
* 이 마이그레이션에서 사용할 데이터베이스 커넥션
*
* @var string
*/
protected $connection = 'pgsql';
/**
* 마이그레이션 실행
*/
public function up(): void
{
// ...
}마이그레이션 실행
아직 실행되지 않은 모든 마이그레이션을 실행하려면 migrate Artisan 명령어를 사용하세요.
php artisan migrate지금까지 실행된 마이그레이션 목록을 확인하려면 migrate:status 명령어를 사용하세요.
php artisan migrate:status실제 실행 없이 어떤 SQL이 실행될지 미리 확인하려면 --pretend 플래그를 사용하세요.
php artisan migrate --pretend마이그레이션 동시 실행 방지
여러 서버에 배포하면서 배포 과정에서 마이그레이션을 실행한다면, 두 서버가 동시에 마이그레이션을 실행하는 상황을 피해야 합니다. 이를 방지하려면 --isolated 옵션을 사용하세요.
--isolated 옵션을 지정하면 Laravel이 마이그레이션을 시작하기 전에 캐시 드라이버를 통해 원자적 락(atomic lock)을 획득합니다. 락이 유지되는 동안 다른 서버에서 실행된 migrate 명령어는 실제로 실행되지 않지만, 성공 코드로 종료됩니다.
php artisan migrate --isolatedWARNING
이 기능을 사용하려면 애플리케이션의 기본 캐시 드라이버가 memcached, redis, dynamodb, database, file, array 중 하나여야 합니다. 또한 모든 서버가 동일한 중앙 캐시 서버에 연결되어 있어야 합니다.
프로덕션 환경에서 강제 실행
일부 마이그레이션 작업은 데이터 손실을 유발할 수 있어, 프로덕션 데이터베이스에 실행하기 전에 확인 메시지가 표시됩니다. 확인 없이 강제로 실행하려면 --force 플래그를 사용하세요.
php artisan migrate --force마이그레이션 롤백
가장 최근에 실행된 마이그레이션 배치를 되돌리려면 migrate:rollback 명령어를 사용하세요. 하나의 배치에는 여러 마이그레이션 파일이 포함될 수 있습니다.
php artisan migrate:rollback--step 옵션으로 되돌릴 마이그레이션 수를 제한할 수 있습니다. 예를 들어 아래 명령어는 최근 5개의 마이그레이션을 롤백합니다.
php artisan migrate:rollback --step=5--batch 옵션으로 특정 배치 번호에 해당하는 마이그레이션만 롤백할 수도 있습니다. 배치 값은 migrations 테이블에서 확인할 수 있습니다. 예를 들어 아래 명령어는 배치 번호 3에 해당하는 마이그레이션을 모두 롤백합니다.
php artisan migrate:rollback --batch=3실제 실행 없이 어떤 SQL이 실행될지 미리 확인하려면 --pretend 플래그를 사용하세요.
php artisan migrate:rollback --pretend모든 마이그레이션을 롤백하려면 migrate:reset 명령어를 사용하세요.
php artisan migrate:reset롤백 후 즉시 재실행
migrate:refresh 명령어는 모든 마이그레이션을 롤백한 뒤 다시 실행합니다. 데이터베이스 전체를 처음부터 다시 구성하는 효과가 있습니다.
php artisan migrate:refresh# 데이터베이스를 초기화하고 시더까지 실행...php artisan migrate:refresh --seed--step 옵션으로 최근 N개의 마이그레이션만 롤백 후 재실행할 수 있습니다.
php artisan migrate:refresh --step=5모든 테이블 삭제 후 마이그레이션
migrate:fresh 명령어는 데이터베이스의 모든 테이블을 삭제한 뒤 마이그레이션을 처음부터 실행합니다.
php artisan migrate:freshphp artisan migrate:fresh --seed기본적으로 migrate:fresh는 기본 데이터베이스 커넥션의 테이블만 삭제합니다. --database 옵션으로 대상 커넥션을 지정할 수 있으며, 커넥션 이름은 database 설정 파일에 정의된 이름과 일치해야 합니다.
php artisan migrate:fresh --database=adminWARNING
migrate:fresh 명령어는 테이블 접두사에 관계없이 데이터베이스의 모든 테이블을 삭제합니다. 다른 애플리케이션과 공유하는 데이터베이스에서 사용할 때는 각별히 주의하세요.
테이블
테이블 생성
새 데이터베이스 테이블을 생성하려면 Schema 파사드의 create 메서드를 사용하세요. 첫 번째 인자는 테이블 이름, 두 번째 인자는 Blueprint 객체를 받는 클로저입니다.
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email');
$table->timestamps();
});테이블을 생성할 때 스키마 빌더의 컬럼 메서드를 사용해 테이블의 컬럼을 정의할 수 있습니다.
테이블 / 컬럼 존재 여부 확인
hasTable, hasColumn, hasIndex 메서드로 테이블, 컬럼, 인덱스의 존재 여부를 확인할 수 있습니다.
if (Schema::hasTable('users')) {
// "users" 테이블이 존재함...
}
if (Schema::hasColumn('users', 'email')) {
// "users" 테이블에 "email" 컬럼이 존재함...
}
if (Schema::hasIndex('users', ['email'], 'unique')) {
// "users" 테이블의 "email" 컬럼에 유니크 인덱스가 존재함...
}데이터베이스 커넥션 및 테이블 옵션
기본 커넥션이 아닌 다른 커넥션에서 스키마 작업을 수행하려면 connection 메서드를 사용하세요.
Schema::connection('sqlite')->create('users', function (Blueprint $table) {
$table->id();
});그 외에도 테이블 생성 시 다양한 옵션을 설정할 수 있습니다. MariaDB / MySQL에서 스토리지 엔진을 지정하려면 engine 메서드를 사용하세요.
Schema::create('users', function (Blueprint $table) {
$table->engine('InnoDB');
// ...
});MariaDB / MySQL에서 문자셋과 콜레이션을 지정하려면 charset과 collation 메서드를 사용하세요.
Schema::create('users', function (Blueprint $table) {
$table->charset('utf8mb4');
$table->collation('utf8mb4_unicode_ci');
// ...
});임시 테이블을 생성하려면 temporary 메서드를 사용하세요. 임시 테이블은 현재 데이터베이스 세션에서만 보이며 커넥션이 닫힐 때 자동으로 삭제됩니다.
Schema::create('calculations', function (Blueprint $table) {
$table->temporary();
// ...
});테이블에 코멘트를 추가하려면 comment 메서드를 사용하세요. 테이블 코멘트는 현재 MariaDB, MySQL, PostgreSQL에서만 지원됩니다.
Schema::create('calculations', function (Blueprint $table) {
$table->comment('비즈니스 계산용 테이블');
// ...
});테이블 수정
기존 테이블에 컬럼이나 인덱스를 추가하려면 Schema 파사드의 table 메서드를 사용하세요. create와 마찬가지로 테이블 이름과 Blueprint 인스턴스를 받는 클로저를 인자로 받습니다.
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
Schema::table('users', function (Blueprint $table) {
$table->integer('votes');
});테이블 이름 변경 / 삭제
테이블 이름을 변경하려면 rename 메서드를 사용하세요.
use Illuminate\Support\Facades\Schema;
Schema::rename($from, $to);테이블을 삭제하려면 drop 또는 dropIfExists 메서드를 사용하세요.
Schema::drop('users');
Schema::dropIfExists('users');외래 키가 있는 테이블 이름 변경 시 주의사항
테이블 이름을 변경하기 전에, 마이그레이션 파일에서 해당 테이블의 외래 키 제약에 명시적인 이름이 지정되어 있는지 확인하세요. Laravel이 자동으로 생성한 이름을 사용하는 경우, 외래 키 제약 이름에 이전 테이블명이 그대로 남아 있을 수 있습니다.
컬럼
컬럼 생성
기존 테이블에 컬럼을 추가할 때도 Schema 파사드의 table 메서드를 사용합니다. 클로저에서 Illuminate\Database\Schema\Blueprint 인스턴스를 받아 컬럼을 추가할 수 있습니다.
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
Schema::table('users', function (Blueprint $table) {
$table->integer('votes');
});사용 가능한 컬럼 타입
스키마 빌더 Blueprint는 데이터베이스 테이블에 추가할 수 있는 다양한 컬럼 타입 메서드를 제공합니다. 사용 가능한 메서드는 아래에서 확인하세요.
불리언 타입
문자열 및 텍스트 타입
숫자 타입
bigIncrements bigInteger decimal double float id increments integer mediumIncrements mediumInteger smallIncrements smallInteger tinyIncrements tinyInteger unsignedBigInteger unsignedInteger unsignedMediumInteger unsignedSmallInteger unsignedTinyInteger
날짜 및 시간 타입
dateTime dateTimeTz date time timeTz timestamp timestamps timestampsTz softDeletes softDeletesTz year
바이너리 타입
오브젝트 및 JSON 타입
UUID 및 ULID 타입
공간 타입
관계 타입
특수 타입
`bigIncrements()` {.collection-method .first-collection-method}
자동 증가하는 UNSIGNED BIGINT(기본 키) 컬럼을 생성합니다.
$table->bigIncrements('id');
`bigInteger()` {.collection-method}
BIGINT 컬럼을 생성합니다.
$table->bigInteger('votes');
`binary()` {.collection-method}
BLOB 컬럼을 생성합니다.
$table->binary('photo');
MySQL, MariaDB, SQL Server에서는 length와 fixed 인자를 전달해 VARBINARY 또는 BINARY 컬럼을 생성할 수 있습니다.
$table->binary('data', length: 16); // VARBINARY(16)
$table->binary('data', length: 16, fixed: true); // BINARY(16)`boolean()` {.collection-method}
BOOLEAN 컬럼을 생성합니다.
$table->boolean('confirmed');
`char()` {.collection-method}
지정한 길이의 CHAR 컬럼을 생성합니다.
$table->char('name', length: 100);
`dateTimeTz()` {.collection-method}
타임존 정보를 포함한 DATETIME 컬럼을 생성합니다. 소수점 이하 초 정밀도를 선택적으로 지정할 수 있습니다.
$table->dateTimeTz('created_at', precision: 0);
`dateTime()` {.collection-method}
DATETIME 컬럼을 생성합니다. 소수점 이하 초 정밀도를 선택적으로 지정할 수 있습니다.
$table->dateTime('created_at', precision: 0);
`date()` {.collection-method}
DATE 컬럼을 생성합니다.
$table->date('created_at');