Perl 모듈

Perl 모듈 (패키지와 심볼 테이블)

이 문서는 Perl의 패키지(package), 네임스페이스(namespace), 심볼 테이블(symbol table), 그리고 클래스에 관한 몇몇 정보를 다뤄요. 새 모듈을 만드는 방법을 배우려면 perlnewmodperlmodstyle을 함께 보는 게 좋아요.

출처: Perl 공식 문서 - perlmod

본문

당신이 찾던 문서가 이것인가요? (Is this the document you were after?)

찾고 있는 정보를 담고 있을 수 있는 다른 문서들이 있어요.

이 문서 — Perl의 패키지, 네임스페이스, 클래스에 관한 몇몇 정보.

perlnewmod — 새 모듈을 만드는 튜토리얼.

perlmodstyle — 새 모듈을 만들기 위한 모범 사례.

패키지 (Packages)

모든 변수가 동적이고 하나의 전역 이름 공간을 공유해서 유지보수성 문제를 일으켰던 Perl 4와 달리, Perl 5는 코드가 다른 코드에 의해 변수가 짓밟히는 것을 보호하는 두 가지 메커니즘을 제공해요: mystate로 만든 어휘 스코프 변수, 그리고 vars 프래그마나 our 키워드로 노출되는 네임스페이스화된 전역 변수죠. 어떤 전역 변수든 네임스페이스의 일부로 간주되며 "정규화된 형태(fully qualified form)"로 접근할 수 있어요. 반대로 어떤 어휘 스코프 변수든 그 어휘 스코프의 일부로 간주되며 "정규화된 형태"가 없어요.

Perl에서 네임스페이스는 "패키지(package)"라고 불리며, package 선언은 컴파일러에게 our 변수와 정규화되지 않은 동적 이름을 어떤 네임스페이스에 접두사로 붙일지 알려 줘요. 이것은 우발적인 짓밟힘을 막아 줄 뿐 아니라, 다른 스코프나 패키지에서 선언되고 사용된 전역 동적 변수를 의도적으로 덮어쓰고 싶을 때 그렇게 할 수 있는 인터페이스도 제공해요.

package 선언의 스코프는 선언 자체부터 포함하는 블록, eval, 또는 파일의 끝 중 먼저 오는 곳까지예요 (my(), our(), state(), local() 연산자와, 변경될 수 있는 실험적 "참조 별칭"의 효과와 같은 스코프). 또는 다음 package 선언까지예요. 정규화되지 않은 동적 식별자는 이 네임스페이스에 있게 되는데, 아래에 설명된 것처럼 정규화되지 않으면 현재 패키지 대신 main 패키지를 기본으로 하는 아주 몇몇 식별자는 예외예요. package 문은 서브루틴 이름과 local()을 쓴 변수를 포함한 동적 전역 심볼에만 영향을 주고, my(), our(), state()로 만든 어휘 변수에는 영향을 주지 않아요.

보통 package 문은 do, require, use 연산자 중 하나로 프로그램에 포함된 파일의 첫 번째 선언이에요. 한 곳 이상에서 패키지로 전환할 수 있어요: package는 컴파일러가 그 블록의 나머지 또는 다음 package 문까지 동적 심볼에 사용할 심볼 테이블을 지정하는 것 외에는 아무 효과도 없어요. 다른 패키지의 변수와 파일핸들을 참조하려면 식별자 앞에 패키지 이름과 이중 콜론을 붙이면 돼요: $Package::Variable. 패키지 이름이 null이면 main 패키지로 간주돼요. 즉 $::sail$main::sail과 동등해요.

