본문 바로가기

마이그레이션

업데이트됨

번역일: 2026년 9월 19일

이 페이지는 원문이 업데이트되어 번역이 갱신되었습니다.

원문 수정
2026년 9월 19일
번역 갱신
2026년 9월 19일

마이그레이션

소개

마이그레이션은 데이터베이스에도 버전 관리 시스템을 도입한 것이라고 생각하면 됩니다. 덕분에 팀 전체가 애플리케이션의 데이터베이스 스키마 정의를 함께 정의하고 공유할 수 있습니다. 협업 중인 동료에게 "로컬 데이터베이스에 컬럼 하나 추가해줘"라고 말로 전달하는 대신, 동료가 소스 컨트롤에서 최신 변경 사항을 받아 바로 실행할 수 있는 마이그레이션 파일 하나만 공유하면 됩니다.

NOTE

Blade로 데이터베이스 테이블 구조를 시각적으로 살펴보고 싶다면 Laravel Schema Designer를 확인해보세요. Tinkerwell에서 제공하는 이 무료 도구는 Laravel 애플리케이션과 훌륭하게 통합됩니다.

Laravel의 Schema 파사드는 Laravel이 지원하는 모든 데이터베이스 시스템에 대해 테이블을 생성하고 조작할 수 있는, 데이터베이스에 종속되지 않는 기능을 제공합니다. 일반적으로 마이그레이션은 이 파사드를 사용해서 데이터베이스 테이블과 컬럼을 생성하고 수정합니다.

마이그레이션 생성하기

make:migration Artisan 명령어를 사용해 데이터베이스 마이그레이션을 생성할 수 있습니다. 새로 생성된 마이그레이션은 database/migrations 디렉터리에 저장됩니다. 각 마이그레이션 파일명에는 타임스탬프가 포함되는데, 이를 통해 Laravel이 마이그레이션 실행 순서를 결정합니다.

php artisan make:migration create_flights_table

Laravel은 마이그레이션의 이름을 기반으로 테이블명과 새 테이블 생성 여부를 추측하여, 가능한 경우 마이그레이션 파일에 지정된 테이블을 미리 채워줍니다. 만약 마이그레이션 이름에서 테이블명을 자동으로 감지하기 어렵다면, 명령어에 --table이나 --create 옵션을 사용해 직접 테이블명을 지정할 수 있습니다.

php artisan make:migration add_paid_to_orders_table --table=ordersphp artisan make:migration create_orders_table --create=orders

생성된 마이그레이션을 특정 경로에 저장하고 싶다면 make:migration 명령어 실행 시 --path 옵션을 사용하면 됩니다. 이때 지정하는 경로는 애플리케이션의 베이스 경로를 기준으로 한 상대 경로여야 합니다.

NOTE

마이그레이션 스텁(stub)은 스텁 커스터마이징을 통해 원하는 형태로 수정할 수 있습니다.

마이그레이션 스쿼싱

애플리케이션을 개발하다 보면 시간이 지남에 따라 database/migrations 디렉터리에 점점 더 많은 마이그레이션 파일이 쌓이게 됩니다. 이 디렉터리가 수백 개의 마이그레이션 파일로 비대해지면 감당하기 어려워질 수 있습니다. 이럴 때는 마이그레이션을 하나의 SQL 파일로 "스쿼싱(squash)"할 수 있습니다. 시작하려면 schema:dump 명령어를 실행하세요.

php artisan schema:dump# 현재 데이터베이스 스키마를 덤프하고 기존 마이그레이션을 모두 정리합니다...php artisan schema:dump --prune

이 명령어를 실행하면 Laravel이 애플리케이션의 database/schema 디렉터리에 "스키마" 파일을 작성합니다. 이 스키마 파일명은 사용 중인 데이터베이스 커넥션에 대응됩니다. 이제 데이터베이스를 마이그레이션하려고 할 때, 아직 실행된 마이그레이션이 하나도 없다면 Laravel은 먼저 사용 중인 데이터베이스 커넥션의 스키마 파일에 있는 SQL 문을 실행합니다. 스키마 파일의 SQL 문을 모두 실행한 후에는, 스키마 덤프에 포함되지 않은 나머지 마이그레이션들을 실행합니다.

애플리케이션의 테스트가 로컬 개발 중 평소 사용하는 것과 다른 데이터베이스 커넥션을 사용한다면, 해당 데이터베이스 커넥션을 사용해서도 스키마 파일을 덤프해두어야 테스트에서 데이터베이스를 올바르게 구성할 수 있습니다. 보통은 로컬 개발용 데이터베이스 커넥션을 덤프한 다음, 별도로 테스트용 데이터베이스 커넥션도 덤프하는 순서로 진행하면 좋습니다.

php artisan schema:dumpphp artisan schema:dump --database=testing --prune

데이터베이스 스키마 파일은 소스 컨트롤에 커밋해두어야 팀의 다른 새로운 개발자들도 애플리케이션의 초기 데이터베이스 구조를 빠르게 만들어볼 수 있습니다.

WARNING

마이그레이션 스쿼싱 기능은 MariaDB, MySQL, PostgreSQL, SQLite에서만 사용할 수 있으며, 데이터베이스의 커맨드 라인 클라이언트를 사용합니다.

마이그레이션

소개

마이그레이션은 데이터베이스에 대한 버전 관리 시스템이라고 생각하면 이해하기 쉽습니다. 팀원들과 애플리케이션의 데이터베이스 스키마 정의를 공유하고, 함께 관리할 수 있게 해줍니다.

혹시 동료가 소스 컨트롤에서 변경 사항을 받아온 뒤, "로컬 데이터베이스에 컬럼 하나 수동으로 추가해줘"라고 부탁했던 경험이 있나요? 마이그레이션은 바로 이런 문제를 해결하기 위해 존재합니다.

Laravel의 Schema 파사드는 Laravel이 지원하는 모든 데이터베이스 시스템에서 동일한 방식으로 테이블을 생성하고 조작할 수 있는 기능을 제공합니다. 일반적으로 마이그레이션 코드에서는 이 파사드를 사용해 데이터베이스 테이블과 컬럼을 생성하거나 수정합니다.

NOTE

마이그레이션은 데이터베이스 종류에 상관없이 동일한 코드로 스키마를 다룰 수 있게 해주는 것이 핵심입니다. 예를 들어 로컬 개발 환경에서는 MySQL을, 운영 환경에서는 다른 DBMS를 사용하더라도 마이그레이션 코드를 그대로 재사용할 수 있습니다.

마이그레이션

마이그레이션 생성하기

make:migration Artisan 명령어를 사용하면 데이터베이스 마이그레이션 파일을 생성할 수 있습니다. 새로 생성된 마이그레이션 파일은 database/migrations 디렉터리에 저장됩니다. 각 마이그레이션 파일명에는 타임스탬프가 포함되어 있어서, Laravel이 마이그레이션을 실행할 순서를 파악하는 데 사용됩니다.

php artisan make:migration create_flights_table

