열일곱번째 날: DBIx::Simple

저자

@luzluna - luz + luna

시작하며

간단히 DB를 사용할 수 있는 모듈인 DBIx::Simple을 소개합니다.

준비물

데비안 계열의 리눅스를 사용하고 있다면 다음 명령을 이용해서 개발 의존 패키지를 설치합니다.

$ sudo apt-get install libpq-dev

필요한 모듈은 다음과 같습니다.

직접 CPAN을 이용해서 설치한다면 다음 명령을 이용해서 모듈을 설치합니다.

$ sudo cpan      \
    DBD::Pg      \
    DBIx::Simple \
    Data::Dump   \
    File::Slurp  \
    Mojolicious

사용자 계정으로 모듈을 설치하는 방법을 정확하게 알고 있거나 perlbrew를 이용해서 자신만의 Perl을 사용하고 있다면 다음 명령을 이용해서 모듈을 설치합니다.

$ cpan           \
    DBD::Pg      \
    DBIx::Simple \
    Data::Dump   \
    File::Slurp  \
    Mojolicious

데이터베이스 접속 준비

PostgreSQL 데이터베이스를 기준으로 데이터베이스를 준비합니다.

데이터베이스에 접속하는 명령은 다음과 같습니다.

$ psql -U postgres
psql (9.3beta2)
Type "help" for help.

사용자 test를 생성하고 비밀번호를 test$$로 설정하는 명령은 다음과 같습니다.

postgres=# CREATE USER test WITH PASSWORD 'test$$';
CREATE ROLE

test 데이터베이스 생성합니다.

postgres=# CREATE DATABASE test;
CREATE DATABASE

생성한 유저에게 접근 권한 부여합니다.

postgres=# GRANT ALL PRIVILEGES ON DATABASE test to test;
GRANT

완료되었습니다. 프로그램을 종료하려면 다음 명령을 입력합니다.

postgres=# \q
$

테이블 생성

테이블을 생성하기 위해 test 계정으로 test 데이터베이스에 접속합니다.

$ psql -U test test
psql (9.3beta2)
Type "help" for help.

postgres 9.3이후 디폴트로 포함된 데이터타입인 JSON 타입으로 데이터 필드를 선언해보았습니다. 내부적으로 TEXT 타입과 같지만 타입 체크 및 요소별 접근이 가능하고 특정 요소에 인덱스를 걸 수 있어서 NOSQL처럼 사용할 수 있다는 장점이 있습니다.

test=> CREATE TABLE item ( id SERIAL PRIMARY KEY, data JSON );
CREATE TABLE

샘플 자료를 추가해보죠.

test=> INSERT INTO item (data) VALUES ('{"name":"test1", "value":31}');
INSERT 0 1

웹 응용을 위한 설정 파일 생성

Mojolicious는 기본적으로 설정 파일을 지원합니다. Mojolicious::Lite를 이용해서 웹 응용을 제작할 경우 웹 응용과 동일한 파일명에 확장자를 .conf로 설정하면 자동으로 읽어들입니다. 파일을 준비해보죠.

$ mkdir dbix-simple-example
$ cd dbix-simple-example
$ touch item.conf
$ touch item.pl

item.conf 파일을 다음처럼 작성합니다.

{
    db => [
        'dbi:Pg:dbname=test;host=127.0.0.1;port=5432',
        'test',
        'test$$',
    ]
}

Mojolicious::Lite 어플리케이션

item.pl 파일을 다음처럼 작성합니다.

#!/usr/bin/env perl

use Mojolicious::Lite;

use DBD::Pg;
use DBI;
use DBIx::Simple;
use JSON;

my $config = plugin Config;

my $dbh = DBIx::Simple->connect( @{$config->{db}} );
helper db => sub { $dbh };

get '/item/list' => sub {
    my $self = shift;

    my $items = $self->db->query("SELECT * FROM item")->hashes;
    for my $item (@$items) {
        $item->{data} = JSON::decode_json( $item->{data} );
    }

    $self->render( json => $items );
};

app;

실행

실행하는 명령은 다음과 같습니다.

$ morbo -l http://*:5000 item.pl
[Mon Dec  9 18:15:17 2013] [debug] Reading config file "/home/user/dev/dbix_simple/config.conf".
[Mon Dec  9 18:15:17 2013] [info] Listening at "http://*:5000".
Server available at http://127.0.0.1:5000.

-l http://*:5000 옵션을 이용해 5000번 포트로 실행했으므로 웹 브라우저로 접속할 때도 http://localhost:5000 주소로 접속해야 합니다. 웹 브라우저로 http://localhost:5000/item/list 주소로 접속해보세요.

[{"id":1,"data":{"value":31,"name":"test1"}}]

예쁘게 잘 나옵니다. :)

CREATE 핸들러 추가

item.pl 웹 응용 코드의 app; 바로 위에 다음 코드를 추가합니다.

get  '/item/create' => 'item/create';
post '/item/create' => sub {
    my $self = shift;

    $self->db->query(
        "INSERT INTO item (data) VALUES (?)",
        $self->param('data'),
    );

    $self->render(json => {"status"=>"done"});
};

그리고 item.plapp; 바로 다음에 다음 코드를 추가합니다.

__DATA__

@@ item/create.html.ep
<form action="/item/create" method="post">
  <input name="data" type="text">
  <input type="submit">
</form>

morbo는 변경한 소스를 자동으로 감지해서 새로 서버를 기동시키므로 별도로 종료 후 다시 기동할 필요는 없습니다. 이제 웹브라우저를 이용해서 http://localhost:5000/item/create 주소로 접속해보면 아이템을 추가하기 위한 간단한 양식을 볼 수 있습니다. 양식에 JSON 형식을 입력하면 다음과 같은 결과를 확인할 수 있습니다.

#
# 입력
#
{"babo":"eee"}

#
# 결과
#
{"status":"done"}

유효하지 않은 JSON 형식을 입력할 경우의 PostgreSQL에서 발생하는 오류를 확인할 수 있습니다.

#
# 입력
#
bad json format

#
# 결과
#
DBD::Pg::st execute failed: ERROR:  invalid input syntax for type json

명령줄에서 사용하기

웹 페이지를 통하지 않고 일반 명령줄 유틸리티에서도 간단히 사용할 수 있습니다.

$!/usr/bin/env perl

use v5.14;
use strict;
use warnings;

use DBIx::Simple;
use Data::Dump qw( dump );
use File::Slurp;

my $config = eval( read_file('config.conf') );

my $dbh = DBIx::Simple->connect( @{$config->{db}} );

my $ret= $dbh->query("SELECT * FROM item")->hashes;

say dump($ret);

실행한 결과는 다음과 같습니다.

$ perl dbis.pl
[
  { data => "{\"name\":\"test1\", \"value\":31}", id => 1 },
  { data => "{\"babo\":\"eee\"}", id => 2 },
]

정리하며

웹페이지를 만드는 용도로 사용한다면 DBIx::XHTML_Table 모듈을 이용해서 테이블로 그려 볼수도 있고, 명령줄에서 사용한다면 Text::Table을 사용해 예쁘게 출력해볼 수도 있습니다. 이 부분은 과제로 남겨두죠. :)

MojoliciousDancer 같은 경량 웹프레임워크를 사용하다보면 DBIx::Class 모듈이 조금 무겁게 느껴질 때가 있습니다. 그렇다고 그냥 DBI 모듈로 직접 쿼리를 날리는 것은 불편하구요. 이런때에 간단히 DBIx::Simple 모듈을 이용해보는건 어떨까요? ;-)

blog comments powered by Disqus