옛 패키지 구분자는 작은따옴표였지만, 이중 콜론이 이제 선호되는 구분자예요. 부분적으로는 사람이 읽기 더 좋고, 부분적으로는 emacs 매크로가 읽기 더 좋기 때문이에요. 또한 C++ 프로그래머가 뭘 하고 있는지 안다고 느끼게 해 주죠—구분자로 작은따옴표를 쓰던 것은 Ada 프로그래머가 뭘 하고 있는지 안다고 느끼게 하려는 것이었는데 말이죠. 옛 방식 문법은 역호환성을 위해 여전히 지원되므로, "This is $owner's house" 같은 문자열을 쓰려 하면 $owner::s, 즉 패키지 owner의 $s 변수에 접근하게 돼요. 아마 당신이 의도한 게 아닐 거예요. "This is ${owner}'s house"처럼 중괄호를 써서 구분하세요.

'를 패키지 구분자로 쓰는 것은 이렇게 비활성화할 수 있어요.

no feature 'apostrophe_as_package_separator';

그리고 use v5.42; 이상에서도 비활성화돼요.

패키지는 $OUTER::INNER::var처럼 패키지 구분자를 자체적으로 포함할 수 있어요. 하지만 이것은 이름 조회 순서에 대해 아무것도 암시하지 않아요. 상대 패키지(relative packages)는 없어요: 모든 심볼은 현재 패키지에 국한되거나, 바깥 패키지 이름부터 아래로 완전히 정규화되어야 해요. 예를 들어 패키지 OUTER 안 어디에도 $INNER::var$OUTER::INNER::var를 가리키는 곳은 없어요. INNER는 완전히 별개의 전역 패키지를 가리켜요. 패키지 이름을 계층으로 취급하는 관습은 아주 강하지만, 언어는 그것을 어떤 식으로도 강제하지 않아요.

글자(또는 밑줄)로 시작하는 식별자만 패키지의 심볼 테이블에 저장돼요. 다른 모든 심볼은 패키지 main에 유지되는데, $\_ 같은 모든 구두점 변수를 포함해서요. 추가로, 정규화되지 않으면 STDIN, STDOUT, STDERR, ARGV, ARGVOUT, ENV, INC, SIG 식별자는 내장 용도 외 다른 용도로 사용되더라도 패키지 main에 강제로 들어가요. m, s, y라는 패키지가 있다면 식별자의 정규화된 형태를 쓸 수 없어요. 그것이 대신 패턴 매치, 치환, 또는 음역(transliteration)으로 해석되기 때문이에요.

밑줄로 시작하는 변수는 한때 패키지 main으로 강제됐지만, 패키지 작성자가 앞 밑줄로 비공개 변수와 메서드 이름을 나타낼 수 있게 하는 게 더 유용하다고 판단했어요. 하지만 $_sub _ 같은 단일 _로 이름 지어진 변수와 함수는 여전히 패키지 main으로 강제돼요. perlvar의 "변수 이름의 문법"도 참고하세요.

eval된 문자열은 eval()이 컴파일된 패키지에서 컴파일돼요. (단, $SIG{}에 대한 할당은 지정된 시그널 핸들러가 main 패키지에 있다고 가정해요. 패키지에 시그널 핸들러를 두고 싶으면 시그널 핸들러 이름을 정규화하세요.) 예를 들어 Perl 라이브러리의 _perldb.pl_을 살펴보세요. 디버거가 디버깅 중인 프로그램의 변수와 간섭하지 않도록 처음에 DB 패키지로 전환해요. 하지만 여러 지점에서 main 패키지(또는 당신이 온 곳)의 문맥에서 다양한 표현식을 평가하기 위해 일시적으로 main 패키지로 다시 전환해요. perldebug를 보세요.

특별 심볼 __PACKAGE__는 현재 패키지를 담고 있지만, (쉽게는) 변수 이름을 구성하는 데 쓸 수 없어요. my($foo)가 패키지 변수 $foo를 숨긴 후에도, 어떤 패키지에 있는지 모른 채 ${__PACKAGE__.'::foo'}로 여전히 접근할 수 있어요.

my() 및 local()과 관련된 다른 스코프 문제는 perlsub을, 클로저에 관해서는 perlref를 보세요.

심볼 테이블 (Symbol Tables)

