라라벨로 배우는 실전 PHP 웹 프로그래밍
PART 1 라라벨 입문
7. 데이터베이스 마이그레이션
데이터베이스 마이그레이션이란, 테이블 스키마의 버전 관리다. 데이터베이스 마이그레이션을 이용하면, 테이블에 새로운 열을 추가한다든지, 열 이름을 바꾼다든지 하는 이력을 마이그레이션 코드로 남겨 두고 필요할 때마다 마이그레이션을 실행했다가 롤백하는 등의 작업을 자유롭게 할 수 있다.
SQL 문장을 이용해서 데이터베이스 스키라를 만들고 관리할 수 있는데, 마이그레이션은 왜 필요할까?
모던 개발 방법론
팀 내 개발자들은 같은 데이터베이스 스키마로 개발해야 한다. 한 개발자의 스키마 변경을 다른 개발자도 사용해야 한다. 개발 환경뿐 아니라 테스트 서버, 지속적 통합 서버, 운영 서버 등에서 환경을 쉽고 빠르게 만들 수 있는 도구가 필요하다.‘완벽’이란 없다. ‘완벽 추구’만 있을 뿐이다.
비지니스는 계속 변하고, 요구 사항도 계속 변한다. 데이터베이스 모델링을 기가 막히게 했더라도 시간이 지나면 바뀔 수 밖에 없다(users 테이블에 직원과 고객을 모두 넣었는데, 직원이 고객이 되면? 또는 직원일 때의 이메일과 고객일 때의 이메일이 다르다면?) 또는 실수로 열이름에 오탈자가 들어갔다거나, 모델링을 잘못했는데 빠르게 롤백해야 하는 상황도 생각해 볼 수 있다.
번거롭더라도 데이터베이스 마이그레이션을 작성해 두면 데이터베이스 스키마 때문에 위기에 처하거나 변경 요구가 생겼을 때 효과적으로 대응할 수 있다.
7.1 마이그레이션 만들기
이전 테이블을 모두 삭제한다
데이터베이스 정리
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
$ mysql -uhomestead -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 36
Server version: 8.0.22 Homebrew
Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> use myapp;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> set foreign_key_checks=0;
Query OK, 0 rows affected (0.00 sec)
mysql> drop table posts;
Query OK, 0 rows affected (0.01 sec)
mysql> drop table authors;
Query OK, 0 rows affected (0.01 sec)
mysql> set foreign_key_checks=1;
Query OK, 0 rows affected (0.00 sec)
새로운 마이그레이션 만든다. --create=테이블_이름
과 --table=테이블_이름
옵션을 주면 좀더 많은 코드를 생성해 준다.
마이그레이션 클래스 뼈대 코드 만들기
1
2
3
4
$ php artisan make:migration create_posts_table --create=posts
Created Migration: 2021_01_17_141752_create_posts_table
$ php artisan make:migration create_authors_table --create=authors
Created Migration: 2021_01_17_141834_create_authors_table
생성된 파일은 database/migrations
디렉터리 아래에 있다.
NOTE
1
2
마이그레이션의 파일 이름
테이블과 모델 이름의 관례처럼 마이그레이션 이름 명명에 엄격한 규칙이 있는 것은 아니다. 관례적으로 스네이크 표기법을 사용하며, create_, make_, add_, drop_, change_ 등으로 시작하고, _table로 끝난다. 둘 사이에는 아미그레이션을 설명할 수 있는 내용을 기술한다.
up()
은 마이그레이션을 실행하는 메서드이고, down()
은 롤백을 위한 메서드다.
database/migrations/2021_01_17_141752_create_posts_table.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreatePostsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->increments('id');
$table->string('title');
$table->text('body');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('posts');
}
}
database/migrations/2021_01_17_141834_create_authors_table.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateAuthorsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('authors', function (Blueprint $table) {
$table->increments('id');
$table->string('email',255);
$table->string('password',60);
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('authors');
}
}
- Schema::create(string $table , \Closure $callback) 테이블을 만든다.
- Schema::dropIfExists(string $table ) 테이블을 지운다.
- Schema::table(string $table , \Closure $callback) 테이블을 생성/삭제를 제외한 나머지 대부분의 스키마 관련 작업을 담는다.
메서드 | 내용 |
---|---|
boolean(), dateTime(), enum(), integer(), timestamp() | 열 타입 메서드 |
timestamps(), softDeletes() | 도우미 메서드 |
nullable(), default(), unsigned() | 장식 메서드 |
unique(), index() | 인덱스 메서드 |
전체 목록은 공식 문서를 참고 하자.
note
1
2
타입 힌트
마이그레이션 코드에서 blueprint라 타이핑된 문자열은 타입 힌트다. Schema::create() 메서드의 주 번째 인자는 콜백 함수인데, 콜백 함수가 인자로 받는 $table이 Illuminate/Database/Schema/Blueprint 클래스의 인스턴스여야 한다고 강제하는 것이다.
7.2 마이그레이션 실행
마이그레이션 실행 확인
마이그레시연 힐생
1
2
3
4
5
6
7
8
9
$ php artisan migrate
Migrating: 2014_10_12_000000_create_users_table
Migrated: 2014_10_12_000000_create_users_table (16.35ms)
Migrating: 2014_10_12_100000_create_password_resets_table
Migrated: 2014_10_12_100000_create_password_resets_table (9.62ms)
Migrating: 2021_01_17_141752_create_posts_table
Migrated: 2021_01_17_141752_create_posts_table (4.58ms)
Migrating: 2021_01_17_141834_create_authors_table
Migrated: 2021_01_17_141834_create_authors_table (4.69ms)
마이그레이션 실행 결과
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
$ mysql -uhomestead -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 39
Server version: 8.0.22 Homebrew
Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> use myapp;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> describe posts;
+------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+----------------+
| id | int unsigned | NO | PRI | NULL | auto_increment |
| title | varchar(255) | NO | | NULL | |
| body | text | NO | | NULL | |
| created_at | timestamp | YES | | NULL | |
| updated_at | timestamp | YES | | NULL | |
+------------+--------------+------+-----+---------+----------------+
5 rows in set (0.00 sec)
mysql> describe authors;
+------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+----------------+
| id | int unsigned | NO | PRI | NULL | auto_increment |
| email | varchar(255) | NO | | NULL | |
| password | varchar(60) | NO | | NULL | |
| created_at | timestamp | YES | | NULL | |
| updated_at | timestamp | YES | | NULL | |
+------------+--------------+------+-----+---------+----------------+
5 rows in set (0.00 sec)
7.3 롤백
롤백
1
2
3
4
5
6
7
8
9
$ php artisan migrate:rollback
Rolling back: 2021_01_17_141834_create_authors_table
Rolled back: 2021_01_17_141834_create_authors_table (13.51ms)
Rolling back: 2021_01_17_141752_create_posts_table
Rolled back: 2021_01_17_141752_create_posts_table (3.25ms)
Rolling back: 2014_10_12_100000_create_password_resets_table
Rolled back: 2014_10_12_100000_create_password_resets_table (4.22ms)
Rolling back: 2014_10_12_000000_create_users_table
Rolled back: 2014_10_12_000000_create_users_table (3.21ms)
테이블이 삭제 되었다
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$ mysql -uhomestead -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 41
Server version: 8.0.22 Homebrew
Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> use myapp;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> describe posts;
ERROR 1146 (42S02): Table 'myapp.posts' doesn't exist
mysql> describe authors;
ERROR 1146 (42S02): Table 'myapp.authors' doesn't exist
migration 테이블은 롤백 해도 지워지지 않는다.
마이그레이션 실행
1
2
3
4
5
6
7
8
9
$ php artisan migrate
Migrating: 2014_10_12_000000_create_users_table
Migrated: 2014_10_12_000000_create_users_table (16.35ms)
Migrating: 2014_10_12_100000_create_password_resets_table
Migrated: 2014_10_12_100000_create_password_resets_table (9.62ms)
Migrating: 2021_01_17_141752_create_posts_table
Migrated: 2021_01_17_141752_create_posts_table (4.58ms)
Migrating: 2021_01_17_141834_create_authors_table
Migrated: 2021_01_17_141834_create_authors_table (4.69ms)
7.4 열 추가
authors 테이블에 name 컬럼을 추가 해 보자.
테이블 열 추가 마이드레이션 뼈대 코드 만들기
1
2
$ php artisan make:migration add_name_to_authors_table --table=authors
Created Migration: 2021_01_17_145632_add_name_to_authors_table
database/migrations/2021_01_17_145632_add_name_to_authors_table.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddNameToAuthorsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('authors', function (Blueprint $table) {
$table->string('name')->nullable();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('authors', function (Blueprint $table) {
$table->dropColumn('name');
});
}
}
create() 메소드가 아닌 table() 메서드를 사용한다
마이그레이션 실행
1
2
3
$ php artisan migrate
Migrating: 2021_01_17_145632_add_name_to_authors_table
Migrated: 2021_01_17_145632_add_name_to_authors_table (2.69ms)
마이그레이션 실행 결과
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
$ mysql -uhomestead -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 53
Server version: 8.0.22 Homebrew
Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> use myapp;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> describe authors;
+------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+----------------+
| id | int unsigned | NO | PRI | NULL | auto_increment |
| email | varchar(255) | NO | | NULL | |
| password | varchar(60) | NO | | NULL | |
| created_at | timestamp | YES | | NULL | |
| updated_at | timestamp | YES | | NULL | |
| name | varchar(255) | YES | | NULL | |
+------------+--------------+------+-----+---------+----------------+
6 rows in set (0.00 sec)
초기화 및 새로고침
migrate:rollback 명령은 직전 마이그레이션만 록백 하는 반면, migrate:reset 명령은 모든 마이그레이션을 롤백하고 데이터베이스를 초기화한다. migrateLrefresh는 초기화한 후, 마이그레이션을 다시 실행하는 명령이다.
마이그레이션 새로고침
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
% php artisan migrate:refresh
Rolling back: 2021_01_17_145632_add_name_to_authors_table
Rolled back: 2021_01_17_145632_add_name_to_authors_table (13.63ms)
Rolling back: 2021_01_17_141834_create_authors_table
Rolled back: 2021_01_17_141834_create_authors_table (2.90ms)
Rolling back: 2021_01_17_141752_create_posts_table
Rolled back: 2021_01_17_141752_create_posts_table (2.90ms)
Rolling back: 2014_10_12_100000_create_password_resets_table
Rolled back: 2014_10_12_100000_create_password_resets_table (3.84ms)
Rolling back: 2014_10_12_000000_create_users_table
Rolled back: 2014_10_12_000000_create_users_table (3.18ms)
Migrating: 2014_10_12_000000_create_users_table
Migrated: 2014_10_12_000000_create_users_table (10.88ms)
Migrating: 2014_10_12_100000_create_password_resets_table
Migrated: 2014_10_12_100000_create_password_resets_table (12.00ms)
Migrating: 2021_01_17_141752_create_posts_table
Migrated: 2021_01_17_141752_create_posts_table (5.69ms)
Migrating: 2021_01_17_141834_create_authors_table
Migrated: 2021_01_17_141834_create_authors_table (4.86ms)
Migrating: 2021_01_17_145632_add_name_to_authors_table
Migrated: 2021_01_17_145632_add_name_to_authors_table (5.58ms)
Comments powered by Disqus.