Laravel은 마이그레이션 이름을 분석해서 테이블 이름과 새 테이블을 생성하는 마이그레이션인지 여부를 추측합니다. 마이그레이션 이름에서 테이블 이름을 알아낼 수 있는 경우, Laravel은 생성되는 마이그레이션 파일에 해당 테이블 이름을 미리 채워 넣어 줍니다. 만약 이름만으로 유추가 어렵다면, 마이그레이션 파일을 직접 열어서 테이블 이름을 수동으로 지정하면 됩니다.

생성되는 마이그레이션 파일의 경로를 직접 지정하고 싶다면 make:migration 명령어 실행 시 --path 옵션을 사용할 수 있습니다. 이때 지정하는 경로는 애플리케이션의 기본 경로(base path)를 기준으로 한 상대 경로여야 합니다.

NOTE

마이그레이션 스텁(stub)은 스텁 퍼블리싱 기능을 사용해 원하는 형태로 커스터마이징할 수 있습니다.

마이그레이션 압축(Squashing)하기

애플리케이션을 개발하다 보면 시간이 지날수록 마이그레이션 파일이 점점 늘어나게 됩니다. 이렇게 되면 database/migrations 디렉터리에 수백 개에 달하는 마이그레이션 파일이 쌓여서 관리가 부담스러워질 수 있습니다. 이런 경우에는 지금까지의 마이그레이션들을 하나의 SQL 파일로 "압축(squash)"할 수 있습니다. schema:dump 명령어를 실행해 보세요.

php artisan schema:dump <h1 id="forcing-migrations-to-run-in-production">현재 데이터베이스 스키마를 덤프하고 기존 마이그레이션 파일들을 모두 정리(삭제)합니다...</h1> php artisan schema:dump --prune

이 명령어를 실행하면 Laravel은 애플리케이션의 database/schema 디렉터리에 "스키마" 파일을 생성합니다. 이 스키마 파일의 이름은 사용 중인 데이터베이스 커넥션 이름을 따르게 됩니다. 이후 마이그레이션을 실행할 때, 아직 실행된 마이그레이션이 하나도 없는 상태라면 Laravel은 먼저 현재 사용 중인 데이터베이스 커넥션에 해당하는 스키마 파일의 SQL 구문을 실행합니다. 스키마 파일의 SQL 구문을 모두 실행한 뒤에는, 스키마 덤프에 포함되지 않았던 나머지 마이그레이션들을 순서대로 실행합니다.

만약 애플리케이션의 테스트 코드가 로컬 개발 환경에서 평소에 사용하는 것과는 다른 데이터베이스 커넥션을 사용한다면, 해당 커넥션 기준으로도 스키마 파일을 별도로 덤프해 두어야 테스트 실행 시 데이터베이스를 정상적으로 구성할 수 있습니다. 보통은 평소 사용하는 로컬 개발용 데이터베이스 커넥션을 먼저 덤프한 뒤, 다음과 같이 테스트용 커넥션도 함께 덤프해 두면 됩니다.

php artisan schema:dumpphp artisan schema:dump --database=testing --prune