패키지의 심볼 테이블은 그 이름에 이중 콜론을 덧붙인 해시에 저장돼요. main 심볼 테이블의 이름은 그래서 %main::, 줄여서 %::예요. 마찬가지로 앞서 언급한 중첩 패키지의 심볼 테이블은 %OUTER::INNER::로 이름 지어져요.

해시의 각 항목의 값은 *name typeglob 표기법을 쓸 때 여러분이 참조하는 것입니다.

local *main::foo    = *main::bar;

이것으로 예를 들어 패키지의 모든 변수를 출력할 수 있어요. 표준이지만 구식인 dumpvar.pl 라이브러리와 CPAN 모듈 Devel::Symdump가 이것을 이용해요.

새 심볼 테이블 항목을 직접 만들거나, 이미 typeglob이 아닌 항목을 수정한 결과는 정의되지 않았으며 perl 릴리스 사이에 바뀔 수 있어요.

typeglob에 대한 할당은 별칭(aliasing) 연산을 수행해요. 즉,

*dick = *richard;

는 식별자 richard를 통해 접근 가능한 변수, 서브루틴, 포맷, 파일·디렉터리 핸들이 식별자 dick을 통해서도 접근 가능하게 해요. 특정 변수나 서브루틴만 별칭하고 싶으면 대신 참조를 할당하세요.

*dick = \$richard;

그러면 $richard와 $dick은 같은 변수가 되지만, @richard와 @dick은 별개의 배열로 남아요. 까다롭죠?

다음 두 문장 사이에는 미묘한 차이가 하나 있어요.

*foo = *bar;
*foo = \$bar;

*foo = *bar는 typeglob 자체를 동의어로 만드는 반면, *foo = \$bar는 두 개의 서로 다른 typeglob의 SCALAR 부분이 같은 스칼라 값을 가리키게 해요. 즉 다음 코드는

$bar = 1;
*foo = \$bar;       # Make $foo an alias for $bar

{
    local $bar = 2; # Restrict changes to block
    print $foo;     # Prints '1'!
}

'1'을 출력해요. 왜냐하면 $foo원래 $bar에 대한 참조를 담고 있기 때문이에요. local()이 치워 두었다가 블록이 끝날 때 복원될 그 참조 말이죠. 변수는 typeglob을 통해 접근되므로, *foo = *bar로 지역화할 수 있는 별칭을 만들 수 있어요. (하지만 그러면 별개의 @foo@bar를 가질 수 없다는 뜻이라는 점을 유의하세요.)

이 모든 것이 중요한 이유는 Exporter 모듈이 import/export 메커니즘으로 glob 별칭을 사용하기 때문이에요. 모듈에서 export된 변수를 제대로 지역화할 수 있는지 여부는 그것이 어떻게 export됐는지에 달려 있어요.

@EXPORT = qw($FOO); # Usual form, can't be localized
@EXPORT = qw(*FOO); # Can be localized

첫 번째 경우는 지역 값이 필요한 곳에 정규화된 이름($Package::FOO)을 쓰거나, 스크립트에서 *FOO = *Package::FOO라고 말해 재정의함으로써 해결할 수 있어요.

*x = \$y 메커니즘은 전체를 복사하기 싫을 때 값싼 참조를 서브루틴에 전달하고 반환하는 데 쓸 수 있어요. 이것은 동적 변수에 할당할 때만 동작하고, 어휘 변수에서는 동작하지 않아요.

    %some_hash = ();			# can't be my()
    *some_hash = fn( \%another_hash );
    sub fn {
	local *hashsym = shift;
	# now use %hashsym normally, and you
	# will affect the caller's %another_hash
	my %nhash = (); # do what you want
	return \%nhash;
    }

반환 시 그 참조는 \*some\_hash typeglob이 지정한 심볼 테이블의 해시 슬롯을 덮어써요. 변수를 명시적으로 역참조하는 것을 기억하고 싶지 않을 때 참조를 값싸게 주고받는 다소 까다로운 방법이에요.

