주의: [설치하지 않은 의존 모듈 적재시 발생하는 오류 회피하기]의 가장 최근 판은 이곳에서 확인할 수 있습니다.
시작하며
회사에서 업무용으로 작성하는 펄 스크립트의 경우 개인적으로 작성하는 스크립트에
비해 개인의 취향을 배제하는 것은 물론 비교적 엄격하게 만드는 편입니다.
이것은 어찌보면 조금 괴로운 일인데, 예를 들면 즐겨쓰는 단축 표현은
최대한 자제하는 편이며, 조금 과하다 싶을 정도로 주석을 달고 있습니다.
또한 의존 모듈을 최대한 줄이기 위해 기본 펄 배포판에 들어가있지 않은
CPAN 모듈은 최대한 쓰지않고, 가능한 하나의 파일로 작성해서 배포의
용이성을 살리는 것에 중점을 두고 있습니다.
하지만 CPAN 모듈을 전혀 사용하지 않는 것은 어려운 상황이 많습니다.
이런 경우 어쩔수 없이 CPAN 모듈을 사용하는데 문제는 펄을 즐겨 사용하지 않는
팀원들의 경우 해당 스크립트를 실행할 때 의존 모듈 적재 오류가 발생해
실행이 불가능한 경우가 종종 생긴다는 것입니다.
익숙한 사람이라면 오류 메시지를 확인해서 해당 펄 모듈을 cpan 쉘을 이용해
설치하겠지만 그렇지 않은 경우 모듈 적재 실패 메시지를 보고 모듈 설치를
해야겠다고 생각하는 일은 어려울 수 있습니다.
또한 cpan 쉘을 이용해서 모듈을 설치하는 방법을 모를 수도 있습니다.
이런 상황을 고려해서 CPAN 모듈을 의존하는 스크립트를 작성할 때
해당 모듈을 설치하지 않아 발생하는 오류를 회피하는 방법을 소개합니다.
이 방법을 이용하면 사용자는 펄이 뿌려주는 오류 메시지보다 훨씬 더 자세하고
친절한 메시지를 보고 문제를 쉽게 해결할 수 있을 것입니다.
구현
다음은 코드 예제입니다:
#!/usr/bin/perl
#
# EMSTONE DVR Camera Library - Test Program (Download)
#
# Copyright (c) 2009 EMSTONE, All rights reserved.
#
BEGIN {
eval q{
use DateTime;
use Net::SSH::Expect;
use Net::SCP::Expect;
};
die <<"END_README" if $@;
Error:
$@
#
# README:
#
# To run this script, install following modules first:
#
# * DateTime
# * Net::SSH::Expect
# * Net::SCP::Expect
#
# You can install requiremnt modules with following commands:
#
# $ sudo cpan DateTime
# $ sudo cpan Net::SSH::Expect
# $ sudo cpan Net::SCP::Expect
#
# or
#
# $ sudo cpan DateTime Net::SSH::Expect Net::SCP::Expect
#
END_README
}
use strict;
use warnings;
use DateTime;
use Getopt::Std;
use File::Basename;
use Net::SSH::Expect;
use Net::SCP::Expect;
#
# ... rest of the code ...
#
분석
상기 코드에서 사용한 기법은 크게 네 가지 입니다.
- BEGIN 블록
- eval 함수
- here-document 문자열
- 추가적인 use 사용
BEGIN 블록
BEGIN 은 UNITCHECK 와 CHECK, INIT, END 와 함께 펄 프로그램의 실행 전
또는 실행 후에 동작하는 이름있는 블록(named block)입니다.
BEGIN 코드 블록은 프로그램 안에서 여러번 사용할 수 있으며 프로그램의
첫 머리부터 발견하는 즉시 블록 안의 코드를 실행합니다.
프로그램 시작 전에 전처리의 개념으로써 미리 처리할 부분이 있다면
BEGIN 블록을 사용하면 쉽게 구현할 수 있습니다.
자세한 내용은 perlmod 문서를 참고하세요.
eval 함수
eval은 현재 실행중인 펄 프로그램과는 별개의 실행 문맥을 가지도록
하면서 코드를 수행하는 와중에 eval 내의 코드를 실행하기 위해 사용합니다.
eval을 사용하면 프로그램을 종료시키는 오류가 발생하더라도 현재
실행중인 프로그램을 종료시키지 않으며 별도의 문맥으로 실행하는 코드를
종료시키고 에러 메시지를 $@ 변수에 저장합니다.
따라서 예외 처리라던가 프로그램 내의 프로그램 실행 등의 동작을 수행할 때
매우 유용하게 사용할 수 있습니다.
eval 함수의 원형은 다음과 같습니다:
eval EXPR
eval BLOCK
두 가지 호출 방식은 기능 면에서는 비슷하나
펄이 파싱을 언제, 어떻게 하느냐? 에 따라 미묘한 차이가 있습니다.
효율적인 측면에서는 BLOCK 구문을 사용하는 편이,
컴파일 시간의 오류를 피한다는 측면에서는 EXPR 구문을 사용하는 편이 유리합니다.
자세한 내용은 perlfunc의 eval 함수 설명 문서를 참고하세요.
here-document 문자열
here-document 기법은 많은 양의 문자열을 한 번에 처리할 때 유용한 기법입니다.
대부분의 쉘이 가지고 있는 기능인데 쉘의 특징을 계승한 펄 역시 가지고 있으며,
쉘에 비해 다양한 보간(interpolation) 방식을 지원하며,
후처리 역시 가능하기 때문에 기능면에서는 훨씬 뛰어납니다.
here-document 를 사용하지 않을 경우, 인용부호를 남발해야하는 경우가 있는데,
이럴 때 적절하게 사용하면 코드의 가독성을 높일 수 있습니다.
하지만 here-document를 코드 중간에 너무 남발할 경우 오히려 들여쓰기가
시각적으로 망가져서 가독성을 오히려 떨어뜨릴 수 있으니 주의해야 합니다.
자세한 내용은 perlop와 perldata 문서를 참고하세요.
추가적인 use 사용
대부분의 경우 모듈을 적재하기 위해 use 함수를 사용합니다.
use로 모듈을 적재하면 현재 패키지의 이름 공간에서
해당 모듈의 함수나 변수를 사용할 수 있게 도와주며,
특별히 이름 공간에 넣는 함수나 변수가 없다 할지라도
모듈을 사용하기 위해서는 반드시 use나 require 등을 이용해서
모듈을 적재해야 합니다.
require 보다 use를 사용하는 것이 조금 더 편리한데
만약 자신이 require 와 use 의 차이를 정확하게 모른다면
use를 선택하는 것이 대부분의 경우 올바른 선택입니다.
use를 사용하는 것은 다음 코드와 동일합니다:
BEGIN { require Module; Module->import( LIST ); }
앞의 예제에서는 비록 BEGIN 과 eval의 조합에서 use를 이용해
모듈을 적재하기 때문에 아래 부분에서 다시 use를 사용할 필요가 없지만
가독성이라는 측면과, 모듈의 의존성 점검시 정확한 결과를 보여주기 위해
한번 더 use를 사용합니다.
이 때 모듈 적재를 중복해서 시도했다고 할지라도
적재한 모듈의 경우 다시 적재하지 않으므로 성능상의 저하는 없습니다.
use 함수의 원형은 다음과 같습니다:
use Module VERSION LIST
use Module VERSION
use Module LIST
use Module
use VERSION
자세한 내용은 perlfunc의 use 함수 설명 문서를 참고하세요.
정리하며
펄 프로그램의 실행을 시작하기 전 의존 모듈을 적재 가능 여부를 점검해서
조건을 충족시키지 못할 경우 사용자에게 펄의 오류 메시지가 아닌
이 프로그램을 실행하기 위해 다음으로 취해야 할 행동을 제시함으로써
사용자 친화적인 프로그램을 작성할 수 있습니다.
대부분의 경우 이런 기법은 프로그램의 기능적인 측면에서 영향을
미치는 요소는 아니나 오히려 펄 프로그래머 입장에서는 초급보다
한 단계 높은 내용이므로 펄을 더욱 잘 활용하기 위해서는 숙지해야할 내용입니다.
또한 회사에서와 같이 여러 사람과 협업을 하는 경우 펄을 잘 모르는 개발자나
사용자를 감안해서 사용자 친화적인 기능을 추가한다면 프로그램의 완성도를
한 단계 더 끌어올릴 수 있습니다.

This work, unless otherwise expressly stated, is licensed under a Creative Commons Attribution-Noncommercial-No Derivative Works 2.0 Korea License.