데이터베이스 스키마 파일은 반드시 소스 컨트롤(Git 등)에 커밋해 두어야 합니다. 그래야 팀에 새로 합류한 개발자도 애플리케이션의 초기 데이터베이스 구조를 빠르게 구성할 수 있습니다.

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 { // ... }

마이그레이션 건너뛰기

아직 활성화되지 않은 기능을 위한 마이그레이션이라서, 지금 당장은 실행하고 싶지 않은 경우가 있을 수 있습니다. 이럴 때는 마이그레이션에 shouldRun 메서드를 정의하면 됩니다. shouldRun 메서드가 false를 반환하면 해당 마이그레이션은 실행되지 않고 건너뜁니다.

use App\Models\Flight; use Laravel\Pennant\Feature; /** * 이 마이그레이션을 실행해야 하는지 결정합니다. */ public function shouldRun(): bool { return Feature::active(Flight::class); }

NOTE

예를 들어 항공권 예약 서비스에 새로운 좌석 등급 기능을 추가하는 중이고, 아직 Laravel Pennant 기능 플래그로 이 기능이 비활성화되어 있다면, 관련 테이블을 생성하는 마이그레이션에 shouldRun을 사용해 기능이 켜지기 전까지는 실행을 미룰 수 있습니다.

마이그레이션 실행하기

아직 실행되지 않은 마이그레이션을 모두 실행하려면 migrate Artisan 명령어를 사용합니다.

php artisan migrate

지금까지 어떤 마이그레이션이 실행됐고 어떤 것이 아직 대기 중인지 확인하고 싶다면 migrate:status 명령어를 사용하면 됩니다.

php artisan migrate:status

migrate 명령어에 --step 옵션을 추가하면 각 마이그레이션을 별도의 배치(batch)로 나누어 실행합니다. 이렇게 하면 이후에 migrate:rollback 명령어로 특정 마이그레이션만 개별적으로 롤백할 수 있습니다.

php artisan migrate --step

마이그레이션을 실제로 실행하지 않고 어떤 SQL 문이 실행될지 미리 확인하고 싶다면, migrate 명령어에 --pretend 플래그를 추가하세요.

php artisan migrate --pretend

마이그레이션 실행을 하나로 제한하기

애플리케이션을 여러 서버에 배포하면서 배포 과정 중 마이그레이션을 실행하는 경우, 두 대 이상의 서버가 동시에 같은 데이터베이스를 마이그레이션하려고 시도하는 상황은 피해야 합니다. 이런 문제를 막기 위해 migrate 명령어 실행 시 isolated 옵션을 사용할 수 있습니다.

isolated 옵션을 지정하면, Laravel은 마이그레이션을 실행하기 전에 애플리케이션의 캐시 드라이버를 이용해 원자적(atomic) 락을 획득합니다. 이 락이 걸려 있는 동안 다른 서버에서 migrate 명령어를 실행하려고 하면 실제로는 마이그레이션이 실행되지 않지만, 명령어 자체는 성공 종료 코드를 반환합니다.

php artisan migrate --isolated

WARNING

이 기능을 사용하려면 애플리케이션의 기본 캐시 드라이버가 memcached, redis, dynamodb, database, file, array 중 하나여야 합니다. 또한 모든 서버가 동일한 중앙 캐시 서버와 통신하고 있어야 합니다.

프로덕션 환경에서 강제로 마이그레이션 실행하기

일부 마이그레이션 작업은 데이터를 손실시킬 수 있는 파괴적인(destructive) 작업입니다. 프로덕션 데이터베이스에서 실수로 이런 명령어를 실행하는 것을 방지하기 위해, 명령어를 실행하기 전에 확인 메시지가 표시됩니다. 확인 절차 없이 강제로 실행하려면 --force 플래그를 사용하세요.

php artisan migrate --force

마이그레이션 롤백하기

가장 최근에 실행한 마이그레이션 작업을 롤백하려면 rollback Artisan 명령어를 사용합니다. 이 명령어는 마지막 "배치(batch)" 단위로 롤백을 수행하며, 하나의 배치에는 여러 개의 마이그레이션 파일이 포함될 수 있습니다.

php artisan migrate:rollback

rollback 명령어에 step 옵션을 지정하면 롤백할 마이그레이션 개수를 제한할 수 있습니다. 예를 들어 아래 명령어는 마지막 5개의 마이그레이션을 롤백합니다.

php artisan migrate:rollback --step=5

rollback 명령어에 batch 옵션을 지정하면 특정 "배치"에 속한 마이그레이션만 롤백할 수 있습니다. 이때 batch 값은 애플리케이션의 migrations 테이블에 저장된 배치 값과 일치해야 합니다. 예를 들어 아래 명령어는 배치 3에 속한 모든 마이그레이션을 롤백합니다.

php artisan migrate:rollback --batch=3

마이그레이션을 실제로 롤백하지 않고 어떤 SQL 문이 실행될지 미리 확인하고 싶다면, migrate:rollback 명령어에 --pretend 플래그를 추가하세요.

php artisan migrate:rollback --pretend

migrate:reset 명령어는 애플리케이션의 모든 마이그레이션을 롤백합니다.

php artisan migrate:reset

한 번의 명령어로 롤백 후 재실행하기

migrate:refresh 명령어는 모든 마이그레이션을 롤백한 다음 migrate 명령어를 다시 실행합니다. 즉, 이 명령어 하나로 데이터베이스 전체를 처음부터 다시 생성하는 효과를 얻을 수 있습니다.

php artisan migrate:refresh <h1 id="updating-tables">데이터베이스를 초기화하고 시더도 함께 실행하기...</h1> php artisan migrate:refresh --seed

refresh 명령어에 step 옵션을 지정하면 롤백 및 재실행할 마이그레이션 개수를 제한할 수 있습니다. 예를 들어 아래 명령어는 마지막 5개의 마이그레이션만 롤백한 뒤 다시 실행합니다.

php artisan migrate:refresh --step=5

모든 테이블을 삭제하고 마이그레이션 실행하기

migrate:fresh 명령어는 데이터베이스의 모든 테이블을 삭제한 다음 migrate 명령어를 실행합니다.

php artisan migrate:freshphp artisan migrate:fresh --seed

기본적으로 migrate:fresh 명령어는 기본 데이터베이스 연결에 속한 테이블만 삭제합니다. 다른 데이터베이스 연결을 대상으로 하려면 --database 옵션을 사용해 연결 이름을 지정할 수 있습니다. 이때 지정하는 연결 이름은 애플리케이션의 database 설정 파일에 정의된 연결 이름과 일치해야 합니다.

php artisan migrate:fresh --database=admin

WARNING

migrate:fresh 명령어는 테이블 접두사(prefix)와 관계없이 데이터베이스의 모든 테이블을 삭제합니다. 다른 애플리케이션과 공유하는 데이터베이스에서 작업할 때는 이 명령어를 특히 주의해서 사용해야 합니다.

마이그레이션

테이블

테이블 생성하기

새 데이터베이스 테이블을 생성할 때는 Schema 파사드의 create 메서드를 사용합니다. 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을 사용할 때는 charsetcollation 속성으로 생성할 테이블의 문자셋과 콜레이션을 지정할 수 있습니다:

Schema::create('users', function (Blueprint $table) { $table->charset('utf8mb4'); $table->collation('utf8mb4_unicode_ci'); // ... });

temporary 메서드를 사용하면 테이블을 "임시(temporary)" 테이블로 지정할 수 있습니다. 임시 테이블은 현재 커넥션의 데이터베이스 세션에서만 보이며, 커넥션이 종료되면 자동으로 삭제됩니다:

Schema::create('calculations', function (Blueprint $table) { $table->temporary(); // ... });

데이터베이스 테이블에 "코멘트(설명)"를 추가하고 싶다면 테이블 인스턴스에서 comment 메서드를 호출하면 됩니다. 테이블 코멘트는 현재 MariaDB, MySQL, PostgreSQL에서만 지원됩니다:

Schema::create('calculations', function (Blueprint $table) { $table->comment('Business calculations'); // ... });

테이블 수정하기

기존 테이블을 수정할 때는 Schema 파사드의 table 메서드를 사용합니다. create 메서드와 마찬가지로 table 메서드도 테이블 이름과, 컬럼이나 인덱스를 추가할 때 사용할 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이 자동으로 생성하는 규칙 기반 이름이 아니라 명시적인 이름으로 지정되어 있는지 반드시 확인해야 합니다. 그렇지 않으면 외래 키 제약 조건의 이름이 변경 전 테이블 이름을 그대로 참조하게 되어 문제가 발생할 수 있습니다.

NOTE

예를 들어 posts 테이블을 articles로 이름을 변경했는데, 외래 키 제약 조건 이름이 posts_user_id_foreign처럼 자동 생성된 이름이라면, 테이블 이름만 바뀌고 제약 조건 이름은 그대로 남아 있어 나중에 마이그레이션을 관리할 때 혼란을 줄 수 있습니다. 이런 상황을 피하려면 마이그레이션 작성 시 foreign() 정의에 ->name('원하는_이름')을 명시적으로 지정하는 것이 좋습니다.

컬럼

컬럼 생성하기

Schema 파사드의 table 메서드를 사용하면 기존 테이블을 수정할 수 있습니다. create 메서드와 마찬가지로 table 메서드도 테이블 이름과, 컬럼을 추가할 때 사용할 Illuminate\Database\Schema\Blueprint 인스턴스를 전달받는 클로저 두 가지 인자를 받습니다.

use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; Schema::table('users', function (Blueprint $table) { $table->integer('votes'); });

사용 가능한 컬럼 타입

스키마 빌더의 블루프린트는 데이터베이스 테이블에 추가할 수 있는 다양한 종류의 컬럼에 대응하는 여러 메서드를 제공합니다. 사용 가능한 메서드는 아래 표에 정리되어 있습니다.

불리언 타입

문자열 & 텍스트 타입

숫자 타입

날짜 & 시간 타입

바이너리 타입

객체 & JSON 타입

UUID & ULID 타입

공간(Spatial) 타입

연관관계(Relationship) 타입

특수 타입

`bigIncrements()` {.collection-method .first-collection-method}

bigIncrements 메서드는 자동 증가하는 UNSIGNED BIGINT(기본 키) 컬럼을 생성합니다.

$table->bigIncrements('id');

`bigInteger()` {.collection-method}

bigInteger 메서드는 BIGINT에 해당하는 컬럼을 생성합니다.

$table->bigInteger('votes');

`binary()` {.collection-method}

binary 메서드는 BLOB에 해당하는 컬럼을 생성합니다.

$table->binary('photo');

MySQL, MariaDB, SQL Server를 사용하는 경우 lengthfixed 인자를 전달하여 VARBINARY 또는 BINARY에 해당하는 컬럼을 생성할 수 있습니다.

$table->binary('data', length: 16); // VARBINARY(16) $table->binary('data', length: 16, fixed: true); // BINARY(16)

`boolean()` {.collection-method}

boolean 메서드는 BOOLEAN에 해당하는 컬럼을 생성합니다.

$table->boolean('confirmed');

`char()` {.collection-method}

char 메서드는 지정한 길이의 CHAR에 해당하는 컬럼을 생성합니다.

$table->char('name', length: 100);

`dateTimeTz()` {.collection-method}

dateTimeTz 메서드는 타임존을 포함한 DATETIME에 해당하는 컬럼을 생성하며, 소수 초 정밀도를 선택적으로 지정할 수 있습니다.

$table->dateTimeTz('created_at', precision: 0);

`dateTime()` {.collection-method}

dateTime 메서드는 DATETIME에 해당하는 컬럼을 생성하며, 소수 초 정밀도를 선택적으로 지정할 수 있습니다.

$table->dateTime('created_at', precision: 0);

`date()` {.collection-method}

date 메서드는 DATE에 해당하는 컬럼을 생성합니다.

$table->date('created_at');

`decimal()` {.collection-method}

decimal 메서드는 전체 자릿수(precision)와 소수점 자릿수(scale)를 지정하여 DECIMAL에 해당하는 컬럼을 생성합니다.

$table->decimal('amount', total: 8, places: 2);

`double()` {.collection-method}

double 메서드는 DOUBLE에 해당하는 컬럼을 생성합니다.

$table->double('amount');

`enum()` {.collection-method}

enum 메서드는 지정한 유효 값 목록을 갖는 ENUM에 해당하는 컬럼을 생성합니다.

$table->enum('difficulty', ['easy', 'hard']);

허용 값 배열을 직접 작성하는 대신 Enum::cases() 메서드를 사용할 수도 있습니다.

use App\Enums\Difficulty; $table->enum('difficulty', Difficulty::cases());

`float()` {.collection-method}

float 메서드는 지정한 정밀도를 갖는 FLOAT에 해당하는 컬럼을 생성합니다.

$table->float('amount', precision: 53);

`foreignId()` {.collection-method}

foreignId 메서드는 UNSIGNED BIGINT에 해당하는 컬럼을 생성합니다.

$table->foreignId('user_id');

`foreignIdFor()` {.collection-method}

foreignIdFor 메서드는 지정한 모델 클래스에 대응하는 {column}_id 컬럼을 추가합니다. 컬럼 타입은 모델의 키 타입에 따라 UNSIGNED BIGINT, CHAR(36), CHAR(26) 중 하나가 됩니다.

$table->foreignIdFor(User::class);

`foreignUlid()` {.collection-method}

foreignUlid 메서드는 ULID에 해당하는 컬럼을 생성합니다.

$table->foreignUlid('user_id');

`foreignUuid()` {.collection-method}

foreignUuid 메서드는 UUID에 해당하는 컬럼을 생성합니다.

$table->foreignUuid('user_id');

`foreignUuidFor()` {.collection-method}

foreignUuidFor 메서드는 지정한 모델 클래스에 대응하는 {column}_id UUID 컬럼을 추가합니다.

$table->foreignUuidFor(User::class);

`geography()` {.collection-method}

geography 메서드는 지정한 공간(spatial) 타입과 SRID(공간 참조 식별자)를 갖는 GEOGRAPHY에 해당하는 컬럼을 생성합니다.

$table->geography('coordinates', subtype: 'point', srid: 4326);

NOTE

공간 타입 지원 여부는 데이터베이스 드라이버에 따라 다릅니다. 사용 중인 데이터베이스의 문서를 참고하세요. PostgreSQL을 사용하는 경우 geography 메서드를 사용하기 전에 PostGIS 확장을 설치해야 합니다.

`geometry()` {.collection-method}

geometry 메서드는 지정한 공간 타입과 SRID(공간 참조 식별자)를 갖는 GEOMETRY에 해당하는 컬럼을 생성합니다.

$table->geometry('positions', subtype: 'point', srid: 0);

NOTE

공간 타입 지원 여부는 데이터베이스 드라이버에 따라 다릅니다. 사용 중인 데이터베이스의 문서를 참고하세요. PostgreSQL을 사용하는 경우 geometry 메서드를 사용하기 전에 PostGIS 확장을 설치해야 합니다.

`id()` {.collection-method}

id 메서드는 bigIncrements 메서드의 별칭(alias)입니다. 기본적으로 id라는 이름의 컬럼을 생성하지만, 다른 이름을 사용하고 싶다면 컬럼 이름을 인자로 전달할 수 있습니다.

$table->id();

`increments()` {.collection-method}

increments 메서드는 자동 증가하는 UNSIGNED INTEGER에 해당하는 기본 키 컬럼을 생성합니다.

$table->increments('id');

`integer()` {.collection-method}

integer 메서드는 INTEGER에 해당하는 컬럼을 생성합니다.

$table->integer('votes');

`ipAddress()` {.collection-method}

ipAddress 메서드는 VARCHAR에 해당하는 컬럼을 생성합니다.

$table->ipAddress('visitor');

PostgreSQL을 사용할 경우 INET 컬럼이 생성됩니다.

`json()` {.collection-method}

json 메서드는 JSON에 해당하는 컬럼을 생성합니다.

$table->json('options');

SQLite를 사용할 경우 TEXT 컬럼이 생성됩니다.

`jsonb()` {.collection-method}

jsonb 메서드는 JSONB에 해당하는 컬럼을 생성합니다.

$table->jsonb('options');

SQLite를 사용할 경우 TEXT 컬럼이 생성됩니다.

`longText()` {.collection-method}

longText 메서드는 LONGTEXT에 해당하는 컬럼을 생성합니다.

$table->longText('description');

MySQL이나 MariaDB를 사용하는 경우, binary 문자 집합(character set)을 적용하면 LONGBLOB에 해당하는 컬럼을 만들 수 있습니다.

$table->longText('data')->charset('binary'); // LONGBLOB

`macAddress()` {.collection-method}

macAddress 메서드는 MAC 주소를 저장하기 위한 컬럼을 생성합니다. PostgreSQL과 같은 일부 데이터베이스는 이 데이터 타입에 특화된 전용 컬럼 타입을 제공합니다. 그 외의 데이터베이스는 문자열에 해당하는 컬럼을 사용합니다.

$table->macAddress('device');

`mediumIncrements()` {.collection-method}

mediumIncrements 메서드는 자동 증가하는 UNSIGNED MEDIUMINT에 해당하는 기본 키 컬럼을 생성합니다.

$table->mediumIncrements('id');

`mediumInteger()` {.collection-method}

mediumInteger 메서드는 MEDIUMINT에 해당하는 컬럼을 생성합니다.

$table->mediumInteger('votes');

`mediumText()` {.collection-method}

mediumText 메서드는 MEDIUMTEXT에 해당하는 컬럼을 생성합니다.

$table->mediumText('description');

MySQL이나 MariaDB를 사용하는 경우, binary 문자 집합을 적용하면 MEDIUMBLOB에 해당하는 컬럼을 만들 수 있습니다.

$table->mediumText('data')->charset('binary'); // MEDIUMBLOB

`morphs()` {.collection-method}

morphs 메서드는 {column}_type이라는 VARCHAR 컬럼과 {column}_id 컬럼을 한 번에 추가해주는 편의 메서드입니다. {column}_id 컬럼의 타입은 모델의 키 타입에 따라 UNSIGNED BIGINT, CHAR(36), CHAR(26) 중 하나가 됩니다.

이 메서드는 Eloquent 폴리모픽(polymorphic) 연관관계에 필요한 컬럼을 정의할 때 사용합니다. 아래 예시에서는 taggable_typetaggable_id 컬럼이 생성됩니다.

$table->morphs('taggable');

`nullableMorphs()` {.collection-method}

morphs 메서드와 유사하지만, 생성되는 컬럼이 "nullable"(null 허용)이라는 차이가 있습니다.

$table->nullableMorphs('taggable');

`nullableUlidMorphs()` {.collection-method}

ulidMorphs 메서드와 유사하지만, 생성되는 컬럼이 "nullable"이라는 차이가 있습니다.

$table->nullableUlidMorphs('taggable');

`nullableUuidMorphs()` {.collection-method}

uuidMorphs 메서드와 유사하지만, 생성되는 컬럼이 "nullable"이라는 차이가 있습니다.

$table->nullableUuidMorphs('taggable');

`rememberToken()` {.collection-method}

rememberToken 메서드는 현재 사용 중인 "remember me" 인증 토큰을 저장하기 위한, null을 허용하는 VARCHAR(100)에 해당하는 컬럼을 생성합니다.

$table->rememberToken();

`set()` {.collection-method}

set 메서드는 지정한 유효 값 목록을 갖는 SET에 해당하는 컬럼을 생성합니다.

$table->set('flavors', ['strawberry', 'vanilla']);

`smallIncrements()` {.collection-method}

smallIncrements 메서드는 자동 증가하는 UNSIGNED SMALLINT에 해당하는 기본 키 컬럼을 생성합니다.

$table->smallIncrements('id');

`smallInteger()` {.collection-method}

smallInteger 메서드는 SMALLINT에 해당하는 컬럼을 생성합니다.

$table->smallInteger('votes');

`softDeletesTz()` {.collection-method}

softDeletesTz 메서드는 타임존을 포함한, null을 허용하는 deleted_at TIMESTAMP에 해당하는 컬럼을 추가하며 소수 초 정밀도를 선택적으로 지정할 수 있습니다. 이 컬럼은 Eloquent의 "소프트 삭제(soft delete)" 기능에 필요한 deleted_at 타임스탬프를 저장하는 데 사용됩니다.

$table->softDeletesTz('deleted_at', precision: 0);

`softDeletes()` {.collection-method}

softDeletes 메서드는 null을 허용하는 deleted_at TIMESTAMP에 해당하는 컬럼을 추가하며 소수 초 정밀도를 선택적으로 지정할 수 있습니다. 이 컬럼은 Eloquent의 "소프트 삭제" 기능에 필요한 deleted_at 타임스탬프를 저장하는 데 사용됩니다.

$table->softDeletes('deleted_at', precision: 0);

`string()` {.collection-method}

string 메서드는 지정한 길이의 VARCHAR에 해당하는 컬럼을 생성합니다.

$table->string('name', length: 100);

`text()` {.collection-method}

text 메서드는 TEXT에 해당하는 컬럼을 생성합니다.

$table->text('description');

MySQL이나 MariaDB를 사용하는 경우, binary 문자 집합을 적용하면 BLOB에 해당하는 컬럼을 만들 수 있습니다.

$table->text('data')->charset('binary'); // BLOB

`timeTz()` {.collection-method}

timeTz 메서드는 타임존을 포함한 TIME에 해당하는 컬럼을 생성하며 소수 초 정밀도를 선택적으로 지정할 수 있습니다.

$table->timeTz('sunrise', precision: 0);

`time()` {.collection-method}

time 메서드는 TIME에 해당하는 컬럼을 생성하며 소수 초 정밀도를 선택적으로 지정할 수 있습니다.

$table->time('sunrise', precision: 0);

`timestampTz()` {.collection-method}

timestampTz 메서드는 타임존을 포함한 TIMESTAMP에 해당하는 컬럼을 생성하며 소수 초 정밀도를 선택적으로 지정할 수 있습니다.

$table->timestampTz('added_at', precision: 0);

`timestamp()` {.collection-method}

timestamp 메서드는 TIMESTAMP에 해당하는 컬럼을 생성하며 소수 초 정밀도를 선택적으로 지정할 수 있습니다.

$table->timestamp('added_at', precision: 0);

`timestampsTz()` {.collection-method}

timestampsTz 메서드는 타임존을 포함한 created_at, updated_at TIMESTAMP에 해당하는 컬럼들을 생성하며 소수 초 정밀도를 선택적으로 지정할 수 있습니다.

$table->timestampsTz(precision: 0);

`timestamps()` {.collection-method}

timestamps 메서드는 created_at, updated_at TIMESTAMP에 해당하는 컬럼들을 생성하며 소수 초 정밀도를 선택적으로 지정할 수 있습니다.

$table->timestamps(precision: 0);

`tinyIncrements()` {.collection-method}

tinyIncrements 메서드는 자동 증가하는 UNSIGNED TINYINT에 해당하는 기본 키 컬럼을 생성합니다.

$table->tinyIncrements('id');

`tinyInteger()` {.collection-method}

tinyInteger 메서드는 TINYINT에 해당하는 컬럼을 생성합니다.

$table->tinyInteger('votes');

`tinyText()` {.collection-method}

tinyText 메서드는 TINYTEXT에 해당하는 컬럼을 생성합니다.

$table->tinyText('notes');

MySQL이나 MariaDB를 사용하는 경우, binary 문자 집합을 적용하면 TINYBLOB에 해당하는 컬럼을 만들 수 있습니다.

$table->tinyText('data')->charset('binary'); // TINYBLOB

`unsignedBigInteger()` {.collection-method}

unsignedBigInteger 메서드는 UNSIGNED BIGINT에 해당하는 컬럼을 생성합니다.

$table->unsignedBigInteger('votes');

`unsignedInteger()` {.collection-method}

unsignedInteger 메서드는 UNSIGNED INTEGER에 해당하는 컬럼을 생성합니다.

$table->unsignedInteger('votes');

`unsignedMediumInteger()` {.collection-method}

unsignedMediumInteger 메서드는 UNSIGNED MEDIUMINT에 해당하는 컬럼을 생성합니다.

$table->unsignedMediumInteger('votes');

`unsignedSmallInteger()` {.collection-method}

unsignedSmallInteger 메서드는 UNSIGNED SMALLINT에 해당하는 컬럼을 생성합니다.

$table->unsignedSmallInteger('votes');

`unsignedTinyInteger()` {.collection-method}

unsignedTinyInteger 메서드는 UNSIGNED TINYINT에 해당하는 컬럼을 생성합니다.

$table->unsignedTinyInteger('votes');

`ulidMorphs()` {.collection-method}

ulidMorphs 메서드는 {column}_type이라는 VARCHAR 컬럼과 {column}_id라는 CHAR(26) 컬럼을 함께 추가해주는 편의 메서드입니다.

이 메서드는 ULID 식별자를 사용하는 Eloquent 폴리모픽 연관관계에 필요한 컬럼을 정의할 때 사용합니다. 아래 예시에서는 taggable_typetaggable_id 컬럼이 생성됩니다.

$table->ulidMorphs('taggable');

`uuidMorphs()` {.collection-method}

uuidMorphs 메서드는 {column}_type이라는 VARCHAR 컬럼과 {column}_id라는 CHAR(36) 컬럼을 함께 추가해주는 편의 메서드입니다.

이 메서드는 UUID 식별자를 사용하는 폴리모픽 Eloquent 연관관계에 필요한 컬럼을 정의할 때 사용합니다. 아래 예시에서는 taggable_typetaggable_id 컬럼이 생성됩니다.

$table->uuidMorphs('taggable');

`ulid()` {.collection-method}

ulid 메서드는 ULID에 해당하는 컬럼을 생성합니다.

$table->ulid('id');

`uuid()` {.collection-method}

uuid 메서드는 UUID에 해당하는 컬럼을 생성합니다.

$table->uuid('id');

`vector()` {.collection-method}

vector 메서드는 vector에 해당하는 컬럼을 생성합니다.

$table->vector('embedding', dimensions: 1536);

벡터 컬럼은 pgvector 확장을 사용하는 PostgreSQL 연결과 MariaDB 11.7 이상에서 지원됩니다. PostgreSQL을 사용하는 경우, vector 컬럼을 생성하기 전에 pgvector가 로드되어 있어야 합니다.

Schema::ensureVectorExtensionExists();

벡터 유사도 쿼리의 속도를 높이려면 해당 컬럼에 벡터 인덱스를 추가할 수 있습니다. vector 컬럼에 index 메서드를 호출하면 코사인 거리(cosine distance)를 사용하는 벡터 인덱스가 생성됩니다.

$table->vector('embedding', dimensions: 1536)->index();

`year()` {.collection-method}

year 메서드는 YEAR에 해당하는 컬럼을 생성합니다.

$table->year('birth_year');

컬럼 수정자(Modifier)

위에서 살펴본 컬럼 타입들 외에도, 테이블에 컬럼을 추가할 때 사용할 수 있는 여러 컬럼 "수정자(modifier)"가 있습니다. 예를 들어 컬럼을 "nullable"(null 허용)로 만들려면 nullable 메서드를 사용하면 됩니다.

use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; Schema::table('users', function (Blueprint $table) { $table->string('email')->nullable(); });

다음 표는 사용 가능한 모든 컬럼 수정자를 정리한 것입니다. 이 목록에는 인덱스 수정자는 포함되어 있지 않습니다.

수정자설명
->after('column')특정 컬럼 "다음"에 컬럼을 배치합니다 (MariaDB / MySQL).
->autoIncrement()INTEGER 컬럼을 자동 증가(기본 키)로 설정합니다.
->charset('utf8mb4')컬럼의 문자 집합을 지정합니다 (MariaDB / MySQL).
->collation('utf8mb4_unicode_ci')컬럼의 콜레이션(collation)을 지정합니다.
->comment('my comment')컬럼에 주석을 추가합니다 (MariaDB / MySQL / PostgreSQL).
->default($value)컬럼의 "기본값"을 지정합니다.
->first()테이블의 "맨 앞"에 컬럼을 배치합니다 (MariaDB / MySQL).
->from($integer)자동 증가 필드의 시작 값을 지정합니다 (MariaDB / MySQL / PostgreSQL).
->instant()"instant" 연산을 사용해 컬럼을 추가하거나 수정합니다 (MySQL).
->invisible()SELECT * 쿼리에서 컬럼을 "보이지 않게" 만듭니다 (MariaDB / MySQL).
->lock($mode)컬럼 작업에 대한 잠금(lock) 모드를 지정합니다 (MySQL).
->nullable($value = true)컬럼에 NULL 값을 허용합니다.
->storedAs($expression)저장형(stored) 생성 컬럼을 만듭니다 (MariaDB / MySQL / PostgreSQL / SQLite).
->unsigned()INTEGER 컬럼을 UNSIGNED로 설정합니다 (MariaDB / MySQL).
->using($expression)컬럼 타입을 변경할 때 사용할 캐스팅 표현식을 지정합니다 (PostgreSQL).
->useCurrent()TIMESTAMP 컬럼의 기본값을 CURRENT_TIMESTAMP로 설정합니다.
->useCurrentOnUpdate()레코드가 갱신될 때 TIMESTAMP 컬럼이 CURRENT_TIMESTAMP를 사용하도록 설정합니다 (MariaDB / MySQL).
->virtualAs($expression)가상(virtual) 생성 컬럼을 만듭니다 (MariaDB / MySQL / SQLite).
->generatedAs($expression)지정한 시퀀스 옵션을 갖는 identity 컬럼을 만듭니다 (PostgreSQL).
->always()identity 컬럼에서 시퀀스 값이 입력값보다 우선하도록 지정합니다 (PostgreSQL).

기본값 표현식(Default Expressions)

default 수정자는 값 또는 Illuminate\Database\Query\Expression 인스턴스를 받을 수 있습니다. Expression 인스턴스를 사용하면 Laravel이 값을 따옴표로 감싸지 않으므로, 데이터베이스 전용 함수를 사용할 수 있습니다. 이 방식이 특히 유용한 경우는 JSON 컬럼에 기본값을 지정해야 할 때입니다.

<?php use Illuminate\Support\Facades\Schema; use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Query\Expression; use Illuminate\Database\Migrations\Migration; return new class extends Migration { /** * 마이그레이션을 실행합니다. */ public function up(): void { Schema::create('flights', function (Blueprint $table) { $table->id(); $table->json('movies')->default(new Expression('(JSON_ARRAY())')); $table->timestamps(); }); } };

WARNING

기본값 표현식 지원 여부는 사용하는 데이터베이스 드라이버, 데이터베이스 버전, 필드 타입에 따라 달라집니다. 반드시 사용 중인 데이터베이스의 문서를 참고하세요.

컬럼 순서

MariaDB나 MySQL 데이터베이스를 사용할 때는 after 메서드를 사용해 스키마 내 기존 컬럼 다음에 새 컬럼을 추가할 수 있습니다.

$table->after('password', function (Blueprint $table) { $table->string('address_line1'); $table->string('address_line2'); $table->string('city'); });

Instant 컬럼 작업

MySQL을 사용할 때는 컬럼 정의에 instant 수정자를 체이닝하여 해당 컬럼을 MySQL의 "instant" 알고리즘으로 추가하거나 수정하도록 지정할 수 있습니다. 이 알고리즘을 사용하면 테이블 크기와 무관하게 전체 테이블을 재구성(rebuild)하지 않고도 특정 스키마 변경을 거의 즉시 수행할 수 있습니다.

$table->string('name')->nullable()->instant();

Instant 방식의 컬럼 추가는 테이블의 맨 끝에만 컬럼을 붙일 수 있으므로, instant 수정자는 afterfirst 수정자와 함께 사용할 수 없습니다. 또한 이 알고리즘은 모든 컬럼 타입이나 작업을 지원하지는 않습니다. 요청한 작업이 호환되지 않으면 MySQL이 오류를 발생시킵니다.

어떤 작업이 instant 컬럼 수정과 호환되는지는 MySQL 문서를 참고하세요.

DDL 잠금(Locking)

MySQL을 사용할 때는 컬럼, 인덱스, 외래 키 정의에 lock 수정자를 체이닝하여 스키마 작업 중 테이블 잠금 방식을 제어할 수 있습니다. MySQL은 여러 잠금 모드를 지원합니다: none은 동시 읽기·쓰기를 모두 허용하고, shared는 동시 읽기는 허용하지만 쓰기는 막으며, exclusive는 모든 동시 접근을 막고, default는 MySQL이 가장 적절한 모드를 자동으로 선택하게 합니다.

$table->string('name')->lock('none'); $table->index('email')->lock('shared');

요청한 잠금 모드가 해당 작업과 호환되지 않으면 MySQL이 오류를 발생시킵니다. lock 수정자는 instant 수정자와 함께 사용하여 스키마 변경을 더욱 최적화할 수도 있습니다.

$table->string('name')->instant()->lock('none');

컬럼 수정하기

change 메서드를 사용하면 기존 컬럼의 타입과 속성을 수정할 수 있습니다. 예를 들어 string 컬럼의 길이를 늘리고 싶을 때가 있을 것입니다. change 메서드가 실제로 동작하는 모습을 보기 위해, name 컬럼의 길이를 25에서 50으로 늘려보겠습니다. 이를 위해서는 원하는 컬럼의 새로운 상태를 정의한 다음 change 메서드를 호출하면 됩니다.

Schema::table('users', function (Blueprint $table) { $table->string('name', 50)->change(); });

컬럼을 수정할 때는 유지하고자 하는 모든 수정자를 컬럼 정의에 명시적으로 포함해야 합니다. 누락된 속성은 모두 제거됩니다. 예를 들어 unsigned, default, comment 속성을 유지하려면, 컬럼을 변경할 때 각 수정자를 반드시 명시적으로 호출해야 합니다.

Schema::table('users', function (Blueprint $table) { $table->integer('votes')->unsigned()->default(1)->comment('my comment')->change(); });

change 메서드는 컬럼의 인덱스를 변경하지 않습니다. 따라서 컬럼을 수정할 때 인덱스를 명시적으로 추가하거나 제거하려면 인덱스 수정자를 함께 사용해야 합니다.

// 인덱스를 추가... $table->bigIncrements('id')->primary()->change(); // 인덱스를 제거... $table->char('postal_code', 10)->unique(false)->change();

PostgreSQL 컬럼 수정

PostgreSQL에서 컬럼의 타입을 변경할 때는 using 수정자를 사용해 기존 값을 어떤 표현식으로 캐스팅할지 지정할 수 있습니다.

Schema::table('users', function (Blueprint $table) { $table->date('birthday')->using('birthday::date')->change(); });

컬럼 이름 변경하기

컬럼 이름을 변경하려면 스키마 빌더가 제공하는 renameColumn 메서드를 사용하면 됩니다.

Schema::table('users', function (Blueprint $table) { $table->renameColumn('from', 'to'); });

컬럼 삭제하기

컬럼을 삭제하려면 스키마 빌더의 dropColumn 메서드를 사용합니다.

Schema::table('users', function (Blueprint $table) { $table->dropColumn('votes'); });

dropColumn 메서드에 컬럼 이름 배열을 전달하면 테이블에서 여러 컬럼을 한 번에 삭제할 수 있습니다.

Schema::table('users', function (Blueprint $table) { $table->dropColumn(['votes', 'avatar', 'location']); });

사용 가능한 명령어 별칭(Alias)

Laravel은 흔히 사용되는 유형의 컬럼을 삭제할 때 편리하게 쓸 수 있는 여러 메서드를 제공합니다. 각 메서드에 대한 설명은 아래 표에 정리되어 있습니다.

명령어설명
$table->dropMorphs('morphable');morphable_typemorphable_id 컬럼을 삭제합니다.
$table->dropRememberToken();remember_token 컬럼을 삭제합니다.
$table->dropSoftDeletes();deleted_at 컬럼을 삭제합니다.
$table->dropSoftDeletesTz();dropSoftDeletes() 메서드의 별칭입니다.
$table->dropTimestamps();created_atupdated_at 컬럼을 삭제합니다.
$table->dropTimestampsTz();dropTimestamps() 메서드의 별칭입니다.

인덱스

인덱스 생성

Laravel 스키마 빌더는 다양한 종류의 인덱스를 지원합니다. 아래 예제는 email 컬럼을 새로 만들면서 이 값이 유일해야 함을 지정합니다. 컬럼 정의에 unique 메서드를 체이닝하면 인덱스를 만들 수 있습니다:

use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; Schema::table('users', function (Blueprint $table) { $table->string('email')->unique(); });

또는 컬럼 정의 이후에 별도로 인덱스를 생성할 수도 있습니다. 이 경우 스키마 빌더 블루프린트에서 unique 메서드를 호출하면 되며, 이 메서드는 유일 인덱스를 적용할 컬럼명을 인자로 받습니다:

$table->unique('email');

인덱스 관련 메서드에는 배열을 전달해 복합(합성) 인덱스를 만들 수도 있습니다:

$table->index(['account_id', 'created_at']);

인덱스를 생성하면 Laravel이 테이블명, 컬럼명, 인덱스 종류를 바탕으로 자동으로 인덱스 이름을 생성해 줍니다. 하지만 두 번째 인자로 원하는 이름을 직접 지정할 수도 있습니다:

$table->unique('email', 'unique_email');

사용 가능한 인덱스 종류

Laravel의 스키마 빌더 블루프린트 클래스는 Laravel이 지원하는 각 인덱스 종류에 대응하는 메서드를 제공합니다. 각 인덱스 메서드는 인덱스 이름을 지정할 수 있는 두 번째 인자를 선택적으로 받습니다. 이름을 생략하면 테이블명과 컬럼명, 인덱스 종류를 조합해 자동으로 이름이 생성됩니다. 사용 가능한 인덱스 메서드는 다음 표를 참고하세요:

명령어설명
$table->primary('id');기본 키(primary key)를 추가합니다.
$table->primary(['id', 'parent_id']);복합 키를 추가합니다.
$table->unique('email');유일 인덱스를 추가합니다.
$table->index('state');일반 인덱스를 추가합니다.
$table->fullText('body');전체 텍스트 인덱스를 추가합니다 (MariaDB / MySQL / PostgreSQL).
$table->fullText('body')->language('english');지정한 언어의 전체 텍스트 인덱스를 추가합니다 (PostgreSQL).
$table->spatialIndex('location');공간 인덱스를 추가합니다 (SQLite 제외).
$table->vectorIndex('embedding');벡터 인덱스를 추가합니다 (MariaDB / PostgreSQL).

온라인 인덱스 생성

기본적으로 대용량 테이블에 인덱스를 생성하면 인덱스가 만들어지는 동안 테이블이 잠기고 읽기/쓰기가 차단될 수 있습니다. PostgreSQL이나 SQL Server를 사용한다면 인덱스 정의에 online 메서드를 체이닝해서 테이블을 잠그지 않고 인덱스를 생성할 수 있습니다. 이렇게 하면 인덱스 생성 중에도 애플리케이션이 계속 데이터를 읽고 쓸 수 있습니다:

$table->string('email')->unique()->online();

PostgreSQL의 경우 이 옵션은 인덱스 생성 구문에 CONCURRENTLY 옵션을 추가합니다. SQL Server의 경우에는 WITH (online = on) 옵션이 추가됩니다.

인덱스 이름 변경

인덱스 이름을 변경하려면 스키마 빌더 블루프린트가 제공하는 renameIndex 메서드를 사용하면 됩니다. 이 메서드는 첫 번째 인자로 현재 인덱스 이름을, 두 번째 인자로 원하는 새 이름을 받습니다:

$table->renameIndex('from', 'to');

인덱스 삭제

인덱스를 삭제하려면 인덱스의 이름을 지정해야 합니다. 기본적으로 Laravel은 테이블명, 인덱스가 걸린 컬럼명, 인덱스 종류를 조합해 자동으로 인덱스 이름을 생성합니다. 다음은 몇 가지 예시입니다:

명령어설명
$table->dropPrimary('users_id_primary');"users" 테이블에서 기본 키를 삭제합니다.
$table->dropUnique('users_email_unique');"users" 테이블에서 유일 인덱스를 삭제합니다.
$table->dropIndex('geo_state_index');"geo" 테이블에서 일반 인덱스를 삭제합니다.
$table->dropFullText('posts_body_fulltext');"posts" 테이블에서 전체 텍스트 인덱스를 삭제합니다.
$table->dropSpatialIndex('geo_location_spatialindex');"geo" 테이블에서 공간 인덱스를 삭제합니다 (SQLite 제외).
$table->dropVectorIndex('documents_embedding_vectorindex');"documents" 테이블에서 벡터 인덱스를 삭제합니다.

인덱스를 삭제하는 메서드에 컬럼명 배열을 전달하면, 테이블명과 컬럼명, 인덱스 종류를 조합한 관례적인 인덱스 이름이 자동으로 생성되어 사용됩니다:

Schema::table('geo', function (Blueprint $table) { $table->dropIndex(['state']); // 'geo_state_index' 인덱스를 삭제합니다 });

외래 키 제약 조건

Laravel은 데이터베이스 수준에서 참조 무결성을 강제하는 외래 키 제약 조건 생성도 지원합니다. 예를 들어 posts 테이블에 user_id 컬럼을 정의하고 users 테이블의 id 컬럼을 참조하도록 만들어 보겠습니다:

use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; Schema::table('posts', function (Blueprint $table) { $table->unsignedBigInteger('user_id'); $table->foreign('user_id')->references('id')->on('users'); });

이 문법은 다소 길기 때문에, Laravel은 관례를 활용해 더 나은 개발 경험을 제공하는 더 간결한 메서드도 함께 제공합니다. foreignId 메서드를 사용해 컬럼을 만들면 위 예제를 다음과 같이 다시 작성할 수 있습니다:

Schema::table('posts', function (Blueprint $table) { $table->foreignId('user_id')->constrained(); });

foreignId 메서드는 UNSIGNED BIGINT에 대응하는 컬럼을 생성하며, constrained 메서드는 관례에 따라 참조할 테이블과 컬럼을 자동으로 결정합니다. 만약 테이블명이 Laravel의 관례와 다르다면, constrained 메서드에 직접 테이블명을 전달할 수 있습니다. 이때 생성될 인덱스의 이름도 함께 지정할 수 있습니다:

Schema::table('posts', function (Blueprint $table) { $table->foreignId('user_id')->constrained( table: 'users', indexName: 'posts_user_id' ); });

또한 제약 조건의 "on delete", "on update" 동작도 원하는 대로 지정할 수 있습니다:

$table->foreignId('user_id') ->constrained() ->onUpdate('cascade') ->onDelete('cascade');

이러한 동작을 더 표현력 있게 지정할 수 있는 대안 문법도 제공됩니다:

메서드설명
$table->cascadeOnUpdate();상위 레코드가 수정되면 함께 갱신(cascade)됩니다.
$table->restrictOnUpdate();상위 레코드 수정을 제한(restrict)합니다.
$table->nullOnUpdate();상위 레코드가 수정되면 외래 키 값을 null로 설정합니다.
$table->noActionOnUpdate();수정 시 별도 동작을 수행하지 않습니다.
$table->cascadeOnDelete();상위 레코드가 삭제되면 함께 삭제(cascade)됩니다.
$table->restrictOnDelete();상위 레코드 삭제를 제한(restrict)합니다.
$table->nullOnDelete();상위 레코드가 삭제되면 외래 키 값을 null로 설정합니다.
$table->noActionOnDelete();하위(자식) 레코드가 존재하면 삭제를 막습니다.

추가적인 컬럼 수정자는 반드시 constrained 메서드보다 앞에서 호출해야 합니다:

$table->foreignId('user_id') ->nullable() ->constrained();

외래 키 삭제

외래 키를 삭제하려면 dropForeign 메서드에 삭제할 외래 키 제약 조건의 이름을 인자로 전달하면 됩니다. 외래 키 제약 조건의 이름 규칙은 인덱스와 동일합니다. 즉, 테이블명과 제약 조건에 포함된 컬럼명을 조합한 뒤 "_foreign" 접미사를 붙인 형태입니다:

$table->dropForeign('posts_user_id_foreign');

또는 외래 키가 걸린 컬럼명을 배열로 dropForeign 메서드에 전달할 수도 있습니다. 이 배열은 Laravel의 제약 조건 이름 규칙에 따라 외래 키 제약 조건 이름으로 변환됩니다:

$table->dropForeign(['user_id']);

외래 키 제약 조건 켜기/끄기

마이그레이션 내에서 다음 메서드를 사용해 외래 키 제약 조건을 활성화하거나 비활성화할 수 있습니다:

Schema::enableForeignKeyConstraints(); Schema::disableForeignKeyConstraints(); Schema::withoutForeignKeyConstraints(function () { // 이 클로저 내부에서는 제약 조건이 비활성화됩니다... });

WARNING

SQLite는 기본적으로 외래 키 제약 조건이 비활성화되어 있습니다. SQLite를 사용한다면 마이그레이션에서 외래 키를 생성하기 전에 데이터베이스 설정에서 외래 키 지원을 활성화해야 합니다.

이벤트

마이그레이션 작업이 실행될 때마다 편의를 위해 각종 이벤트가 발생합니다. 아래 이벤트들은 모두 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기존 데이터베이스 스키마 덤프 파일을 불러왔을 때 발생합니다.

이 문서는 Laravel 공식 문서(MIT)를 한국 개발자를 위해 번역·재구성한 것입니다.

번역일: 2026년 9월 19일