심볼 테이블의 또 다른 용도는 "상수(constant)" 스칼라를 만드는 거예요.

*PI = \3.14159265358979;

이제 $PI를 변경할 수 없어요. 전체적으로 봐도 좋은 일이죠. 이것은 컴파일 시간에 최적화 대상이 되는 상수 서브루틴과는 다르지 않아요. 상수 서브루틴은 인자를 받지 않고 상수 표현식을 반환하도록 프로토타입된 것입니다. 자세한 내용은 perlsub을 보세요. use constant 프래그마가 이것들의 편리한 축약형이에요.

*foo{PACKAGE}*foo{NAME}을 말해서 \*foo 심볼 테이블 항목이 어떤 이름과 패키지에서 왔는지 알아낼 수 있어요. typeglob을 인자로 받는 서브루틴에서 유용할 수 있어요.

sub identify_typeglob {
    my $glob = shift;
    print 'You gave me ', *{$glob}{PACKAGE},
        '::', *{$glob}{NAME}, "\n";
}
identify_typeglob *foo;
identify_typeglob *bar::baz;

이것은 이렇게 출력해요.

You gave me main::foo
You gave me bar::baz

*foo{THING} 표기법은 \*foo의 개별 요소에 대한 참조를 얻는 데도 쓸 수 있어요. perlref를 보세요.

서브루틴 정의(그리고 선언도)는 그것이 심볼 테이블을 차지하는 패키지에 반드시 위치할 필요는 없어요. 서브루틴 이름을 명시적으로 정규화해서 패키지 밖에서 정의할 수 있어요.

package main;
sub Some_package::foo { ... }   # &foo defined in Some_package

이것은 컴파일 시간의 typeglob 할당의 축약형일 뿐이에요.

BEGIN { *Some_package::foo = sub { ... } }

그리고 이렇게 쓰는 것과는 같지 않아요.

    {
	package Some_package;
	sub foo { ... }
    }

처음 두 버전에서는 서브루틴의 본문이 어휘적으로 main 패키지에 있고, Some\_package에 있지 않아요. 그래서 이런 것이:

    package main;

    $Some_package::name = "fred";
    $main::name = "barney";

    sub Some_package::foo {
	print "in ", __PACKAGE__, ": \$name is '$name'\n";
    }

    Some_package::foo();

이렇게 출력해요.

in main: $name is 'barney'

이렇게가 아니라요.

in Some_package: $name is 'fred'

이것은 SUPER:: 수식어의 사용에도 함의를 가져요 (perlobj를 보세요).

BEGIN, UNITCHECK, CHECK, INIT, END

다섯 개의 특별히 이름 지어진 코드 블록이 실행 중인 Perl 프로그램의 시작과 끝에서 실행돼요. 이들은 BEGIN, UNITCHECK, CHECK, INIT, END 블록이에요.

이 코드 블록들은 서브루틴처럼 보이도록 sub를 접두사로 붙일 수 있어요 (좋은 스타일로 여겨지진 않지만). 이 코드 블록들은 (겉보기와 달리) 이름 있는 서브루틴으로 실제로는 존재하지 않는다는 점을 알아 두어야 해요. 이것을 드러내는 것은 프로그램에 이 코드 블록이 하나 이상 있을 수 있고, 적절한 순간에 모두 실행된다는 사실이에요. 그래서 이 코드 블록들을 이름으로 실행할 수는 없어요.

BEGIN 코드 블록은 가능한 한 빨리, 즉 완전히 정의되는 순간, 포함 파일(문자열)의 나머지가 파싱되기 전에도 실행돼요. 파일(eval된 문자열) 안에 여러 BEGIN 블록이 있을 수 있고, 정의된 순서대로 실행돼요. BEGIN 코드 블록은 즉시 실행되므로, 컴파일과 실행 시간의 나머지에 보이도록 다른 파일에서 서브루틴 정의 같은 것을 끌어올 수 있어요. BEGIN이 실행되면 즉시 정의되지 않게 되고, 그것이 사용한 어떤 코드든 Perl의 메모리 풀로 반환돼요.

