> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# 데이터베이스 마이그레이션

> Laravel의 마이그레이션 기능을 사용해 데이터베이스 스키마를 버전 관리하는 방법을 설명합니다.

## 마이그레이션이란

마이그레이션은 데이터베이스의 버전 관리 같은 것입니다.
팀이 애플리케이션의 데이터베이스 스키마 정의를 공유·관리할 수 있습니다.

소스 코드를 pull한 후에 "로컬 데이터베이스에 컬럼을 수동으로 추가해 주세요"라고 팀 멤버에게 전달해야 하는 상황을 경험한 적이 있을 것입니다.
마이그레이션은 그 문제를 해결합니다.

마이그레이션 파일은 `database/migrations` 디렉터리에 저장됩니다.
각 파일명에는 타임스탬프가 포함되어 있어 Laravel이 마이그레이션 실행 순서를 결정하는 데 사용됩니다.

## 마이그레이션 파일 생성

`make:migration` Artisan 명령으로 새 마이그레이션 파일을 생성합니다.

```shell theme={null}
php artisan make:migration create_posts_table
```

마이그레이션 이름에서 Laravel이 테이블 이름을 추측하고 적절한 스텁을 생성합니다.
`create_posts_table`이라는 이름이라면 `posts` 테이블을 생성하는 코드가 미리 준비됩니다.

## 마이그레이션 구조

마이그레이션 클래스는 `up`과 `down` 두 개의 메서드를 가집니다.

* `up` 메서드: 테이블·컬럼·인덱스를 데이터베이스에 추가합니다.
* `down` 메서드: `up`의 조작을 되돌립니다. 롤백 시 호출됩니다.

```php theme={null}
<?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_at`과 `updated_at`을 함께 추가     |
| `$table->softDeletes()`             | 논리 삭제용 `deleted_at` 컬럼 추가             |
| `$table->foreignId('user_id')`      | 외래 키용 `BIGINT UNSIGNED 컬럼`            |

### 컬럼 수식자

컬럼 정의에는 메서드 체이닝으로 수식자를 추가할 수 있습니다.

```php theme={null}
$table->string('email')->unique();
$table->string('name')->nullable();
$table->integer('votes')->default(0);
$table->string('title')->after('id'); // 지정된 컬럼 뒤에 배치
```

## 마이그레이션 실행

`migrate` 명령으로 미실행된 마이그레이션을 모두 실행합니다.

```shell theme={null}
php artisan migrate
```

실행된 마이그레이션과 미실행된 마이그레이션을 확인하려면 `migrate:status`를 사용합니다.

```shell theme={null}
php artisan migrate:status
```

<Warning>
  프로덕션 환경에서 마이그레이션을 실행하면 확인 프롬프트가 표시됩니다.
  확인 없이 실행하려면 `--force` 플래그를 사용하지만, 데이터가 손실되는 조작도 있으므로 신중하게 진행해 주세요.
</Warning>

## 롤백

가장 최근의 마이그레이션 배치를 취소하려면 `migrate:rollback`을 사용합니다.

```shell theme={null}
php artisan migrate:rollback
```

특정 스텝 수만큼만 롤백하려면 `--step` 옵션을 지정합니다.

```shell theme={null}
# 최근 5건의 마이그레이션을 롤백
php artisan migrate:rollback --step=5
```

모든 마이그레이션을 롤백한 후 다시 실행하려면 `migrate:refresh`를 사용합니다.

```shell theme={null}
php artisan migrate:refresh
```

<Info>
  `migrate:refresh`는 모든 테이블을 다시 만들기 때문에 기존 데이터가 사라집니다.
  개발 중 데이터베이스 리셋에 편리합니다.
</Info>

## 실전 예시: posts 테이블 생성

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

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

```shell theme={null}
php artisan make:migration create_posts_table
```

### 2. 마이그레이션 편집

`database/migrations/xxxx_xx_xx_xxxxxx_create_posts_table.php`를 열어 편집합니다.

```php theme={null}
<?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. 마이그레이션 실행

```shell theme={null}
php artisan migrate
```

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

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

테이블 생성 후 새 컬럼을 추가하고 싶은 경우, 기존 마이그레이션을 편집하지 말고 새 마이그레이션을 생성합니다.

```shell theme={null}
php artisan make:migration add_excerpt_to_posts_table
```

```php theme={null}
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');
    });
}
```

<Tip>
  기존 마이그레이션 파일을 직접 편집하는 것은 피합시다.
  다른 멤버나 프로덕션 환경과의 정합성이 깨집니다.
  변경은 항상 새 마이그레이션으로 추가합니다.
</Tip>

## 마이그레이션 이벤트

마이그레이션 조작마다 [이벤트](/ko/events)가 발행됩니다. 모든 이벤트는 `Illuminate\Database\Events\MigrationEvent`를 상속하고 있습니다.

| 클래스                                              | 설명                                |
| ------------------------------------------------ | --------------------------------- |
| `Illuminate\Database\Events\DatabaseRefreshed`   | `migrate: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` 이벤트를 리슨해 마이그레이션 완료 후 캐시를 삭제할 수 있습니다.

```php theme={null}
use Illuminate\Database\Events\MigrationsEnded;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Event;

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

## 다음 단계

<Card title="데이터베이스 시딩" icon="seedling" href="/ko/seeding">
  마이그레이션으로 생성한 테이블에 샘플 데이터를 투입하는 방법을 배웁니다.
</Card>

<Card title="Eloquent 입문" icon="database" href="/ko/eloquent">
  마이그레이션으로 생성한 테이블을 Eloquent ORM으로 조작하는 방법을 배웁니다.
</Card>


## Related topics

- [데이터베이스 테스트](/ko/database-testing.md)
- [데이터베이스 시딩](/ko/seeding.md)
- [데이터베이스 설정](/ko/database.md)
- [Laravel Pulse](/ko/pulse.md)
- [Eloquent 입문](/ko/eloquent.md)
