모든 프로그램(디렉토리 목록 출력 프로그램부터 웹 브라우저에 이르기 까지)이 갖추어야 할 첫째 조건 중 하나는 사용자의 구성(설정)이 가능하도록 하는 것이다. 파일 기반의 구성과 명령 행 옵션의 조합은 사용자 구성에 있어서 오랫 동안 유연성있게 사용되어 온 솔루션이다. Perl 프로그램은 대개 이러한 접근법을 채택하고 때로 구성 파일과 명령 행 파싱 루틴(command-line parsing routines)을 사용한다.
이 글에서 사용할 명령 행 파싱(command-line parsing)은 약간 복잡하다. 만약 간단한 인자보다 고수준의 파싱을 사용할 것이라면 나중의 혼돈을 피하기 위해 Parse::RecDescent(또는 같은 역할의 파싱 모듈) 사용을 권장한다. 복잡한 명령 행 파싱에 대한 논의는 Perl 프로그램 관련 자료인 이전 글(US)을 참고한다.
Perl 5.005 또는 그 이상의 버전과 CPAN AppConfig 모듈이 설치되어 있는지 확인하라. 또한 Persistent:MySQL 이나 사용하고 있는 데이터베이스에 맞는 Persistent 클래스가 필요하다. CPAN을 참고한다. (참고자료)
올바른 툴을 사용할 경우, 이론적으로 모든 사용자가 구성 파서를 구축할 수 있다. 예를 들면 Perl Cookbook은 빠르게 시작할 수 있는 구현 방법을 보여준다. 이런 종류의 구현을 할 경우, 구성 파일 파서 작성이 매우 어려울 수 있다.
이런 방식의 프로젝트는 다음과 같은 실질적인 복잡한 문제를 발생시킬 수 있다.:
- 구성 파일에서 공백 행과 주석
- 에러 행(철자가 틀린 키워드 등) 및 중요도의 의문 사항
- 다양한 데이터 구조(부울, 스칼라, 배열, 해시)가 필요할 때 자체 파서 작성
- 다중 구성 파일
- 변수 디폴트
- 명령 행 옵션과 파일 구성의 통합 및 상호작용 제어
- 다른 DIY 구성 파일 형식에서 사용자 교육 (예: 행에 '=' 이 없으면, 자체 작동할 것이다. 주석은 '#'으로 시작한다. 그런데 주석 자체에서 그렇게 시작해야 한다. 키워드는 대문자, 값은 소문자를 사용한다는 점을 주의한다. 필수 키워드들도 있다.)
- 모듈 재사용 대신 버그 위험이 있는 구성 코드 복사 또는 다시 쓰기
- 흔히 사용하는 키워드의 해시 대신 일관성 있는 인터페이스를 포함한 객체 구성 만들기
AppConfig 이 모든 것을 처리한다. DIY는 사용하지 않는 것이 좋을 것 같다.
Andy Wardley의 AppConfig CPAN 모듈이 위에 기술된 모든 문제 해결에 도움을 주지만, 만병통치약은 아니다. 때때로 AppConfig사용을 위해 재작성이 필요하다.
DIY 또는 AppConfig의 사용이 불확실하면 사용자 경험을 토대로 하여 작성하는 것에 따라 결정해야 한다. 그러나 AppConfig 보다 DIY 접근 방법이 더 나은 경우는 별로 많지 않다고 생각한다.
AppConfig로 무엇을 할 수 있는지 차근차근 설명하겠다. (이전 섹션에서 언급되었던 문제들이다):
- 구성 파일에서 공백 행과 주석 AppConfig는 공백 행과 주석을 알 수 있으며, 그것들을 무시한다.
- 오자의 에러 행 중에서 중요한 것과 무시해도 좋은 것 잘못된 세팅을 무시하거나 또는 프로그램을 취소하도록 AppConfig의 민감도를 설정할 수 있다. 철자를 대체하는 것이 가능한 경우에는 키워드에 별칭을 줄 수 있다.
- 다양한 데이터 구조(부울, 스칼라, 배열, 해시)가 필요할 때 자체 파서 작성: AppConfig는 이 모든 데이터 구조를 처리하지만, 중첩 처리는 하지 않는다. 해시 또는 배열을 중첩 시킬 필요가 있으면. DIY로 하거나 AppConfig를 보조해야 한다.
- 다중 구성 파일 AppConfig는 각 구성 파일의 설정을 차례로 로딩하면서 필요한 만큼의 다수의 구성 파일을 처리한다. 또한 스택의 하단에 삽입된 값이 상단까지 도달하지 않도록 배열 및 해시를 재설정하여 AppConfig를 보조할 수 있다.
- 변수 디폴트: AppConfig은 변수 디폴트를 제공한다. "-variable" 신텍스는 구성 파일에서 변수를 디폴트 상태로 리셋한다.
- 명령 행 옵션과 파일 구성의 통합 AppConfig는 Getopt::Std 및 Getopt::Long 명령 행 옵션 파싱을 모두 지원한다. 파싱은 구성 파일 읽기 전후에 수행될 수 있다.
- 다른 DIY 구성 파일 형식으로 사용자 교육: AppConfig는 유연성있는 표준 포맷을 사용한다. "KEYWORD value" 이나 "KEYWORD=value"은 모두 스칼라에 적용된다. 배열을 추가할 수 있어서, "ARR=1" 다음에 "ARR=2"를 하면 1과 2의 요소를 가진 ARR 배열을 생성한다. 또한 부울 옵션을 "bool", "nobool", "!bool", "bool on", "bool off", "bool yes"("bool no"는 유효하지 않음), "bool 1", "bool=0"(악명 높은 상징성 논리 창시 자인 Dr. George Boole은 안심할 수 있었을 것이다-참고자료 참조)으로 지정할 수 있다. 해시 옵션은 "KEYWORD PARAMETER=value"로 지정된다. 여기서 value 는 키 PARAMETER를 가진 해시 항목이다.
- 모듈을 재사용하는 대신 버그 위험 있는 구성 파일 복제 또는 다시 쓰기: 이 부분에 있어서 AppConfig는 상당히 안정적이다. 또한 모듈과의 인터페이스도 변경되지 않는다. 수천명의 프로그래머들에 의해 테스트되어 온 것으로 사용하지 않을 이유가 없다.
- DIY 우연적 해시 대신 일관성 있는 인터페이스를 포함한 객체 만들기: 일관성 있는 API는 메인 프로그램에서 구성 핸들러를 추출하여 핸들러의 인터페이스를 단순화한다. 이 접근법은 또한 데이터 구조와 직접 작동하는 대신 고유 메소드가 있기 때문에 버그가 적다.
AppConfig 선택 이유를 검토하였으니, 이제 AppConfig 사용법에 대한 완벽한 예제를 보자. 고급 기능은 다음 섹션에서 살펴 볼 것이다. 변수는 스칼라, 부울 및 배열 용 "-varname value" 및 해시 용 "-varneme key=value"으로 명령 행에 설정할 수 있다. config.pl이 구성 파일이고 예제는 다음과 같다. :
# blank lines are ignored |
AppConfig은 EXPAND 설정에 따라 여러 레벨에서 변수 확장을 할 수 있다. 상세한 사항은 AppConfig 문서를 참고한다..
# expand all variables, globally
my $config = AppConfig->new({ GLOBAL => { EXPAND => EXPAND_ALL } }); |
INI-스타일 섹션은 또 하나의 유용한 AppConfig 특징이다. 행 자체가 구성 파일에서 [section]을 이용하여 모든 키워드의 서두를 섹션 이름과 언더라인'_'으로 시작하여 파일 또는 다음 섹션의 끝까지 사용할 수 있다. 예제는 다음과 같다:
[file] location = /tmp type = txt name = accounts.txt [database] host = wyrm user = slayer password = amethyst |
다음은 동일한 내용이다:
file_location = /tmp file_type = txt file_name = accounts.txt database_host = wyrm database_user = slayer database_password = amethyst |
AppConfig 구성 객체는 varlist( ) 함수로 검사할 수 있다. AppConfig 객체에서 각 변수 내용을 인쇄하는 코드는 아래와 같다. varlist ( ) 함수는 정규식을 취해야만 하는 약간의 트릭을 사용한다.(빈 문자열은 유효하지 않다.)
use Data::Dumper; # for hash and array references |
AppConfig의 Getopt::Long 인터페이스는 Getopt::Long 모듈로의 완벽한 액세스를 허용한다. 아래는 명령 행에서 매개변수를 파싱하도록 호출되는 Getopt::Long에 대한 가변 매개변수를 정의한 코드이다.
$config->define("help|h|!"); # define a boolean
$config->define("code|c|=i"); # define a scalar integer
$config->define("list|l|=f@"); # define a array of floating point values only
$config->define("uids|u|=f%"); # define a hash of floating point values only |
AppConfig에서 변수 확인도 가능하다. 이 말은 변수가 정규식(한 개의 코드까지)을 조회하여 간단하게 무의미한 것이나 악의성 있는 것에 대한 값 설정을 거부할 수 있다는 뜻이다.
# the username validation succeeds only when it is exactly "joe"
# the password validation succeeds when it contains "joe" or "joE"
$config->define(
'USERNAME' => { ARGCOUNT => ARGCOUNT_ONE,
VALIDATE => sub # subroutine validation
{
my $varname = shift @_;
my $value = shift @_;
print "$varname = $value\n";
return ($value eq "joe");
}
},
'PASSWORD' => { ARGCOUNT => ARGCOUNT_ONE,
VALIDATE => "jo[Ee]" # regex validation
}
); |
AppConfig은 자동 트리거를 할 수 있어 변수값이 변경될 때 마다 조치가 수행 될 수 있게 한다. AppConfig은 서브 루틴으로 전송되어 기타 변수 변경이 단일 변경에 의해 트리거 될 수 있도록 한다.
$config->define(
'USERNAME' => { ARGCOUNT => ARGCOUNT_ONE,
ACTION => sub # autoaction
{
my $config = shift @_;
my $varname = shift @_;
my $value = shift @_;
print "$varname = $value\n";
}
}
); |
AppConfig는 변수에 삽입된 코드를 처리하지 않는다. 구성 파일에 있어 코드가 불필요하다. 더구나 사용자 임의 코드 실행을 허용하는 것이 효과적이지 않을 수 있다. 변수와 연관된 자동 작동(auto-action) 및 유효성 검사 서브루틴이 변수 평가를 위해 조정될 수 있지만, AppConfig는 자동 변수 평가를 제공하지는 않는다. 필요할 경우 변수를 선택하여 다음 설명과 같이 eval( )을 실행한다. 사용자에게 프로그램에 대한 제어 수준을 확인하는 것이 우선이라는 것을 명심하라.
foreach my $varname ('username', 'password')
{
$config->set($varname, eval $config->get($varname));
} |
AppConfig에서 INI-스타일 섹션은 코드를 정의한다. 그러나 섹션은 미리 그 유용성이 점검되어야 한다. 섹션이 상위 객체에 중첩된 신규 AppConfig 객체를 생성할 수 있도록 설계하는 것이 좋다. 어쨌든 이런 문제는 큰 문제가 아니다.
간단한 테스트를 해보면 로딩과 실행 속도는 AppConfig 사용에 아무 문제가 없다. 매우 작은 모듈이면서 사이즈/스피드 패널티도 무시될 수 있다. 사용자 프로그램이 정확한 시간 값을 필요로 하는 것이라면 AppConfig를 사용할 때와 사용하지 않을 때의 시간을 측정하여 사용할 가치가 있는지 결정해야 한다.
주로 API 덕분에 AppConfig 복잡성과 학습곡선 레벨은 기대치 이하이다. 초보 프로그래머에게 특히 혼란스럽다. 그러나 대체로 기존 Perl을 경험했던 프로그래머에게는 중요한 문제는 아니다.
AppConfig의 파싱 제한은 유용성의 문제 때문이다. 명령 행 옵션의 고급 파싱이 필요하면 Perl 프로그램에 대한 이전 글(AppConfig이 구분 파싱 불가능한 검색 능력에 관한 내용)를 참조 바란다.
AppConfig 및 Persistent::DBI으로 데이터베이스에 구성을 업로딩하기
이 섹션을 읽기 전에 Persistent 모듈 사용의 데이터 저장에 관한 자료를 참조하기 바란다. 또한 Perl 레퍼런스 및 SQL 데이터베이스에 대한 이해가 있어야한다. 예제에서는 MySQL 데이터베이스 및 그에 상응하는 Persistent 모듈을 사용한다. 다른 데이터베이스(예를 들어, Postgres 또는 Oracle)를 사용한다면, 그에 맞는 다른 Persistent 모듈을 찾아야 한다.
데이터베이스에 구성을 적용하기 전에, 데이터베이스 스키마가 미리 설계되어 있어야 한다. 다시 말하면 데이터 저장 및 복원을 위한 코드를 작성하기 전에 어떤 데이터를 저장하고자 하는지 미리 결정해야 한다. 예제에서는 부울, 스칼라, 배열 및 해시를 각각의 별도 테이블에 저장한다.
이 접근법이 반드시 필요한 것은 아니다. 모든 데이터 유형에 대한 하나의 테이블만을 가지거나, 목적 별로 구분된 테이블들을 가질 수 있다. 내가 제시하는 예는Persistent 구성 구현에 필요한 한 가지의 방법이지 유일한 것은 아니다.
이 글에서 제시하는 스키마로 대부분 목적에 사용되기에 충분하다. 값과 키 길이에 있어 제한이 있으나 코드에서 쉽게 조정될 수 있다. 그러나 배열과 해시 요소 ID의 생성에 있어서 문제가 발생될 수 있다. 이런 경우, 완벽한 솔루션은 없다. 문제 해결하기 위한 다양한 접근법이 있을 뿐이다. 관련 데이터베이스에 임의의 구조화된 데이터 저장 문제가 항상 까다롭다.
AppConfig::State의 _argument() 메소드를 사용할 것이다. 메소드에 관한 상세한 정보는 AppConfig::State 사용설명서를 참조한다. 메소드 이름을 알고 있으면 그 메소드는 우리가 어떤 변수를 처리하고 있는 지를 즉시 알려 준다. MySQL 데이터베이스 및 상응 Persistent 모듈에 의한 사용자 .
코드의 예제에 대한 상세한 것은 Persistent config.pl을 참조한다.
AppConfig와 Persistent 클래스는 단순한 공동 작업으로 좋은 성과를 낼 수 있다. 이전 섹션에서 나타난 persistent-config 스크립트는 단축키 및 변수명으로 대부분의 구성을 처리할 수 있다. 그러나 개선되어야 할 부분이 있다. 일단 스크립트가 작성되면 네트워크 어느 곳에서나 스크립트를 시작할 수 있으며 중앙 호스트에서 현재 구성을 로드 할 수 있다. 이 개선 작업으로 데이터베이스 구성에 대해 알게 될 것이고 신규 네트워크 중심 방식으로 애플리케이션을 볼 수 있도록 도와 줄 것이다.
코드 재사용은 일반적인 모듈의 가장 큰 특징 중 하나이다. 특별히 AppConfig의 특징이라 할 수 있다. DIY(Do It Yourself) 접근법이 버그와 지연을 일으키는 경우, AppConfig는 대부분 구성의 요구사항을 만족시킬 충분히 효과적인 단일 솔루션을 제공한다.
"AppConfig limitations" 섹션에 기술된 제한을 매우 미약하다. 물론 AppConfig에 맡기기 이전에 프로젝트에 가장 적합한 것이 어떤 것인지를 결정해야 한다. 여기에 제시된 정보가 특정 프로젝트에 어떻게 적용되는지 파악하고 AppConfig 사용설명서를 참고하기 바란다.
AppConfig에 전체 작업을 맡기지 말고 필요한 부분만 선택한다. 프로그램 절반을 구성 파일에 올리는 것이 흥미로울 지 모르나 그렇게 되면 사용자의 항의가 빗발칠지도 모른다. 간략하고 논리적인 구성 파일을 만들라. AppConfig이 제공하는 명령 행 옵션(command-line options)을 포함하여 프로그램 구성 신텍스에 대한 상세한 내용을 작성한다.
- developerWorks worldwide 사이트에서 이 기사에 관한 영어원문.
- writing
Perl programs that speak English : developerWorks.
- saving
data with the Persistent modules : developerWorks.
- CPAN.org : Perl 모듈에 대한 내용
- Perl.com : Perl 정보 및 관련 참고자료
- Andy Wardley의 Appconfig 모듈:
- CPAN 모듈의 기타 구성 관리:
- XRDB-style resources
- ConfigReader::Simple (little documentation, use at own risk)
- Config::IniFiles (different from AppConfig, some common functionality)
- Parse::PerlConfig (more complex than AppConfig, not as easy for the users)
- Programming
Perl Third Edition : Larry Wall, Tom Christiansen, Jon Orwant
공저 (O'Reilly & Associates, 2000)
- Perl Cookbook
:Tom Christiansen and Nathan Torkington (O'Reilly & Associates,
1998)
- Dr.
George Boole: 상징 논리의 창시자