END 코드 블록은 가능한 한 늦게, 즉 perl이 프로그램 실행을 마친 직후, 인터프리터가 종료되기 직전에 실행돼요. die() 함수 때문에 종료되는 경우에도 그래요. (단, exec로 다른 프로그램으로 변형되거나 시그널로 산산조각나는 경우는 아니에요—그건 스스로(할 수 있다면) 잡아야 해요.) 파일 안에 여러 END 블록이 있을 수 있는데, 정의 역순으로 실행돼요: 즉 마지막에 들어온 것이 먼저 나가는 후입선출(LIFO)이죠. END 블록은 -c 스위치로 perl을 실행하거나 컴파일이 실패하면 실행되지 않아요.

END 코드 블록은 문자열 eval()의 끝에서는 실행되지 _않는다_는 점을 유의하세요: 문자열 eval()에서 생성된 END 코드 블록이 있다면, 그 패키지의 다른 END 코드 블록처럼 LIFO 순서로 인터프리터가 종료되기 직전에 실행돼요.

END 코드 블록 안에서 $?는 프로그램이 exit()에 전달할 값을 담고 있어요. 프로그램의 종료 값을 바꾸기 위해 $?를 수정할 수 있어요. (예를 들어 system으로 뭔가를 실행해서) 우연히 $?를 바꾸는 것을 조심하세요.

END 블록 안에서 ${^GLOBAL_PHASE}의 값은 "END"가 돼요.

END 블록과 비슷한 것은 defer 블록인데, 프로그램 전체가 아니라 개별 블록 스코프의 수명에 대해 동작해요. perlsyn의 "defer"에 문서화되어 있어요.

UNITCHECK, CHECK, INIT 코드 블록은 main 프로그램의 컴파일 단계와 실행 단계 사이의 전환을 포착하는 데 유용해요.

UNITCHECK 블록은 그것들을 정의한 단위(unit)가 컴파일된 직후 실행돼요. main 프로그램 파일과 그것이 로드하는 각 모듈은 컴파일 단위인데, 문자열 eval, 정규식에서 (?{ }) 구성으로 컴파일된 실행 시간 코드, do FILE 호출, require FILE, 명령줄에서 -e 스위치 뒤의 코드도 그래요.

BEGINUNITCHECK 블록은 인터프리터의 단계와 직접 관련되지 않아요. 어떤 단계에서든 생성되고 실행될 수 있어요.

CHECK 코드 블록은 초기 Perl 컴파일 단계가 끝나고 실행 시간이 시작되기 직전에, LIFO 순서로 실행돼요. CHECK 코드 블록은 Perl 컴파일러 스위트에서 프로그램의 컴파일된 상태를 저장하는 데 사용돼요.

CHECK 블록 안에서 ${^GLOBAL_PHASE}의 값은 "CHECK"가 돼요.

INIT 블록은 Perl 실행 시간이 실행을 시작하기 직전에 "선입선출"(FIFO) 순서로 실행돼요.

INIT 블록 안에서 ${^GLOBAL_PHASE}의 값은 "INIT"가 돼요.

require, 문자열 do, 문자열 eval로 컴파일된 코드의 CHECKINIT 블록은 main 컴파일 단계가 끝난 뒤에 있으면 실행되지 않아요. 이것은 런타임에 코드를 로드하기 위해 그 함수들을 쓰는 mod\_perl과 다른 영구적 환경에서 문제가 될 수 있어요.

-n-p 스위치를 쓸 때, BEGINENDawk에서처럼, 축퇴된 경우로 동작해요. 컴파일 전용 문법 검사인 -c 스위치를 쓰면 BEGINCHECK 블록 둘 다 실행돼요. main 코드는 그렇지 않지만요.

