메인 콘텐츠로 건너뛰기

마이그레이션이란

마이그레이션은 데이터베이스의 버전 관리 같은 것입니다. 팀이 애플리케이션의 데이터베이스 스키마 정의를 공유·관리할 수 있습니다. 소스 코드를 pull한 후에 “로컬 데이터베이스에 컬럼을 수동으로 추가해 주세요”라고 팀 멤버에게 전달해야 하는 상황을 경험한 적이 있을 것입니다. 마이그레이션은 그 문제를 해결합니다. 마이그레이션 파일은 database/migrations 디렉터리에 저장됩니다. 각 파일명에는 타임스탬프가 포함되어 있어 Laravel이 마이그레이션 실행 순서를 결정하는 데 사용됩니다.

마이그레이션 파일 생성

make:migration Artisan 명령으로 새 마이그레이션 파일을 생성합니다.
php artisan make:migration create_posts_table
마이그레이션 이름에서 Laravel이 테이블 이름을 추측하고 적절한 스텁을 생성합니다. create_posts_table이라는 이름이라면 posts 테이블을 생성하는 코드가 미리 준비됩니다.

마이그레이션 구조

마이그레이션 클래스는 updown 두 개의 메서드를 가집니다.
  • up 메서드: 테이블·컬럼·인덱스를 데이터베이스에 추가합니다.
  • down 메서드: up의 조작을 되돌립니다. 롤백 시 호출됩니다.
<?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('posts', function (Blueprint $table) {
            $table->id();
            $table->string('title');
            $table->text('body');
            $table->boolean('published')->default(false);
            $table->timestamps();
        });
    }

    /**
     * 마이그레이션을 되돌린다
     */
    public function down(): void
    {
        Schema::dropIfExists('posts');
    }
};

주요 컬럼 정의 메서드

Blueprint 클래스에는 많은 컬럼 타입이 준비되어 있습니다.
메서드설명
$table->id()자동 증분 기본 키(bigIncrements('id')의 별칭)
$table->string('name')VARCHAR 상당의 컬럼(기본 255자)
$table->text('body')TEXT 컬럼
$table->integer('count')INTEGER 컬럼
$table->boolean('active')TINYINT로 진위값 저장
$table->timestamp('published_at')TIMESTAMP 컬럼
$table->timestamps()created_atupdated_at을 함께 추가
$table->softDeletes()논리 삭제용 deleted_at 컬럼 추가
$table->foreignId('user_id')외래 키용 BIGINT UNSIGNED 컬럼

컬럼 수식자

컬럼 정의에는 메서드 체이닝으로 수식자를 추가할 수 있습니다.
$table->string('email')->unique();
$table->string('name')->nullable();
$table->integer('votes')->default(0);
$table->string('title')->after('id'); // 지정된 컬럼 뒤에 배치

마이그레이션 실행

migrate 명령으로 미실행된 마이그레이션을 모두 실행합니다.
php artisan migrate
실행된 마이그레이션과 미실행된 마이그레이션을 확인하려면 migrate:status를 사용합니다.
php artisan migrate:status
프로덕션 환경에서 마이그레이션을 실행하면 확인 프롬프트가 표시됩니다. 확인 없이 실행하려면 --force 플래그를 사용하지만, 데이터가 손실되는 조작도 있으므로 신중하게 진행해 주세요.

롤백

가장 최근의 마이그레이션 배치를 취소하려면 migrate:rollback을 사용합니다.
php artisan migrate:rollback
특정 스텝 수만큼만 롤백하려면 --step 옵션을 지정합니다.
# 최근 5건의 마이그레이션을 롤백
php artisan migrate:rollback --step=5
모든 마이그레이션을 롤백한 후 다시 실행하려면 migrate:refresh를 사용합니다.
php artisan migrate:refresh
migrate:refresh는 모든 테이블을 다시 만들기 때문에 기존 데이터가 사라집니다. 개발 중 데이터베이스 리셋에 편리합니다.

실전 예시: posts 테이블 생성

블로그 게시물을 관리하는 posts 테이블을 예로 일련의 흐름을 확인합니다.

1. 마이그레이션 파일 생성

php artisan make:migration create_posts_table

2. 마이그레이션 편집

database/migrations/xxxx_xx_xx_xxxxxx_create_posts_table.php를 열어 편집합니다.
<?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('posts', function (Blueprint $table) {
            $table->id();
            $table->foreignId('user_id')->constrained()->cascadeOnDelete();
            $table->string('title');
            $table->text('body');
            $table->boolean('published')->default(false);
            $table->timestamp('published_at')->nullable();
            $table->timestamps();
        });
    }

    public function down(): void
    {
        Schema::dropIfExists('posts');
    }
};

3. 마이그레이션 실행

php artisan migrate
실행 후 데이터베이스에 posts 테이블이 생성됩니다.

4. 컬럼을 나중에 추가하기

테이블 생성 후 새 컬럼을 추가하고 싶은 경우, 기존 마이그레이션을 편집하지 말고 새 마이그레이션을 생성합니다.
php artisan make:migration add_excerpt_to_posts_table
public function up(): void
{
    Schema::table('posts', function (Blueprint $table) {
        $table->string('excerpt')->nullable()->after('title');
    });
}

public function down(): void
{
    Schema::table('posts', function (Blueprint $table) {
        $table->dropColumn('excerpt');
    });
}
기존 마이그레이션 파일을 직접 편집하는 것은 피합시다. 다른 멤버나 프로덕션 환경과의 정합성이 깨집니다. 변경은 항상 새 마이그레이션으로 추가합니다.

마이그레이션 이벤트

마이그레이션 조작마다 이벤트가 발행됩니다. 모든 이벤트는 Illuminate\Database\Events\MigrationEvent를 상속하고 있습니다.
클래스설명
Illuminate\Database\Events\DatabaseRefreshedmigrate:refresh 명령의 완료 후
Illuminate\Database\Events\MigrationsStarted마이그레이션 배치가 실행되기 직전
Illuminate\Database\Events\MigrationsEnded마이그레이션 배치의 완료 후
Illuminate\Database\Events\MigrationStarted단일 마이그레이션이 실행되기 직전
Illuminate\Database\Events\MigrationEnded단일 마이그레이션의 완료 후
Illuminate\Database\Events\NoPendingMigrations마이그레이션 명령이 미실행 마이그레이션이 없다고 판정했을 때
Illuminate\Database\Events\SchemaDumped데이터베이스 스키마 덤프의 완료 후
Illuminate\Database\Events\SchemaLoaded기존 스키마 덤프의 로드 후
예를 들어 MigrationsEnded 이벤트를 리슨해 마이그레이션 완료 후 캐시를 삭제할 수 있습니다.
use Illuminate\Database\Events\MigrationsEnded;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Event;

Event::listen(MigrationsEnded::class, function () {
    Cache::flush();
});

다음 단계

데이터베이스 시딩

마이그레이션으로 생성한 테이블에 샘플 데이터를 투입하는 방법을 배웁니다.

Eloquent 입문

마이그레이션으로 생성한 테이블을 Eloquent ORM으로 조작하는 방법을 배웁니다.
마지막 수정일 2026년 7월 13일