난이도 : 초급 Teodor ZlatanovNorthern Light, Inc
2001 년 1 월 01 일 2003 년 11 월 07 일 수정 Ted Zlatanov는 C와 Java 프로그램 개발자를 위해 Perl 5.6의 일부 특성을 설명한다. C와 Java 프로그래머들은 연산자의 중의성(operator ambiguity), 동일한 작업을 하는 다양한 방법들, 구두법(punctuation), 정규식(regular expression), 변수 메커니즘 등과 같이 친숙한 기능을 Perl에서 발견한다면 매우 놀랄 것이다. 결론부터 말하면 Perl은 누구에게나 친숙한 영역이 될 수 있으며, 어떤 점에 있어서는 C와 Java 프로그래머들에게 유용하게 사용될 수 있다.
Perl은 매우 간단한 코드를 사용하기 때문에 경험이 풍부한 프로그래머들 조차도 자주 당황하게 된다. 그러나 Perl이 풍부하고 강력한
언어이며 동일 작업 수행의 경우 1개 이상의 방법을 사용할 수 있도록 디자인된 언어라는 점을 감안하면 Perl의 구조, 특성 및 원리에
관한 혼란은 당연한 것일지도 모른다.
Perl5.6 특징과 C/C++/Java의 특징을 비교할 것이다. Larry Wall의 논문 "Natural Perl을 C/C+/Java로부터
가장 쉽게 구별할 수 있는 원리들을 참조할 수 있는 Language principles in Perl"에 기초하여 설명할 것이다(참고자료).
Perl 신택스의 정확한 역학(mechanics)은 "periodic perlsyn" 매뉴얼 페이지와 현재 Perl에 대한 최고 가이드인
Programming Perl(참고자료)을 참고하기 바란다.
인터프리터 역학
초보 Perl 프로그래머들은 컴파일 과정이 없다는 것을 곧바로 알아챌 수 있을 것이다. Perl 스크립트는 Perl 인터프리터에 의해 곧바로
실행된다(UNIX시스템에서는 "perl", DOS/Window 시스템에서는 "perl.exe", Mac OS 에서는 또 다른 이름을 갖고
있다.) 직접 시도해보라. Perl 인터프리터 이름을 입력하거나 Mac OS 시스템에서 Perl 인터프리터를 실행시킨다. 그 다음 곧바로
수식을 입력하여 테스트해 볼 수 있을 것이다. 대부분의 시스템들에서 end-of-file키 시퀀스(UNIX에서는 Ctrl-D)가 사용자
입력이 끝났음을 표시하는 데에 사용된다. UNIX시스템이라면 다음과 같이 "5+6"의 결과를 인쇄할 것이다:
가장 작은 프로그램으로 시작하기
> perl
(Perl is waiting for user input here, because no script name is given)
print 5+6
You press Control-D here
11
|
Perl이 한 줄의 스크립트를 실행하고 계산하여 결과값 "11"을 표시함을 알 수 있다.
Perl 인터프리터는 많은 옵션을 갖는다. 예를 들면 "e-"플래그는 명령행 인수들을 스크립트로서 실행하라고 명령할 것이다. 그래서 명령어
perl -e'print 5+6'(인쇄명령의 인용 부호에 주의)는 상기의 짧은 프로그램과 동일한 것이다. "-i"플래그는 말하자면 필터를
통해 파일들을 실행시키는 것과 같이, 파일들을 적절하게 편집한다. "-n"스위치와 "-p"스위치는 인터프리터가 프로그래머에 의해 지정된
입출력 필터처럼 작동하도록 한다. "-w"스위치는 경고옵션을 켜 놓는데, C/C++ 컴파일에서 "-Wall"스위치와 같은 것이다. 단,
Perl의 경우엔 프로그램 실행 동안에도 이 옵션이 유효하다.
속도 및 벤치마킹
사람들은 자주 Perl과 C 또는 C++를 비교하며, Perl이 빠르지 않다고 불평한다. 사실이다. 그러나 나는 C 나 C++가 더 빠를
것(모든 경우에 항상 그런 것은 아니므로)이라고 결론 내리기 전에 벤치마크 모듈 사용을 권한다(perldoc Benchmark). 또한
Perl은 C/C++코드와 라이브러리에 연결되는 장점이 있으며, sort나 print같은 Perl의 내장함수는 같은 역할을 하는 C의 함수만큼
빠르다. 다시 한번, 무엇이 더 좋을 지 결정하기 전에 벤치마크로 테스트해 보라
성급한 최적화가 모든 문제의 근원이다. 만약 Perl에서 프로토타입을 작성하고 그 다음 다른 언어로 프로그램을 만든다면 그것으로도 좋다.
프로토타입은 신속하게 개발되고 쉽게 폐기할 수 있다는 것을 뜻한다.
Java와 비교하여, Perl의 작동은 원할하지만 그래도 벤치마킹을 권한다. Perl과 달리 Java는 쓰레딩에 장점이 있으며, 따라서
Java에서 쓰레딩을 할 수 있는 알고리즘이라면 그렇게 하는 것이 더 효과적이다. 그러나 Perl의 Tk GUI 인터페이스 툴킷은 Java의
Swing GUI 라이브러리와 비교해도 손색이 없다. 또한 Java 코드는 항상 Perl 프로그램에 링크 될 수 있으며 그 반대도 가능하다.
그래서 때로는 두 언어의 장점을 모두 취할 수 있을 것이다.
예외 사항, 컴파일, 문서
Perl은 CAPN과 내장함수인 eval()을 통해 예외를 갖는다. Eval은 하나의 코드 블록이나 하나의 스트링을 마치 C++나 Java의
try/catch 블록 내부에서 실행 중인 프로그램의 일부분인 것처럼 여긴다.
Perl은 실행되기 전에 스크립트들을 컴파일하지만, C/C++/Java 프로그래머들이 추측하는 그런 방법은 아니다. 디자인과 효과에 있어서
Java 바이트-컴파일 과정과 매우 유사하다. "perldoc perlrun"과 "perldoc perlcc"에 컴파일에 관한 더 많은
정보가 있다.
문서는 POD 포맷으로 Perl 프로그램 내에 삽입된다. 이는 API 문서에 가장 적합한 Javadoc 포맷보다 더욱 일반적이고, 마크업이나
섹션들의 삽입이 허락되지 않는 C/C++/Java코멘트보다 더 명확하다.
Perl 프로그램은 C, C++, Java와 비교할 때 전혀 구조화된 프로그램이 아니다. 예를 들면, BEGIN 블록들은 처음에 실행될
수 있지만, 프로그램 전반에 걸쳐 여러 번 지정될 수 있다. 네임스페이스(namespace)는 어느 곳에서나 시작하고 끝날 수 있다. 정의,
변수, 함수의 몸체(body)부분 들도 어느 곳에서나 있을 수 있고, Perl은 이것을 수용하기 위해 최선을 다할 것이다.
엄격하지 않은 구조, 내장된 주석 및 총체적인 언어의 중의성 때문에 Perl을 편리하게 사용할 수 있게 되면 마치 영어로 편지를 쓰는
것과 흡사할 것이다.
언어의 중의성
Perl은 C/C++/Java 보다 중의성(ambiguity)에 대해 더욱 관용적이다. 예를 들면, 컴마(commas)는 구문들 뿐 아니라
함수 파라미터(parameters)들을 분리하는 데에도 사용된다:
설명어들과 함수 파라미터들의 구분(Separating statements or function parameters)
print 'Hello', ' ', 'there.', "\n"; # print "Hello there\n"
foreach (1..10)
{
my $i;
$i = $_ * 2, print "$i\n"; # print evens from 2 to 20
}
|
Perl은 중의성을 할 수 있는 한 제거하려고 한다 (이 점에서 Perl은 영어와 매우 비슷하다)..
Perl에서 다른 공통된 모호성은 한 변수가 종종 함축적으로 사용된다는 것이다. 예를 들면, "print"는 그 자체로서 $_변수의 내용을
인쇄한다. 이것은, $_ 변수가 대부분의 연산에서 디폴트 변수라는 것을 알면 이해된다. 다음의 예제를 보자:
함축적으로 사용되는 변수(Implicitly used variable)
$_ = "hello";
s/hello/hi/; # $_ is "hi" now
print; # prints "hi"
|
디폴트 변수들이 사용될 때, 코드가 얼마나 수월하게 되는 지에 주목해야 한다. 중의성 은 Perl과 영어에서 단축된 표현들을 가능하게
한다.
어떤 일을 하는 데에는 1가지 이상의 방법이 있다. (TMTOWD)
모든 언어가 관용어를 갖는다. C에서, for()루프는 주어진 수 만큼 반복하는 최상의 방법이다. Java에서 정적 메소드(static
method)는 인스턴스 명(Instance name) 대신 클래스 명(class name)으로 호출되어야 한다.
Perl은 어떤 작업을 할 경우 적어도 두 가지 이상의 방법을 갖는다. TMTOWTDI(There's more than one way
to do it)는 기본적인 언어 원리이다. Perl 커뮤니티에서 다양성은 허용될 뿐 아니라 권장사항 이다.
배열의 값들을 출력하는 예를 살펴보자. 모든 식들이 모두 같은 일을 한다.
배열(array)의 값 출력
print foreach @array;
foreach (@array) {print};
map {print} @array;
print @array;
|
위의 코드를 이해하는 것은 모든 Perl 코드를 이해하는 것과 마찬가지라 할 수 있다. 하나 이상의 방법이 존재하므로 어떤 것이 올바른
방법인지에 대해 고민하지 말라. 서로 다른 접근법에 대해 생각하다 보면, 이 언어에 대해 무언가 배울 수 있을 것이다.
그런데 하나 이상의 방법이 존재한다는 사실이 곧 잘못된 방법은 존재하지 않는다는 것을 뜻하는 것은 아니다. 올바른 코드를 작성할 때 보다
잘못된 코드를 작성하는 경우가 당연히 더 많다. 코드를 읽기 쉽게 만들고, 되도록 Perl의 내장함수를 사용하고, 명백한 작업이라도 기록하는
습관을 가져라.
정규식에 대한 혼란
정규식(regular expression)은 초보자에게는 두려운 것이다. 정규식(regular expression)들은 마치 문자와 느낌표로
혼합된 것처럼 보인다. 대부분의 사람들은 정규식(regular expression)이 실제로 몇 년 전에 전세계의 대학들에 컴퓨터 과학
프로그램들을 침투시켰던 Kalahari bushmen에 의해 발명되었다고 믿고 있다.
Perl 정규식은 쉘 스크립팅과 awk/grep 툴에서 물려받았다. 그러나 언어의 능력은 기존의 것들을 능가한다.
기초적인 정규식은 작성하기에는 쉽지만 읽기에는 다소 까다롭다. 예를 들면, "con\w+"는 "pro"나 "con"이 아니라 "contra"와
"contrary"에 매치된다. 그러나 Perl 5.6에서, 정규식은 마치 스테로이드처럼 복합적으로 변한다. 유니코드 문자 클래스 지시자들,
패턴 내부의 임의의 실행코드, 플래그 토글, 조건식 및 기타의 특징들이 정규식(regular expression) 엔진에 추가되었다.
초보자에게는 정규식의 기본 (참고자료의 "perldoc perlre" 참조)을 학습하고 당분간
고급기술을 멀리할 것을 권고한다. 정규식은 보통 공백 없이 쓰여지고 주석(실제 생산코드를 작성할 때 주석은 권장사항 이다)이 없기 때문에,
다른 Perl 코드 보다 읽기가 상당히 어렵다.
정규식(regular expression)은 외부 패키지로서 C/C++/Java에서 이용할 수 있지만, Perl은 오늘날 정규식(regular
expression)을 검색하고 대치하는 데에 이용할 수 있는 최상의 도구이다. 순수하게 C로 접근하는 것보다 느릴 수도 있지만, Perl은
순수히 정규식-관련 문제(regular expression-oriented problems)를 위한 첫번째 도구라고 생각해도 된다.
스칼라, 배열 , 해시
C, C++, Java의 변수들과 달리 Perl의 변수는 이름이 주어질 때 자동으로 인스턴스화되고 타입이 결정된다. 새로운 Perl 프로그래머들에게는
놀라울 수 있지만 일단 한번 이해하면 아주 유용한 것이다.
모든 생산코드에 "use strict" pragma를 사용할 것을 권한다. 무엇보다도, 변수들을 사용하기 전에 확실히 선언되야 한다.
이는 오타에 의한 오류들을 피하기위해서이다.
"use strict"를 사용하지 않았을 경우, 다음과 같은 문제점들을 만날 수 있다 :
일반적인 오타(A common typo )
$i = 5;
print $j; # print $i
|
프로그래머가 i를 입력하기 원했는데 오타로 j를 입력하였다. Perl은 적합 여부를 고려하고 $j의 값을 출력하는데 물론 여기엔 아무런
값도 없다. 때로는 자동-인스턴스화(auto-instantiation)는 유용하지만, 내 경험상 다른 사람과 공유하는 코드에만 "use
strict"를 꺼 놓는 것이 제일 좋다.
Perl 변수는 스칼라나 배열, 또는 해시(더 있지만 직접 만날 일이 거의 없을 것이다) 중의 하나이다. 또한 단지 스칼라 참조일 수도
있다. 스칼라 명은 "$"로 시작하고, 배열 명은 "@"로 시작하며, 해시 명은 "%"로 시작한다.
스칼라는 아주 일반적인 변수이다. 단일 값을 가지며, 그 값은 문자열이나 참조일 것이다. Perl은 필요하면 문자열을 숫자로 전환할 것이다.
이것은 새로운 Perl 프로그래머들에게 놀라운 일일 것이다. 다음 예제를 보자:
스칼라(Scalars)
$i = "hi there";
print 1+$i; # prints 1
|
스칼라 $i는 수치값 0을 갖는 "hi there"라는 문자열을 포함한다. 이리하여 1 + "hi there"는 1이 된다.
그것들을 스트링 대 숫자로서 생각하지 마라. 메모리에 단지 하나의 스칼라가 있으며, 하나의 스칼라 값을 갖는다. 그 값은 수의 문맥(추가)에서
하나의 숫자일 수 있거나, 스트링 문맥에서 하나의 스트링일 수 있다. 그러나 여전히 거기에는 하나의 값이 있다.
정의되지 않은 스칼라들은 "undef"값을 가진다. C/C++/Java에서 null값과 비교하는 것과 달리 Perl에서는 undef를
어떤 것과도 비교해서는 안된다. 대신, 다음과 같이 defined() 함수를 사용하라:
'defined()" 함수 사용
$i = "hi there";
print $i if defined $i; # prints "hi there"
undef $i; # set $i to be undef
print $i if defined $i; # prints nothing
|
배열은 스칼라의 리스트이다. 배열은 Java에서 백터 클래스들과 비슷하게 필요에 따라 자동으로 크기가 변경된다. C와 C++는 그와 동일한
기능을 내장하지 않고 있다. 대신 유사한 기능성을 제공하는 STL과 같은 많은 라이브러리들이 존재한다. 배열의 흥미로운 특성은 스칼라 문맥에서는
배열 요소의 개수를 산출한다는 것이다:
배열에 있는 요소들의 수
@a = ("hi there", "nowhere");
print scalar @a; # prints 2
push @a, "hello"; # add "hello" at the end
print scalar @a; # prints 3
|
해시(Hashes)는 배열과 비슷하지만 스칼라들이 위치상으로 정렬되지는 않는다. 그들은 또 다른 스칼라(독특한 키)에 의해 색인이 붙게
된다. 예를 들면, 색인이 붙은 이름들의 리스트가 해시 될 수 있다. 해시에서 키들의 삽입은 해시를 자동적으로 확장한다. 해시는 Java
HashMap과 Hashtable classes와 유사하다.
참조(reference)는 스칼라에 포함되며, 어떤 것이라도 가리킬 수 있다. 이리하여, 해시의 배열, 배열의 해시, 해시들의 해시,
배열의 배열(N차원 배열)을 갖는 것이 가능하다. 명시된 역참조(dereferencing)나 "->" 연산자에 의해 참조의 내용에 접근하는
몇 가지 방법이 있다. "perldoc perlref" 매뉴얼을 참조하기 바란다.
C와 C++는 단지 스칼라를 내장형으로만 가지고 있다. 따라서 프로그래머들이 STL과 같은 외부의 라이브러리의 사용을 포함하는 배열과
해시를 원할 때 많은 고생을 할 수밖에 없다.
Java는 해시와 배열에 상응하는 내장형을 가지고 있지만, 언어 고유에 존재하는 것은 아니다. 예를 들면, 해시의 키들을 통해 Perl에서
반복하기 보다 Java에서의 타이핑 양이 약 3배에 해당한다:
Java에서 해시 키의 반복
import java.util.Enumeration;
import java.util.Hashtable;
Hashtable hi = new Hashtable();
// fill in hi's values
// we can use an Iterator, still a lot of typing
for (Enumeration enum = hi.elements();
enum.hasMoreElements();)
{
Object o = enum.nextElement();
// do something with o
}
|
# note that this even includes the definition and initialization of
# the hash, and still is more compact than the Java code!
%hash = { a => "hi", b => "hello" };
foreach (values %hash)
{
# do something with $_
}
|
perl이 보완해야 할 점
Perl에는 C, C++와 Java에 있는 많은 특징들이 없다. 어쨌든 Perl은 다른 언어인 것이다. 이러한 특징들의 일부는, 예를 들면,
Java의 단일계승모델(single inheritance model)과 C++의 복수계승모델(multiple inheritance model)과
같이, 서로 직접적으로 충돌할 수 있다. 확실히 둘 다는 불가능하며, Perl은 고유의 방법으로 작업을 수행할 것이다.
Perl 프로그램들이 C라이브러리에 링크 될 수 있기 때문에(사실 이것이 Perl의 기능성이 구현된 방법이다), Perl이 링크를 통해
완수할 수 없는 C와 C++의 기능은 거의 없다. 여기서는 외부 링크 관련사항은 제외하고 언어에 내장되어 있는 기능성만을 얘기하겠다.
C, C++와 비교하면, Perl은 때때로 실행 속도가 느리다. 이것이 문제가 될 수 있지만, 프로그램을 잘 짜고 Perl에 내장된 기능성을
잘 활용하면 쉽게 극복할 수 있다.
Perl은 또한 C와 C++의 라이브러리를 직접적으로 사용할 수 없다. 상수와 기능성이 모듈들과 다양한 바인딩을 통해 Perl에 적절하게
구성되며, 이것이 개발을 지연시키고 실행속도를 느리게 할 수 있다. 최근에는 많은 양의 바인딩이 CPAN에서 릴리즈됨으로써 문제들이 많이
해결되었다.
기술적 측면에서 볼 때, Perl이 C와 C++처럼 쉽게 수용하기 어렵다. Perl은 젊은 언어이며, 인기가 급상승하지만 아직 보편적으로
사용되지는 않는다. Perl은 대부분의 UNIX시스템에 장착되며 Perl이 포팅되지 않은 운영체제는 거의 없다.
Perl은 단일 혹은 다중 상속(single or multiple inheritance hierarchies), 캡슐화(encapsulation)
그리고 다형성(polymorphism)을 지원하는데, 이는 외부모듈 또는 프로그래머의 승인 하에 이루어진다. 다른 말로 하면, 언어 자체는
프로그래머에게 엄격한 OOP 규칙을 강요하지 않는다. 규칙을 지키는 것은 프로그래머에게 달려있다. 이렇듯 프로그래머와 프로젝트의 성격에
의존하는 것은 장단점이 있다.
Perl의 쓰레드와 유니코드의 지원은 Java보다 현저하게 뒤쳐지며, C/C++보다는 다소 뒤진다. Java는 처음부터 쓰레드와 유니코드를
지원하도록 고안된 반면, C/C++는 Perl보다는 훨씬 오랜 시간이 걸린 후에 지원하게 된 것이다. Perl은 아직은 이러한 특징들을
더욱 필요로 한다. 쓰레드와 유니코드의 지원은 Perl에서는 여전히 실험적인 단계에 있지만 5.6 이후에 버전에서는 안정적으로 바뀔 것이다.
최고의 Perl
C/C++/Java 프로그래머들에게 있어서, Perl이 이러한 언어들보다 더 잘 할 수 있는 것들의 가치는 평가 할 수 없다. 예를 들면,
정규식(Regular expressions)은 Perl에서는 사소한 것이지만 C, C++ 혹은 Java에서는 하기가 아주 어려운 것이다.
내재하는 함수 변수, 느슨한 신택스, 자유로운 프로그램 구조들은 Perl의 매력이다.
Perl은 모두를 위한 언어가 아니다. 모든 결점을 수용할 준비가 될 때 Perl을 유용하게 사용할 수 있다. 단지 멋진 언어라는 이유만으로
Perl을 사용하지 말고, Perl이 더 나은 도구라고 느낄 때 사용하기 바란다. C, C++, Java가 더 좋은 경우에는 그 언어를
사용하면 된다. 유능한 프로그래머는 항상 바로 사용할 수 있는 몇 개의 도구를 준비한다.
Perl은 일부 부족한 부분이 있으며, 이는 열정적인 개발자들에 의해 보완되고 있다. 쓰레드, 유니코드 지원 혹은 엄격한 OOP의 준수할
필요에 따라, 특정 필요성을 수용할 수 있도록 Perl 이외의 다른 언어를 고려할 수도 있다.
Perl은 범용 언어이다. 많은 이질적인 모듈 사이에서 접착제 역할을 할 수 있는 유연한 언어이다. Perl은 어떤 절차 알고리즘이나
함수 알고리즘을 구현할 수 있다. 해시 요소들에서의 반복과 같은, 보다 적은 코드로 동일한 일이 가능케 하므로, Perl은 개발 주기를
현저하게 감소시킨다. 그러나 무엇보다도 중요한 것은 Perl은 재미있으며 배우는 재미가 있다.
참고자료
- developerWorks worldwide 사이트에서 이 기사에 관한 영어원문.
-
CPAN: Perl 모듈
- perldoc pages : perlrun, perlsyn, perlfaq, perlop, perlcc, perlre,
perlref 참조
- Larry Wall의 "Natural
Language Principles in Perl" 참조
-
Perl.com : Perl 정보에 대한 상세 자료
-
Programming Perl,
3rd Edition
: 5.005와 5.6.0으로 업데이트 된 가이드
-
Mastering Regular
Expressions: 정규식(Regula�1999년에 보스턴 대학에서
컴퓨터 공학을 전공했다. 졸업 후 Perl, Java, C, C++를 사용하여 프로그램을 개발하였다.
필자소개  | | Teodor Zlatanov has authored this article |
기사에 대한 평가
|