begincheck 프로그램이 결국 모든 것을 명확히 해 줘요.

#!/usr/bin/perl

# begincheck

print         "10. Ordinary code runs at runtime.\n";

END { print   "16.   So this is the end of the tale.\n" }
INIT { print  " 7. INIT blocks run FIFO just before runtime.\n" }
UNITCHECK {
  print       " 4.   And therefore before any CHECK blocks.\n"
}
CHECK { print " 6.   So this is the sixth line.\n" }

print         "11.   It runs in order, of course.\n";

BEGIN { print " 1. BEGIN blocks run FIFO during compilation.\n" }
END { print   "15.   Read perlmod for the rest of the story.\n" }
CHECK { print " 5. CHECK blocks run LIFO after all compilation.\n" }
INIT { print  " 8.   Run this again, using Perl's -c switch.\n" }

print         "12.   This is anti-obfuscated code.\n";

END { print   "14. END blocks run LIFO at quitting time.\n" }
BEGIN { print " 2.   So this line comes out second.\n" }
UNITCHECK {
 print " 3. UNITCHECK blocks run LIFO after each file is compiled.\n"
}
INIT { print  " 9.   You'll see the difference right away.\n" }

print         "13.   It only _looks_ like it should be confusing.\n";

__END__

Perl 클래스 (Perl Classes)

Perl에는 안정적인 클래스 문법이 없지만, 메서드로 동작할 서브루틴을 제공하면 패키지가 클래스로 기능할 수 있어요. 그런 패키지는 전역 @ISA 배열(패키지 전역이어야 하지, 어휘 변수가 아니어야 해요)에 다른 패키지 이름을 나열해 다른 클래스(패키지)로부터 메서드 중 일부를 파생시킬 수도 있어요.

패키지가 클래스로 기능하는 것에 대한 더 자세한 내용은 perlootutperlobj을 보세요. 아직 안정화되지 않은 클래스 문법에 대해서는 perlclass을 보세요.

Perl 모듈 (Perl Modules)

모듈은 라이브러리 파일에 담긴 관련 함수 집합일 뿐이에요. 즉 파일과 같은 이름을 가진 Perl 패키지죠. 다른 모듈이나 프로그램이 재사용할 수 있도록 특별히 설계되었어요. 사용하는 어떤 패키지의 심볼 테이블로 자체 심볼 중 일부를 export하는 메커니즘을 제공해서, 또는 클래스 정의로 기능해서 명시적으로 아무것도 export하지 않고도 클래스와 그 객체에 대한 메서드 호출을 통해 그 의미를 암시적으로 제공해서 그렇게 할 수 있어요. 또는 둘 다 조금씩 할 수도 있어요.

예를 들어 Some::Module이라는 전통적이고 비-OO 모듈을 시작하려면 _Some/Module.pm_이라는 파일을 만들고 이 템플릿으로 시작하세요.

package Some::Module;  # assumes Some/Module.pm

use v5.36;

# Get the import method from Exporter to export functions and
# variables
use Exporter 5.57 'import';

# set the version for version checking
our $VERSION     = '1.00';

# Functions and variables which are exported by default
our @EXPORT      = qw(func1 func2);

# Functions and variables which can be optionally exported
our @EXPORT_OK   = qw($Var1 %Hashit func3);

# exported package globals go here
our $Var1    = '';
our %Hashit  = ();

# non-exported package globals go here
# (they are still accessible as $Some::Module::stuff)
our @more    = ();
our $stuff   = '';

# file-private lexicals go here, before any functions which use them
my $priv_var    = '';
my %secret_hash = ();

# here's a file-private function as a closure,
# callable as $priv_func->();
my $priv_func = sub {
    ...
};

# make all your functions, whether exported or not;
# remember to put something interesting in the {} stubs
sub func1      { ... }
sub func2      { ... }

# this one isn't always exported, but could be called directly
# as Some::Module::func3()
sub func3      { ... }

