카탈리스트(Catalyst)와 파일 업로드

주의: [카탈리스트(Catalyst)와 파일 업로드]의 가장 최근 판은 이곳에서 확인할 수 있습니다.

시작하며

카탈리스트(Catalyst)는 웹 응용 개발시 필연적인 발생하는
반복적인 작업을 줄여주고 협업 작업을 가능하게 도와주는
펄(Perl) 기반의 MVC 웹 응용 프레임워크입니다.
카탈리스트는 모델(Model)-뷰(View)-컨트롤러(Controller)의 개념을 도입했기 때문에
모델은 DB로, 뷰는 HTML로, 컨트롤러는 실제 로직으로 치환이 가능하므로
업무를 분담하기 쉬워지며, 코드의 독립성이 높아져 유지보수 측면에서 유리합니다.
카탈리스트는 웹응용 개발에 필요한 대부분의 기능을 미리 제공하고 있는데
파일 업로드 역시 번거로운 작업은 모두 처리해주기 때문에
카탈리스트를 기반으로 웹 응용을 개발하는 경우 손쉽게 처리할 수 있습니다.

관련 연구

준비물

카탈리스트로 파일 업로드를 다루기 위해서는 우선 카탈리스트를 설치해야 합니다.
카탈리스트는 CPAN으로 설치하는 것이 정석이지만, 번거롭다면 리눅스의 경우
배포판의 저장소에서 카탈리스트 패키지를 대부분 제공하고 있으므로
이를 활용하면 손쉽게 설치할 수 있습니다.
(본 문서에서는 카탈리스트를 시스템에 설치하는 방법에 대해 다루지는 않습니다.)
다음은 카탈리스트의 파일 업로드와 관련한 모듈의 목록 입니다:

구현

설정

업로드하는 파일을 임시로 저장할 공간에 시스템 임시 디렉터리를 사용하지 않고
직접 지정하기 위해서는 설정 파일에 uploadtmp 항목을 추가합니다.
더불어 업로드와 직접적인 상관은 없지만 임시 디렉터리에 저장한 파일을
옮겨둘 디렉터리 경로도 userdir 항목을 이용해서 표시합니다:

  tinyblog.conf:
  ...
  uploadtmp       __HOME__/tmp/upload
  userdir         __HOME__/tmp/user
  ...

설정 파일을 이용하지 않고 코드에 직접 명시할 경우는 다음을 참고합니다:

  lib/TinyBlog.pm:
  ...

  __PACKAGE__->config(
      name      => 'TinyBlog',
      session   => {
        flash_to_stash => 1,
      },
      uploadtmp => '__HOME__/tmp/upload',
      userdir   => '__HOME__/tmp/user',
  );

  __PACKAGE__->setup();

뷰(View)

TinyBlog 에서 파일을 업로드하기 위한 양식을 웹브라우저에 출력하기 위한
템플릿 툴킷(Template Toolkit)의 소스의 일부분은
다음과 같습니다.
업로드를 위한 양식의 식별자 이름이 mkfile임을 주의하세요:

  root/src/upload/index.tt2:
  <div class="upload">
    <h3>[% title %]</h3>
    <table>
      <tr>
          <form method="post" action="[% c.uri_for('/upload') | html %]"
                enctype="multipart/form-data">
            <td> <label for="upload_file">파일이름:</label> </td>
            <td> <input type="file" name="mkfile" /> </td>
            <td> <input type="submit" value="업로드" /> </td>
          </form>
      </tr>
    </table>
  </div>

컨트롤러(Controller)

다음은 TinyBlog 업로드 모듈인 TinyBlog::Controller::Upload의 소스 코드 일부입니다.
TinyBlog::Controller::Upload 모듈의 index 함수의 경우
웹에서는 http://localhost:3000/upload 로 접근할 수 있습니다.
if 조건문에서 뷰에서 업로드를 위해 사용한 mkfile 식별자를 이용함을 주의하세요:

  lib/TinyBlog/Controller/Upload.pm:
  package TinyBlog::Controller::Upload;

  use strict;
  use warnings;
  use File::Basename;

  use parent 'Catalyst::Controller';

  sub index :P ath :Args {
      my ( $self, $c ) = @_;

      if ( my $upload = $c->request->upload('mkfile') ) {

          my $upload_basename = basename( $upload->filename );
          $upload_basename =~ s/[`~!@#\$%^&*()=+\[{\]}\\|;:'",<>\/?]+/_/g;
          $upload_basename =~ s/\s+/_/g;
          $upload_basename =~ s/_+/_/g;

          my $dest_path = $c->config->{userdir}.'/'.$upload_basename;

          if (!-e $dest_path) {
              $upload->copy_to($dest_path);
              $c->log->debug("[$upload_basename] 업로드 완료");
          }
          else {
              $c->log->debug("[$upload_basename] 파일이 이미 존재합니다.");
          }
      }
  }

$upload 객체가 호출할 수 있는 메소드는
Catalyst::Request::Upload 문서에서 확인할 수 있습니다.
앞의 예제에서는 $upload->copy_to() 메소드를 사용해서
임시 디렉터리에 저장되어 있는 업로드 파일을 원하는 위치로 복사합니다.

정리하며

파일 업로드는 웹 응용을 제작할 때 난이도에 비해 손이 많이 가는 번거로운 부분입니다.
카탈리스트를 이용하면 업로드에 필요한 전처리 작업의 양이 대폭 줄어듭니다.
개발자는 단지 뷰의 HTML 양식에서 파일 업로드용 식별자를 만들어놓고
컨트롤러에서는 카탈리스트 문맥의 요청 객체의 upload
메소드($c->request->upload())를 이용해서 업로드 객체를 얻기만하면
업로드한 파일을 마음대로 다룰 수 있습니다.
물론 카탈리스트는 업로드 과정에서 임시 디렉터리에 파일을 보관하는 부분까지
처리하기 때문에 그 외 서버의 메모리 확보 문제 등 업로드 관련한 민감한 문제를
해결하기 위해서는 카탈리스트 뿐만 아니라 mod_perl 또는 fast_cgi와
관련한 연구가 더 필요할 것입니다.

Creative Commons License
This work, unless otherwise expressly stated, is licensed under a Creative Commons Attribution-Noncommercial-No Derivative Works 2.0 Korea License.
This entry was posted in Development and tagged , , , . Bookmark the permalink.

Comments are closed.