이번 챕터의 코드는 https://github.com/koeunyeon/ci4/tree/model-migration 에 있습니다.
최근에 나온 대부분의 웹 프레임워크는 "마이그레이션"을 사용합니다. 간단하게 말하면, 자동으로 "데이터베이스의 버전 관리"를 하는 겁니다.
많은 서비스에서 프로그램과 데이터베이스는 끊임없이 변화해 나갑니다. 이 중 프로그램은 형상 관리(VCS - Version Control System)을 통해 소스코드의 변화를 추적해 나가지만, 데이터베이스는 그렇지 못한 경우가 많았습니다. 기껏해야 SQL 스크립트를 버전관리에 추가하는 정도였죠.
마이그레이션은 이 과정을 자동화합니다. 코드이그나이터4의 경우를 예로 들면 PHP로 데이터베이스 테이블 스키마를 정의한 파일을 생성하고 이 파일을 통해 테이블을 생성하거나 수정하거나 삭제하게 됩니다. 이 때 사용한 파일을 마이그레이션 파일이라고 부르는데, 마이그레이션 파일은 여러 개가 생성될 수 있어서 선택적 데이터베이스 관리가 가능해집니다.
직접 마이그레이션을 만들고, 마이그레이션을 통해 데이터베이스 테이블을 관리해 보겠습니다.
이번에는 PHPStorm이 아니라, 직접 터미널에서 입력하겠습니다. 마이그레이션은 개인의 로컬 서버 뿐만 아니라 개발 서버, 운영 서버에도 동일하게 해야 하는 경우가 많으므로 터미널로 사용하는 것이 빠르기 때문입니다.
마이그레이션은 컨트롤러에서도 불러서 사용할 수 있지만, DDL(Data Definition Language - create table, alter table .. 등)을 직접 웹에서 호출하는 것은 위험천만하기 짝이 없으므로 가능하면 사용하지 마세요.
우선 터미널을 엽니다. 윈도우즈에서는 Windows
키를 누르고 cmd
를 입력하면 됩니다.
이제 프로젝트 루트 디렉토리로 이동합니다.
D:
cd D:\ci4\sample
마이그레이션 파일을 생성합니다.
php spark migrate:create rich
위 명령어 중 rich
는 그냥 이름이므로 식별하기 좋은 이름으로 적어주세요. 지금은 sample_rich
테이블을 만들 예정이어서 rich
로 지었습니다.
PHPStorm으로 돌아와서 app/Database/Migrations
디렉토리 아래에 보면 Y-m-d-u_이름.php
파일이 생성되어 있습니다. 예를 들면 2021-02-02-035600_rich.php
처럼이요.
내용을 살펴보면 아래와 같은 파일이 생성되어 있습니다.
<?php namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
class Rich extends Migration
{
public function up() // (1)
{
//
}
//--------------------------------------------------------------------
public function down() // (2)
{
//
}
}
(1) 마이그레이션이 실행될 때 사용하는 메소드입니다.
(2) 마이그레이션을 롤백(rollback - 되돌림) 하거나, 리프레시(refresh - 삭제하고 다시 생성)할 때 사용하는 메소드입니다.
생성된 마이그레이션 파일 내용을 아래와 같이 변경하겠습니다.
<?php namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
class Rich extends Migration
{
public function up()
{
// (1)
$this->forge->addField([
'sample_rich_id' => [ // (2)
'type' => 'BIGINT', // (3)
'unsigned' => true, // (4)
'auto_increment' => true, // (5)
],
'name' => [
'type' => 'VARCHAR',
'constraint' => '40', // (6)
],
'age' => [
'type' => 'INT',
'null' => true, // (7)
],
'created_at' => [ // (8)
'type' => 'VARCHAR',
'constraint' => '25', // (9)
],
'updated_at' => [ // (10)
'type' => 'VARCHAR',
'constraint' => '25',
],
'deleted_at' => [ // (11)
'type' => 'VARCHAR',
'constraint' => '25',
'null' => true,
]
]);
$this->forge->addKey('sample_rich_id', true); // (12)
$this->forge->createTable('sample_rich'); // (13)
}
//--------------------------------------------------------------------
public function down()
{
$this->forge->dropTable('sample_rich'); // (14)
}
}
(1) 데이터베이스 필드를 정의합니다. forge
는 데이터베이스 관리 클래스라고 생각하시면 됩니다. addField
메소드는 연관배열을 파라미터로 받는데, 연관배열의 각 키가 열 이름이 됩니다.
(2) 연관배열의 키가 sample_rich_id
이므로 sample_rich_id
라는 열을 정의한다는 의미가 됩니다.
(3) type
은 "데이터베이스의 타입"입니다. PHP의 타입이 아니므로 주의하세요.
(4) unsigned
는 짐작할 수 있듯이 "자연수"를 나타냅니다. 즉 음수가 들어갈 수 없습니다.
(5) auto_increment
는 자동 증가를 의미합니다.
(6) constraint
속성은 데이터의 길이를 나타냅니다. VARCHAR
의 경우 데이터의 길이는 필수이므로 40으로 지정했습니다.
(7) null => true
라면 allow null
, 즉 null
허용입니다. 기본값은 false
입니다.
(8) created_at
은 생성 시간을 나타냅니다. 코드이그나이터4에서는 모델에서 자동으로 생성, 수정, 삭제 시간을 넣어주는 기능이 있습니다. 이 기능을 사용해 보기 위해 created_at
열을 추가합니다.
(9) created_at
속성은 기본적으로 PHP의 datetime
형식을 따릅니다. 2021-02-01 22:32:23
처럼요. 19글자를 차지하지만 혹시 모를 여백을 위해 25글자로 맞춰둡니다.
(10) updated_at
열은 수정 시간을 나타냅니다. 데이터가 수정되면 자동으로 updated_at
열도 업데이트됩니다.
(11) deleted_at
열은 삭제 시간을 나타냅니다. 코드이그나이터4에서 소프트 딜리트(soft delete)
를 사용할 경우 데이터를 실제로 삭제하는 것이 아니라 "삭제되었다고 표시"만 할 수 있습니다. 이 때 "삭제되었다고 표시"하는 기준이 deleted_at
이 비어있는 지 확인하는 것이기 때문에 deleted_at
열을 정의합니다.
(12) addKey
메소드로 주 키 (primary key)를 설정합니다.
첫번째 파라미터는 열의 이름, 두번째 파라미터는 주 키인지 여부입니다. 두번째 파라미터가 false
라면 데이터베이스에 단순 인덱스만 추가하게 됩니다.
샘플에는 나와있지 않지만 세번째 파라미터가 true
라면 유일 인덱스(Unique Index
)로 추가하게 됩니다. 세번째 파라미터의 기본값은 false
입니다.
(13) 테이블을 생성합니다. 파라미터는 테이블의 이름입니다. 예제에서는 sample_rich
테이블을 생성했습니다.
(14) 테이블을 삭제하기 위해서는 $this->forge->dropTable(테이블이름);
형태로 사용합니다.
마이그레이션 파일을 실제 데이터베이스에 적용하려면 터미널에서 아래와 같이 입력합니다.
php spark migrate
아래와 같은 메세지가 나오면 성공입니다.
Running all new migrations...
Done
실제로 잘 적용되었는지 확인해 봅시다. PHPStorm에서 Database - Schemas - ci4db 를 클릭하고 ctrl + F5
키를 눌러 새로고침하면 sample_rich
테이블이 있는 것을 확인할 수 있습니다.
sample_rich
테이블 선택 후 ctrl + B
키를 눌러 테이블 스키마를 확인해 보면 아래와 같습니다.
-- auto-generated definition
create table sample_rich
(
sample_rich_id bigint unsigned auto_increment
primary key,
name varchar(40) not null,
age int null,
created_at varchar(25) not null,
updated_at varchar(25) not null,
deleted_at varchar(25) null
)
charset = utf8;
터미널에서 현재 마이그레이션 상태를 확인해 보겠습니다. 현재 마이그레이션 파일들 목록이 나옵니다.
php spark migrate:status
만약 마이그레이션을 되돌리려면 롤백(rollback)
을 사용할 수 있습니다. 아래 내용을 터미널에 입력하면 마이그레이션 파일의 down()
메소드가 실행되어 테이블이 삭제(drop
)됩니다.
php spark migrate:rollback
테이블을 지우고 다시 만드는 것을 한번에 할 수도 있습니다. 테스트 데이터를 깨끗하게 하고 싶을 때 주로 사용하게 됩니다.
php spark migrate:refresh