END { ... }       # module clean-up code here (global destructor)

1;  # don't forget to return a true value from the file

그런 다음 함수에서 자격 없이 변수를 선언하고 사용하세요. 모듈 생성의 메커니즘과 스타일 문제에 대한 자세한 내용은 Exporterperlmodlib을 보세요.

Perl 모듈은 프로그램에 이렇게 말해서 포함돼요.

use Module;

또는

use Module LIST;

이것은 정확히 다음과 동등해요.

BEGIN { require 'Module.pm'; 'Module'->import; }

또는

BEGIN { require 'Module.pm'; 'Module'->import( LIST ); }

특별한 경우로

use Module ();

는 정확히 다음과 동등해요.

BEGIN { require 'Module.pm'; }

모든 Perl 모듈 파일은 .pm 확장자를 가져요. use 연산자가 이것을 가정하므로 " Module.pm"을 따옴표 안에 풀어 쓸 필요가 없어요. 이것은 또한 새 모듈을 옛 _.pl_과 .ph 파일과 구분하는 데 도움을 줘요. 모듈 이름은 프래그마로 기능하지 않는 한 대문자로 시작해요. 프래그마는 사실상 컴파일러 지시문이며, 때로 "pragmatic modules"(고전주의자라면 "pragmata"라)고 불려요.

다음 두 문장은:

require SomeModule;
require "SomeModule.pm";

두 가지 방식에서 서로 달라요. 첫 번째 경우, Some::Module 같은 모듈 이름의 이중 콜론은 시스템의 디렉터리 구분자, 보통 "/"로 변환돼요. 두 번째 경우는 그렇지 않으며 문자 그대로 지정해야 해요. 또 다른 차이는 첫 번째 require를 보면 컴파일러는 $ob = purge SomeModule 같은 "SomeModule"을 수반하는 간접 객체 표기법의 사용이 함수 호출이 아니라 메서드 호출임을 알게 된다는 거예요. (네, 이것이 정말 차이를 만들 수 있어요.)

use 문은 BEGIN 블록을 암시하므로, 의미의 import는 use 문이 컴파일되는 즉시, 파일의 나머지가 컴파일되기 전에 일어나요. 이것이 프래그마 메커니즘으로 기능할 수 있는 방법이고, 모듈이 현재 파일의 나머지에서 리스트 또는 단항 연산자로 보이는 서브루틴을 선언할 수 있는 방법이에요. use 대신 require를 쓰면 이것이 동작하지 않아요. require로는 이런 문제에 빠질 수 있어요.

require Cwd;		# make Cwd:: accessible
$here = Cwd::getcwd();

use Cwd;			# import names from Cwd::
$here = getcwd();

require Cwd;	    	# make Cwd:: accessible
$here = getcwd(); 		# oops! no main::getcwd()

일반적으로 require Module보다 use Module ()을 권장해요. 컴파일 시간에, 프로그램 실행 중간이 아니라, 모듈 가용성을 결정하니까요. 예외는 두 모듈이 서로 use하려 하면서 각각 다른 모듈의 함수도 호출하는 경우예요. 그런 경우엔 require를 쓰기가 쉽죠.

Perl 패키지는 다른 패키지 이름 안에 중첩될 수 있으므로 ::를 포함하는 패키지 이름을 가질 수 있어요. 하지만 그 패키지 이름을 파일 이름으로 직접 쓰면 일부 시스템에서 다루기 힘들거나 불가능한 파일 이름이 돼요. 그래서 모듈 이름이, 말하자면 Text::Soundex라면, 그 정의는 실제로 라이브러리 파일 _Text/Soundex.pm_에서 발견돼요.

