dbDelta() 함수 똑바로 쓰기

기본적인 것들

$wpdb->prefix 꼭 사용하라. 보통 접두에 언더바 붙어 있으니 언더바 중복하지 말고.


$wpdb->get_charset_collate() 메소드는 자동으로 CREATE TABLE (...) 구문 뒤에 들어갈 DEFAULT CHARACTER SET {CHARSET} COLLATE {COLLATE} 구문을 만들어 준다.


dbDelta() 호출 전 반드시, require_once( ABSPATH . 'wp-admin/includes/upgrade.php' ); 해야 한다. 안그러면 fatal error 먹는다.

테이블 변경

코덱스를 참고하면 대략 다음과 같이 쓰라고 되어 있다.

  • 필드 각각 한 줄씩 나눠서 써라.
  • PRIMARY KEY 선언과 주 키 선언 사이에 2개의 스페이스로 띄워라.
  • INDEX 보다는 KEY를 써라. 최소 하나의 키를 첨부해라.
  • KEY는 반드시 다음 괄호 사이에 하나의 스페이스를 두어야 한다.
  • 필드 이름 앞뒤로 어깨점이나 백틱으로 감싸지 마라.
  • 필드 타입은 항상 소문자.
  • CREATE TABLE, UPDATE, KEY 같은 SQL 키워드는 항상 대문자.
  • 필드에 길이 파라미터를 지정할 수 있는 필드는 항상 써야 한다. 가령, int(11) 이나 bigint(20) 같은 것.

dbDelta() 는 꽤나 복잡한 프로세스를 거쳐 SQL 문을 분석해 테이블의 변화를 감지한다. 그리고 자신이 어떤 일을 했는지를 배열로 리턴한다.

Array
(
[wp_temp_table] => Created table wp_temp_table
)

위 예시는 wp_table_table 을 만들었을 때의 결과이다. 그리고,

Array
(
    [wp_temp_table.middle_name] => Added column wp_temp_table.middle_name
)

이 예시는 wp_temp_tablemiddle_name 이라는 필드를 추가했을 때 결과이다. 이런 식으로 필드 타입, 기본값 등등이 잘 변경되는지 확인할 수 있다.


필드가 삭제나 인덱스 삭제는 되지 않는다. 별도로 필드를 없애는 구문을 추가해야 할 것 같다.


코덱스에서는 INDEX 보다는 KEY 쓰리고 하지만, INDEX 가 안 되는 건 아니다. 당연히. 그리고 이미 만들어진 인덱스 변경도 잘 되지 않는다. 별도로 구문을 써야 한다. 마찬가지로 PK 선언시 두 칸을 띄워 쓰라고 하는데, 딱히 왜 그래야 하는지는 잘 모르겠다.


복잡한 변경은 잘 인지하지 못하는 것 같다. 예를 들어 필드의 타입과 기본값까지 동시에 변경 처리하는 경우, 그 둘의 변경점을 잘 감지하지 못하는 것 같다.


CREATE TABLE 선언시 CREATE TABLE IF NOT EXISTS 나, 별도로 테이블이 있는지 없는지 체크하는 따위의 삽질을 하지 않아도 된다. dbDelta 가 적절히 CREATE TABLE 구문과 현재 선언된 테이블의 구조를 파악해 CREATE TABLE을 그대로 사용하기도 하지만, CREATE TABLE 대신에 ALTER TABLE 를 스스로 만들어 내거나, 변경점이 없다면 아무 일도 하지 않기 때문이다.


이런 것도 한 번 체크해 보라. dbDelta() 는 까다로운 녀석이다. SQL 구문에 변경점이 전혀 없어, 딱히 변경할 것이 없어 보인다. 그래도 진짜 아무 일도 실행하지 않는지 (즉, dbDelta()가 빈 배열을 리턴하는지) 확실히 체크해 보라. 간혹, 예를 들어, 타입을 대문자로 썼다거나 하는뭔가 실수 아닌 실수가 있다면 dbDelta()는 변경할 것이 없는데도 계속 ALTER TABLE 구문을 만드는 삽질을 하고 있을 수도 있다.


db 버전을 설정하고 잘 관리하라. 예를 들어,

function update_my_table() {
  $current_version = '1.1.0';
  $installed_version = get_option( 'my_db_version' );

  if ( $current_version !== $installed_version ) {
    global $wpdb;

    $sql = "CREATE TABLE .....";

    require_once ABSPATH . 'wp-admin/includes/upgrade.php';
    dbDelta( $sql );
    update_version( $current_version );
  }
}Code language: PHP (php)

같은 패턴을 쓰면 된다. 이 때 사용자는 테이블을 업데이트하기 위해 플러그인을 비활성화/활성화를 할 수 없다. 그러므로 plugins_loaded 같은 액션의 콜백에서 이 함수를 한 번 호출해야 한다.

만약 이렇게 되면 activation callback 에서 굳이 테이블을 생성하는 작업을 중복해서 할 필요는 없는 것 같다. 아, 물론 플러그인 활성화 시 바로 초기화 작업 같은 것을 해 준다면 이야기가 달라지겠지만.

결론

급하게 테스트해보고 메모하듯이 글을 적었다. 내가 틀린 것을 적었을 수도 있다! 어쨌든 변경점이 생길 때 dbDelta()가 리턴하는 결과와 테이블의 구조를 실제로 잘 체크해야 한다. dbDelta()가 기능 개선이 될 수도 있으니 말이다.

암튼 현재 dbDelta() 함수는 다른 웹 프레임워크의 마이그레이션 솔루션 (예를 들어, 장고) 만큼 테이블 변경을 세련되게 챙겨주지는 못하지만, 그래도 간단하게 테이블 변경을 찜쪄먹기에는 나름 유용한 도구로 보인다. 다만, 이 녀석이 진짜 까다로우니 조심해서 쓰도록 하자.

댓글 남기기