Perl 모듈은 항상 .pm 파일을 가지지만, 모듈과 연관된 동적 링크 실행 파일(종종 _.so_로 끝나는)이나 autoload된 서브루틴 정의(종종 _.al_로 끝나는)가 있을 수도 있어요. 그렇다면 이것들은 모듈 사용자에게 완전히 투명해요. 추가 기능을 로드(또는 autoload되도록 마련)하는 것은 .pm 파일의 책임이에요. 예를 들어 POSIX 모듈은 동적 로드와 autoload 둘 다를 우연히 수행하지만, 사용자는 그저 use POSIX라고 해서 전부 얻을 수 있어요.

모듈을 스레드 안전하게 만들기 (Making your module threadsafe)

Perl은 인터프리터 스레드(ithreads)라 불리는 한 종류의 스레드를 지원해요. 이 스레드는 명시적으로나 암시적으로 쓸 수 있어요.

Ithreads는 데이터 트리를 복제해서 서로 다른 스레드 사이에서 데이터가 공유되지 않도록 동작해요. 이 스레드는 threads 모듈을 쓰거나 win32에서 fork()(가짜 fork() 지원)를 해서 쓸 수 있어요. 스레드가 복제될 때 모든 Perl 데이터는 복제되지만, 비-Perl 데이터는 자동으로 복제될 수 없어요. 5.8.0 이후의 Perl은 CLONE 특별 서브루틴을 지원해요. CLONE에서 필요한 어떤 것이든 할 수 있는데, 예를 들어 필요하다면 비-Perl 데이터의 복제를 처리하는 것도 그렇죠. CLONE은 그것을 정의한(또는 상속한) 모든 패키지에 대해 클래스 메서드로 한 번 호출돼요. 새 스레드의 문맥에서 호출되므로 모든 수정이 새 영역에서 이루어져요. 현재 CLONE은 invocant 패키지 이름 외에는 매개변수 없이 호출되지만, 코드는 이것이 불변이라고 가정해선 안 돼요. 향후 복제 상태에 대한 더 많은 정보를 주는 추가 매개변수가 전달될 가능성이 높으니까요.

모든 객체를 CLONE하려면 패키지별로 그것들을 추적해야 해요. 이것은 해시와 Scalar::Util::weaken()으로 간단히 할 수 있어요.

5.8.7 이후의 Perl은 CLONE_SKIP 특별 서브루틴을 지원해요. CLONE과 마찬가지로 CLONE_SKIP도 패키지당 한 번 호출돼요. 하지만 복제가 시작되기 직전에, 부모 스레드의 문맥에서 호출돼요. 참 값을 반환하면 그 클래스의 객체는 복제되지 않아요. 오히려 bless되지 않은 undef 값으로 복사되죠. 예를 들어 부모에 단일 blessed 해시에 대한 두 참조가 있으면, 자식에는 단일 정의되지 않은 스칼라 값에 대한 두 참조가 대신 있어요. 이것은 모듈을 스레드 안전하게 만드는 간단한 메커니즘을 제공해요. 그냥 클래스 맨 위에 sub CLONE_SKIP { 1 }을 추가하면 DESTROY()가 이제 객체마다 한 번만 호출돼요. 물론 자식 스레드가 객체를 사용해야 한다면 더 정교한 접근이 필요해요.

CLONE과 마찬가지로 CLONE_SKIP도 현재 invocant 패키지 이름 외에는 매개변수 없이 호출되지만, 그것은 바뀔 수 있어요. 비슷하게, 향후 확장을 허용하기 위해 반환 값은 단일 0 또는 1 값이어야 해요.

더 알아보기 (SEE ALSO)

Perl 모듈과 클래스 구축과 관련된 일반 스타일 문제는 perlmodlib을, 표준 라이브러리와 CPAN 설명도 거기서 보세요. Perl의 표준 import/export 메커니즘이 어떻게 동작하는지는 Exporter를, 클래스 생성에 대한 깊이 있는 정보는 perlootutperlobj을, 객체에 대한 하드코어 레퍼런스 문서는 perlobj을, 함수와 스코프에 대한 설명은 perlsub을, 확장 모듈 작성에 대한 더 많은 정보는 perlxstutperlguts을 보세요.

더 알아보기