2012년 1월 3일 화요일

[DeveloperWorks]Jython 스크립트를 재사용하여 WebSphere Application Server 시스템 관리하기

Jython 스크립트를 재사용하여 WebSphere Application Server 시스템 관리하기

소개
결론적으로 말해서 wsadmin Jython 스크립트를 작성하는 대부분의 개발자는 일부 루틴을 재사용하기를 원한다. 독자가 이들 중 한 명이라면 이렇게 할 수 있는 방법이 매우 다양하고 각 기술에는 고유한 장단점과 문제점이 있다는 사실을 다행스럽게 여길 것이다. 그러나 이처럼 다양한 기술에 관한 정보를 찾기가 어렵다는 점이 문제이다. 독자에게 도움을 주기 위해 이 기사에서는 Jython 오브젝트를 재사용할 수 있는 다양한 방법에 관한 정보 콜렉션과, 사용할 기술을 결정할 때 고려해야 할 사항을 소개한다.
여기에 소개된 정보는 독자가 IBM® WebSphere® Application Server 스크립팅 환경을 수월하게 준비하고 정의할 수 있도록 도움을 주기 위한 것이다. 따라서 독자는 IBM WebSphere Application Server와 함께 제공되는 wsadmin 스크립팅 유틸리티뿐만 아니라 Python 프로그래밍 언어나 이 언어를 Java™로 구현한 Jython의 구문과 시맨틱에 익숙해야 한다. 자세히 알고 싶은 경우에는 WebSphere Application Server Information Center 온라인 문서와 IBM Press에서 발행된 책인 WebSphere Application Server Administration Using Jython을 참조하는 것이 좋으며, 이 두 가지는 모두 이 기사에 있는 일부 자료의 중요한 소스가 되었다.
네임스페이스 간소화 및 정리
wsadmin 환경에 있는 Jython 프로그래머의 과제 중 하나는 wsadmin 스크립팅 유틸리티를 처음 시작할 때, 편의를 위해 정의된 많은 것들이 수반된다는 사실이다. 이것을 어떻게 알 수 있을까? wsadmin을 시작하면 dir() 내장 함수를 사용하여 현재 네임스페이스의 내용을 표시할 수 있다. 목록 1에는 이러한 것을 보여주는 대화식 wsadmin 세션이 표시되어 있다. 다음에 있는 표 A에는 목록 1에 있는 대화식 wsadmin 세션의 각 부분이 설명되어 있다. (스크립트 코드와 명령 세션 예제를 명확하게 설명하기 위해 이 기사에서는 목록/표 쌍 규칙을 사용한다.)

목록 1. 초기(기본값) 네임스페이스
1|C:\IBM\WebSphere\AppServer80\bin>wsadmin -lang jython
 2|WASX7209I: Connected to process "dmgr" on node ragweedCellManager03
 3|using SOAP connector; The type of process is: DeploymentManager
 4|WASX7031I: For help, enter: "print Help.help()"
  |
 5|wsadmin>dir()
  |
 6|['AdminApp', 'AdminApplication', 'AdminAuthorizations', 'AdminBLA',
 7|'AdminClusterManagement', 'AdminConfig', 'AdminControl', 'AdminJ2C', 'AdminJDBC',
 8|'AdminJMS', 'AdminLibHelp', 'AdminNodeGroupManagement', 'AdminNodeManagement',
 9|'AdminResources', 'AdminServerManagement', 'AdminTask', 'AdminUtilities',
10|'ApplyPerfTuning', 'Help', 'LTPA_LDAPSecurityOff', 'LTPA_LDAPSecurityOn', 'TypedProxy',
11|'__builtin__', '__doc__', '__name__', 'bsf', 'cellName', 'checkuserpw',
12|'doAuthenticationMechanism', 'doGlobalSecurity', 'doGlobalSecurityDisable',
13|'doLDAPUserRegistry', 'domainHostname', 'exportLTPAKey', 'flag', 'forceSync',
14|'generateLTPAKeys', 'getLDAPUserRegistryId', 'getLTPAId', 'getSecId',
15|'getSecurityAdminMbean', 'imp', 'java', 'ldapPassword', 'ldapPort', 'ldapServer',
16|'ldapServerId', 'ldapUserRegistryId', 'lineSeparator', 'ltpaId', 'main', 'nodeName',
17|'osgiApplicationConsole',  'secMbean', 'securityId', 'securityoff', 'securityon',
18|'sleep', 'sys', 'whatEnv']
  |
19|wsadmin>print len( dir() )
  |
20|60


표 A. 목록 1 설명
설명 및 주석
1wsadmin 명령 호출 - jython을 사용할 언어로 지정한다.
2-3wsadmin이 DeploymentManager에 성공적으로 연결되었다는 것을 표시하는 WASX7209I 정보 메시지이다.
4Help wsadmin 스크립팅 오브젝트를 사용하여 wsadmin 스크립팅 오브젝트의 사용에 관한 정보를 얻는 방법을 표시하는 WASX7031I 정보 메시지이다.
5wsadmin 대화식 명령 프롬프트 "wsadmin>" 다음에 사용자 지정 명령(즉 "dir()")이 있다.
6-18로컬 네임스페이스에 정의되어 있는 모든 오브젝트(예: 변수 및 함수)의 이름이 표시되어 있는, dir() 명령의 출력이다.
19wsadmin 대화식 명령 프롬프트 다음에 dir()이 리턴한 이름 목록의 길이(목록에 있는 이름의 수)를 표시하는 사용자 지정 명령(즉, "print len( dir() )"이 있다.
20dir() 목록에 있는 이름의 수(즉, 60)이다.
불행히도 이러한 모든 것들이 무엇인지 그리고 이것들이 초기 환경에 어떻게 왜 추가되었는지는 아직 분명하지 않다. 여기에서 논의하는 재사용 기술을 이해하기 쉽도록 우선, 초기 네임스페이스에서 이러한 특별 항목을 제거하도록 하자. 이렇게 하면 wsadmin 환경에서 수행하게 될 변경 작업의 효과를 더 수월하게 파악할 수 있게 된다.
네임스페이스 정리(단축화)

적용 가능한 WebSphere Application Server 버전

이 기사에 있는 예제는 WebSphere Application Server Network Deployment V8을 사용하여 테스트했다. 모든 예제는 WebSphere Application Server V7에서도 테스트되었으며 V7에서 새로 도입된 scriptLibrary와 관련이 없는 예제는 V6.1 환경에서 실행되었다.
이러한 초기 오브젝트 이름 목록과 관련해서 자주 묻는 질문으로는 다음과 같은 것들이 있다.
  • 실제로 이러한 오브젝트가 모두 필요할까? 이에 대한 답은 하고자 하는 것과 해야 하는 것이 무엇이냐에 따라 달라진다. 어떤 상황에서는 이러한 오브젝트 중 일부가 유용할 수 있지만, 일반적으로 대부분의 사용자와 상황에서는 이러한 오브젝트를 사용하는 경우가 매우 드물다. 그렇지만, "드물게 사용된다"라고 말하는 것이 이 질문에 대한 일반적이고 보다 정확한 대답이 될 수 있다.
  • 원하지 않는 오브젝트나 필요하지 않은 오브젝트를 제거하는 방법이 있나? 그렇다. "특별한" 오브젝트를 제거하여 오브젝트 이름 목록을 최소한으로 줄이려면 먼저, <WAS_HOME>/scriptLibraries 디렉토리의 이름을 바꾼다. 이 디렉토리 구조에 무엇이 있는지 간단하게 확인할 수 있지만, 지금은 단지 이 디렉토리의 이름을 바꾸고 wsadmin을 다시 시작하여 이 디렉토리 구조가 기본 네임스페이스에서 오브젝트 이름 목록에 대해 어떤 역할을 하는지 확인한다. 목록 2에서는 또 다른 대화식 wsadmin 세션을 사용하여 이것을 표시한다.

목록 2. scriptLibraries 디렉토리의 이름을 바꾼 후의 네임스페이스
1|wsadmin>dir()
  |
 2|['AdminApp', 'AdminConfig', 'AdminControl', 'AdminTask', 'Help',
 3|'LTPA_LDAPSecurityOff', 'LTPA_LDAPSecurityOn', 'TypedProxy', '__builtin__', '__doc__',
 4|'__name__', 'bsf', 'cellName', 'checkuserpw', 'doAuthenticationMechanism',
 5|'doGlobalSecurity', 'doGlobalSecurityDisable', 'doLDAPUserRegistry', 'domainHostname',
 6|'exportLTPAKey', 'flag', 'forceSync', 'generateLTPAKeys', 'getLDAPUserRegistryId',
 7|'getLTPAId', 'getSecId', 'getSecurityAdminMbean', 'imp', 'java', 'ldapPassword',
 8|'ldapPort', 'ldapServer', 'ldapServerId', 'ldapUserRegistryId', 'lineSeparator',
 9|'ltpaId', 'main', 'nodeName', 'secMbean', 'securityId', 'securityoff', 'securityon',
10|'sleep', 'sys', 'whatEnv']
11|wsadmin>print len( dir() )
  |
13|45


표 B. 목록 2 설명
설명 및 주석
1대화식 명령 프롬프트 및 사용자 명령: dir()
2-10로컬 네임스페이스에 정의되어 있는 모든 오브젝트(예: 변수 및 함수)의 이름이 표시되어 있는, dir() 명령의 출력이다.
11wsadmin 대화식 명령 프롬프트 다음에 dir()이 리턴한 이름 목록의 길이(목록에 있는 이름의 수)를 표시하는 사용자 지정 명령, 즉 "print len( dir() )"이 있다.
12dir() 목록에 있는 이름의 수(즉, 45)이다.
표 B에서 알 수 있듯이 목록 2에는 scriptLibraries 디렉토리의 이름을 바꾼 후의 네임스페이스가 표시되어 있으며 로컬 범위 오브젝트 이름의 목록에서 15개의 항목이 제거되었다. 따라서 네임스페이스에 있는 항목 수가 25% 줄었으며 이 정도면 적당하다.
특성 파일 연관
wsadmin을 초기화하는 과정에서는 적절한 wsadmin.properties 파일을 읽어서 이 파일을 wsadmin 환경을 구성하거나 초기화하는 데 사용한다.
예를 들어, wsadmin을 시작할 때 -profileName 명령행 옵션을 사용하거나 특정 프로파일 디렉토리(예: C:\IBM\WebSphere\AppServer\profiles\AppSrv01\bin) 아래에서 wsadmin 유틸리티를 시작하면 이 프로파일의 wsadmin.properties 파일이 사용된다. 다시 말해서, 현재 <WAS_HOME>/bin 디렉토리(예: C:\IBM\WebSphere\AppServer\bin)에 있지만 wsadmin 명령행에서 -profileName 옵션을 지정하지 않은 경우에는 기본 프로파일의 wsadmin.properties 파일이 사용된다. 기본 프로파일의 이름을 확인하려면 다음 명령을 사용한다.
manageprofiles -getDefaultName
일반적으로 주어진 프로파일의 wsadmin.properties 파일은 특정 프로파일 아래에 있는 properties 디렉토리(예: C:\IBM\WebSphere\AppServer\profiles\Dmgr01\properties \wsadmin.properties)에 있다.

기본 프로파일

이 기사에 있는 모든 예제에서는 기본적으로 배치 관리자 프로파일을 사용한다.
이 기사에서는 wsadmin.properties 파일의 몇 가지 지시문을 다루지만, 지금은 사용자 명령이나 스크립트에 앞서 실행하고 처리할 프로파일 파일의 목록을 식별하는 데 사용된 지시문에만 집중하기로 한다. 처음에는 지시문이 다음과 같은 형태가 된다. (이 기사의 목적상, 생략 부호(…)를 사용하여 이 행을 짧게 줄였으며 여기에는 <WAS_HOME> 경로가 표시된다.)
com.ibm.ws.scripting.profiles=.../securityProcs.jacl;.../LTPA_LDAPSecurityProcs.jacl
파일 확장자가 .jacl이면 언어가 Jython일 때, 이러한 프로파일 스크립트가 실행되지 않는 것일까? 그럴 수도 있고 그렇지 않을 수도 있다. 간단히 말해서 언어가 Jython인 경우에는 securityProcs.jacl과 LTPA_LDAPSecurityProcs.jacl을 실행하는 대신 wsadmin이 지정된 디렉토리에 있는 securityProcs.py과 LTPA_LDAPSecurityProcs.py를 찾는다. (텍스트 편집기로 이러한 Jython 파일을 열면 초기 wsadmin 네임스페이스에 있는 대부분의 이름이 지정된 오브젝트가 어디에서 비롯되었는지 알 수 있다. 따라서 이 프로파일 파일의 파일 확장을 wsadmin.properties 파일에 지정된 기본 언어와 일치시키는 것이 좋다.)
단순한(최소) 환경
해당 wsadmin.properties 파일을 편집하여 다음과 같이 해당 행의 시작 부분에 번호 기호("#")를 삽입함으로써 프로파일 지시문을 주석 처리한다.
# com.ibm.ws.scripting.profiles=...
이렇게 하면 초기 wsadmin 환경이 얼마나 변화될까? 목록 3에는 이렇게 변경한 효과가 표시되어 있다.

목록 3. 최소한의 wsadmin 네임스페이스
1|wsadmin>dir()
  |
 2|['AdminApp', 'AdminConfig', 'AdminControl', 'AdminTask', 'Help', 'TypedProxy',
 3|'__builtin__', '__doc__', '__name__', 'bsf', 'imp', 'main', 'sys']
  |
 4|wsadmin>print len( dir() )
  |
 5|13

로컬 네임스페이스의 이름 지정된 오브젝트의 수가 약 80% 줄었으며, 따라서 오브젝트 목록이 60개의 이름으로 구성되었던 원래의 목록보다 상당히 짧아졌다. 이것은 곧 "깨끗한" 환경으로 시작한다는 것을 의미한다.
이제까지 초기 wsadmin 환경의 네임스페이스를 최소화했으므로 각 재사용 기술이 스크립팅 환경에 미치는 영향을 더 쉽게 이해할 수 있을 것이다.
Python에서 상속된 기술
이 기사에서 논의할 기술 중에서 Python 언어에서 상속된 유일한 기술은 다음과 같다.
  • 스크립트 파일
  • 모듈
  • 패키지
이 기사를 읽고 있는 독자라면 아마도 wsadmin 스크립트 파일과 이 파일을 실행하는 방법을 이미 잘 알고 있을 것이다. 일반적으로 wsadmin 스크립트는 wsadmin 유틸리티로 실행할 수 있는 파일에 있는 Jython 명령문으로 구성된 콜렉션이다. 실행될 스크립트 파일의 이름은 -f 플래그 다음에 fwsadmin 명령행 옵션으로 지정한다.
스크립트는 import 명령문을 통해 기존의 모듈이나 내장 모듈을 주로 사용한다. 다양한 내장 오브젝트 스크립트에서 사용 가능하도록 하려면 표 C에 있는 변형된 import 명령문을 사용해야 한다. (이러한 변종에 익숙하지 않은 경우에는 참고자료를 참조한다.)

표 C. Import 명령문 변종
변종 번호변종 구문
1import moduleName
2import moduleName as aliasName
3from moduleName import objectName
4from moduleName import objectName as objectAlias
5from moduleName import *
이러한 변종을 논의하기 전에 import 명령문이 처리되는 과정에서 모듈이 어떻게 발견되고 실행되는지 알아야 한다. Jython은 sys.path 목록에 지정된 각 디렉토리에서 moduleName.py 파일을 검색하여 주어진 moduleName을 찾는다. 목록 4에는 scriptLibraries 디렉토리의 이름을 바꾸기 의 sys.path의 내용이 표시되어 있으며 목록 5에는 이 디렉토리의 이름을 바꾼 의 내용이 표시되어 있다.

목록 4. 기본 sys.path
1|wsadmin>for d in sys.path : print d
 2|wsadmin>
 3|.
 4|C:\IBM\WebSphere\AppServer80\optionalLibraries\jython\Lib
 5|C:/IBM/WebSphere/AppServer80/scriptLibraries/application/V70
 6|C:/IBM/WebSphere/AppServer80/scriptLibraries/osgi
 7|C:/IBM/WebSphere/AppServer80/scriptLibraries/perfTuning/V70
 8|C:/IBM/WebSphere/AppServer80/scriptLibraries/resources/J2C/V70
 9|C:/IBM/WebSphere/AppServer80/scriptLibraries/resources/JDBC/V70
10|C:/IBM/WebSphere/AppServer80/scriptLibraries/resources/JMS/V70
11|C:/IBM/WebSphere/AppServer80/scriptLibraries/resources/Provider/V70
12|C:/IBM/WebSphere/AppServer80/scriptLibraries/security/V70
13|C:/IBM/WebSphere/AppServer80/scriptLibraries/servers/V70
14|C:/IBM/WebSphere/AppServer80/scriptLibraries/system/V70
15|C:/IBM/WebSphere/AppServer80/scriptLibraries/utilities/V70
16|wsadmin>

목록 4의 2행에 있는 빈 행은 Jython 해석기에게 1행에서 시작된 for문이 완료되었다는 사실을 알려주는 역할을 한다.
또한, 목록 4에서는 "현재의 작업 디렉토리"(3행에서 "."로 표시됨)가 목록의 첫 번째 부분에 있다는 것을 알 수 있다. 따라서 import moduleName 명령문이 실행되면 Jython이 현재의 작업 디렉디렉토리를 먼저 조사하여 moduleName.py가 존재하는지 확인한 후, 이 파일을 실행한다. 이 파일이 현재의 작업 디렉토리에 존재하지 않는 경우에는 sys.path 목록에 있는 지정된 moduleName.py 파일을 찾아서 실행하거나 디렉토리 목록이 고갈될 때까지 각 디렉토리를 순서대로 확인한다. 지정된 모듈이나 오브젝트를 찾을 수 없는 경우에는 ImportError 예외가 발생한다.

목록 5. scriptLibraries 디렉토리가 존재하지 않을 때의 sys.path
1|C:\IBM\WebSphere\AppServer80\bin>wsadmin –conntype none
 2|...
 3| wsadmin>for d in sys.path : print d
 4| wsadmin>
 5|.
 6| C:\IBM\WebSphere\AppServer80\optionalLibraries\jython\Lib
 7| wsadmin>

import 명령문 변종 이해하기
이제까지 Jython이 모듈을 어떻게 로드하는지 살펴보았으므로 표 C에 있는 다양한 import 명령문 변종을 살펴보도록 하자. 이러한 변종을 역순으로 살펴보자.
  • 변종 5는 직접 입력한 명령문(모듈 파일 안에 있는)처럼 작동한다. 따라서 파일에서 찾을 수 있는 모든 definitions 및 assignment 명령문이 로컬 범위 네임스페이스에 직접 영향을 끼치게 되며 동일한 이름의 기존 오브젝트를 수정하거나 제거할 수 있게 된다. 이 모듈에 있는 모든 새 오브젝트를 로컬 네임스페이스에 추가하면 네임스페이스 클러터가 많이 생기고 로컬 네임스페이스가 오브젝트 이름으로 빠르게 채워질 뿐만 아니라 이러한 오브젝트가 비롯된 위치를 알거나 기억하지도 못하게 된다. 따라서 이 변종은 사용하지 않는 것이 좋다.
  • 변종 3과 4는 모듈에 있는 오브젝트를 선택적으로 로컬 네임스페이스에 추가하기 위해 사용된다. 이러한 변종은 선택적이기 때문에, 변종 5만큼 위험할 가능성은 훨씬 적지만 여전히 문제를 일으킬 수 있다. 모듈에서 가져온 objectName나 objectAlias가 로컬 네임스페이스에 이미 존재하는 상황을 생각해 보자. 기존 오브젝트가 가져온 오브젝트로 대체되는데, 이러한 결과는 원하는 바가 아니다. 변종 3이나 4를 사용하면 자신도 모르게 기존 오브젝트를 겹쳐 쓸 수 있으며, 이렇게 되면 디버깅을 하거나 진단하기 어려운 방식으로 스크립트가 실패한다.
  • 변종 3에서 5까지는 지정된 모듈에 있는 항목을 로컬 네임스페이스에 추가한다. 이렇게 되면 단순히 오브젝트 이름을 사용하여 지정된 오브젝트에 액세스할 수 있다. 물론 가져오고자 하는 moduleName나 aliasName의 이름이 있는 로컬 네임스페이스에 오브젝트가 이미 존재하지 않는 한, 이것은 변종 1이나 2를 사용하는 경우에는 해당되지 않는다. 이것은 새로울 것도 없다. import moduleName을 사용하는 경우에는 목록 6에서와 같이 로컬 네임스페이스에 moduleName만 추가된다.

목록 6. 변종 1 사용: import moduleName
1|C:\IBM\WebSphere\AppServer80\bin>type something.py
 2|print "dir():", dir()
  |
 3|C:\IBM\WebSphere\AppServer80\bin>wsadmin -conntype none
 4|...
 5|wsadmin>dir()
 6|['AdminApp', 'AdminConfig', 'AdminControl', 'AdminTask', 'Help', 'TypedProxy',
 7|'__builtin__', '__doc__', '__name__', 'bsf', 'imp', 'main', 'sys']
  |
 8|wsadmin>import something
 9|dir(): ['__doc__', '__file__', '__name__']
  |
10|wsadmin>dir()
11|['AdminApp', 'AdminConfig', 'AdminControl', 'AdminTask', 'Help', 'TypedProxy',
12|'__builtin__', '__doc__', '__name__', 'bsf', 'imp', 'main', 'something', 'sys']
  |
13|wsadmin>dir( something )
14|['__doc__', '__file__', '__name__']
  |
15|wsadmin>print something.__file__
16|C:\IBM\WebSphere\AppServer80\bin\.\something.py
17|wsadmin>


표 D. 목록 6 설명
설명 및 주석
1보통의 모듈인 something.py의 내용을 표시하는 운영 체제 명령이다.
2something.py의 내용이다.
3로컬 모드에서 wsadmin 유틸리티를 호출하는 데 사용되는 명령이다.
4wsadmin의 출력이 표시되고 있지 않다는 것을 나타내기 위해 사용된 생략 부호이다.
5대화식 명령 프롬프트와 실행될 import 명령문, 즉 dir()이다.
6-7현재 네임스페이스의 내용이 표시된 출력이 생성되어 있다.
8대화식 프롬프트와 import 명령문(변종 1)
9모듈 스크립트, 즉 module namespace를 실행하여 생성된 출력이다.
10수정된 네임스페이스를 표시할 dir() 명령의 또 다른 인스턴스이다.
11-12새 네임스페이스 항목만 가져온 모듈의 항목(즉, "something")이라는 점을 나타내는 출력이 생성되어 있다.
13dir() 명령의 또 다른 인스턴스로, 이번에는 가져온 모듈의 네임스페이스를 표시하기 위해 사용되었다.
14모듈의 네임스페이스가 변경되지 않았다는 점을 나타내는 출력이 생성되어 있다(9행 참조).
15something 모듈 안에 있는 __file__ 변수의 값을 표시하는 데 사용된 명령문을 인쇄한다. 모듈 오브젝트를 식별하기 위해 점 연산자를 사용한다.
위에 있는 정보는 모듈의 가장 중요한 특성 중 특히 다음과 같은 특성을 설명해 준다.
  • 변종 1이나 2를 사용하여 모듈을 가져오면 로컬 네임스페이스를 무질서하게 하지 않으면서 모든 모듈 오브젝트에 액세스하게 할 수 있다.
  • 참조된 오브젝트를 식별하기 위해 점 표기법을 사용하면 실제 오브젝트가 존재하는 위치(즉, 지정된 모듈 내)를 손쉽게 확인할 수 있다.
모듈과 wsadmin 스크립팅 오브젝트
wsadmin 스크립팅 오브젝트로 wsadmin 환경 안에 존재하는 오브젝트 5개(즉, AdminApp, AdminConfig, AdminControl, AdminTask 및 Help)를 참조하여 WebSphere Application Server를 조작하거나 이 서버와 상호 작용할 것이다.
WebSphere Application Server V7.0 이전에는 이렇게 하려면 모듈에 다소 문제점이 있었다. 사실상, WebSphere Application Server Administration Using Jython 책과 Using the full potential of Jython to build compact and maintainable wsadmin scripts 기사(참고자료 참조)에는 이러한 한계를 극복하기 위해 사용할 수 있는 기술이 설명되어 있다. 그러나 WebSphere Application Server V7.0 이후 버전에는 이러한 문제점이 없으며, 이는 wsadmin 스크립팅 오브젝트에 액세스해야 하는 모든 모듈에는 문제가 되는 오브젝트를 처리하는 데 필요한 "global" 명령문이 있다는 것을 의미한다. 예를 들어, 모듈에서 AdminConfig 스크립팅 오브젝트를 액세스해야 하는 경우에는 모듈에 global AdminConfig와 같은 명령문만 있으면 된다. 나중에 scriptLibraries에 관해 논의하는 과정에서 이 점을 조금 더 살펴볼 것이다.
패키지
패키지는 Python에서 유래한 마지막 재사용 기술이다. 패키지는 모듈을 계층 구조로 체계화하고 점 연산자를 사용하여 관계를 나타내는 방법이다. 예를 들어, wsadmin.properties 파일에 있는 지시문을 다시 살펴보면 com.ibm.ws.scripting.defaultLang과 같은 지시문을 찾을 수 있는데, 이것은 패키지의 이름을 지정하는 작업과 유사한 방식으로 작동한다. 이러한 점으로 구분된 목록에 있는 각 이름(예: "com" 및 "ibm")은 패키지 계층 구조에 있는 일종의 디렉토리이다.
왜 모듈 이름을 이렇게 중첩되게 지정해야 할까? 개발자로 구성된 팀에서 패키지 콜렉션을 설계하는 상황을 생각해 보자. 단일 네임스페이스에서 오브젝트 콜렉션을 서로 분리하기 위해 모듈을 사용하는 것과 마찬가지로 관련된 모듈을 수집하여 함께 구성하기 위해 패키지를 사용할 수 있으며 또한, 그렇게 해야 한다.
Guido van Rossum와 Fred L. Drake, Jr.가 공동으로 저술한 An Introduction to Python(참고자료 참조) 책의 Section 6.4에는 패키지에 관한 우수한 정보를 제공하는 좋은 예제가 있다. 이 예제에서 다음과 같은 것을 배울 수 있다.
  • 단순한 모듈을 사용할 때와 마찬가지로 위에서 설명한 import 명령문 변종을 사용하여 모듈의 오브젝트를 사용 가능하게 할 수 있다.
  • 위에 있는 목록 4와 5에 표시되어 있듯이 sys.path에 있는 디렉토리를 사용하여 모듈을 찾게 된다. 단순한 모듈과 패키지 간의 기본적인 차이점은 포함하는 패키지로 형태로 디렉토리를 처리하도록 Jython에게 지시하는 데 사용되는 특정 파일(예: __init__.py)을 각 패키지 디렉토리에 삽입하는 방식에 있다. 그러나 첫 번째 패키지(예: 위에 있는 "com")를 포함하는 디렉토리만 sys.path에 있어야 한다.
이것이 무엇을 의미하는지 이해하기 위해 sys.path 목록의 기본 내용을 다시 살펴보자. 여기에서는 *.py 파일이 있는 scriptLibraries 계층 구조의 각 디렉토리가 sys.path에 나열된다. 이것이 어떤 도움이 될까? 우선 한가지는 이렇게 하면 import 명령문(이 명령문이 실제로 필요한 경우) import moduleName으로 단순화된다는 사실이다.
scriptLibraries가 패키지인 경우에는 sys.path에 항목이 하나만(예: <WAS_HOME>/scriptLibraries) 있으면 된다. 또한, 각 디렉토리 구조 레벨에는 비어 있을 수도 있는 __init__.py 파일이 포함된다. AdminBLA 모듈을 가져오려면 목록 7과 같은 형식으로 된 import 명령문이 필요하다.

목록 7. AdminBLA를 패키지로서 가져오기
import application.V70.AdminBLA

 또는

from   application.V70 import AdminBLA

사실상, 후자(표 C의 변종 3에 해당)를 사용하는 경우에는 보통 scriptLibraries에서 보게 되는 것처럼 단순히 moduleName(이 경우에는 AdminBLA)이 네임스페이스에 추가되며, 이러한 내용은 나중에 간단히 논의하게 될 것이다.
그러나 패키지를 사용하려면 디렉토리 구조의 각 레벨에 적당한 __init__.py 파일이 있어야 한다.
wsadmin에 고유한 재사용 기술
여기에서 설명하는 마지막 재사용 기술은 Python의 일부가 아니며 따라서 wsadmin 환경에서만 사용 가능하다. 이러한 재사용 기술은 다음과 같다.
  • 프로파일
  • scriptLibraries
프로파일 파일은 네임스페이스에 오브젝트를 추가하거나 네임스페이스에서 오브젝트를 제거할 때 사용되는 스크립트 파일로, wsadmin 유틸리티의 초기화 단계에서 실행된다. 따라서 지정된 사용자 스크립트 파일이 실행되거나 대화식 명령 프롬프트가 표시되기 전에 프로파일 스크립트를 사용하여 wsadmin 스크립팅 환경을 조작할 수 있다.
이는 앞에서 import 변종의 위험성과 관련하여 설명한 것과 매우 비슷하므로 익숙하게 들릴 것이다. 사실상, 이 기사를 시작할 때 wsadmin.properties 파일에서 지시문을 주석처리하여 지정된 파일이 프로파일로 실행되지 않도록 했는데, 이러한 프로파일이 실행되었으면 오브젝트 30개가 로컬 네임스페이스에 추가되었을 것이다.
그렇다면 파일을 실행하는 것과 프로파일을 실행하는 것과는 어떤 차이점이 있을까?
  • 명령행 구문 파일을 실행하려면 -f wsadmin 명령행 옵션 뒤에 이 파일을 이름을 지정한다(예: -f myFile.py). 프로파일 스크립트 파일을 실행하려면 다음과 같은 기술 중 하나를 사용한다.
    • -profile wsadmin 명령행 옵션을 지정할 수 있다(예: wsadmin -profile myFile.py).
    • 실행될 해당 wsadmin.properties 파일과 프로파일 스크립트를 편집하고 앞에서와 같이 이러한 파일과 스크립트를 주석이 해제된 프로파일 지시문에 추가한다.
  • 프로파일이나 파일 스크립트가 실행된 후에 취해지는 후속 조치 모든 프로파일 스크립트 파일이 실행된 후에는 wsadmin이 사용자 지정 스크립트 파일(있는 경우)을 실행하지만, 스크립트 파일이 지정되지 않은 경우에는 사용자 입력용 대화식 프롬프트를 표시한다. (프로파일 스크립트 파일과 달리 -f filename.py 명령행 옵션이 동시에 여러 개가 존재하는 경우에는 마지막 스크립트 파일만 호출된다. 따라서 wsadmin –conntype none –f a.py –f b.py 명령의 경우에는 b.py만 실행된다.
    사용자 지정 스크립트 파일이 실행되면 이 스크립트가 완료될 때까지 wsadmin 유틸리티가 계속 활성화되며, 스크립트가 완료될 때 wsadmin 유틸리티가 종료된다.
wsadmin 명령행 옵션을 사용하거나 스크립트 파일 이름을 wsadmin.properties 파일에 있는 프로파일 지시문에 추가하여 프로파일 스크립트 파일을 지정할 수 있다는 사실과 관련하여 다음과 같은 의문이 들 수 있다. 프로파일 파일은 여러 곳에 지정될 수 있기 때문에 프로파일 파일이 실행될 순서를 즉시 파악하기는 어렵다.
실행 순서와 관련된 의문을 해결하기 위해 비슷한 스크립트 파일 두 개(bob.py 및 Robert.py)를 목록 8에 표시해 놓았다. 첫 번째, bob.py는 wsadmin.properties에 지정하며 두 번째, Robert.py는 wsadmin 명령행 옵션을 사용하여 지정한다.

목록 8. 프로파일 실행 순서 예제
1|C:\IBM\WebSphere\AppServer80\bin>type bob.py
 2|File = 'bob.py'
 3|print 'File: %s  __name__ = "%s"' % ( File, __name__ )
 4|print 'dir():\n%s' % dir()
  |
 5|C:\IBM\WebSphere\AppServer80\bin>type Robert.py
 6|File = 'Robert.py'
 7|print 'File: %s  __name__ = "%s"' % ( File, __name__ )
 8|print 'dir():\n%s' % dir()
  |
 9|C:\IBM\WebSphere\AppServer80\bin>wsadmin -profile Robert.py
10|WASX7209I: Connected to process "dmgr" on node ...
11|File: bob.py  __name__ = "__main__"
12|dir():
13|['AdminApp', 'AdminConfig', 'AdminControl', 'AdminTask', 'File', 'Help', 'TypedProxy',
14|'__builtin__', '__doc__', '__name__', 'bsf', 'imp', 'main', 'sys']
15|File: Robert.py  __name__ = "__main__"
16|dir():
17|['AdminApp', 'AdminConfig', 'AdminControl', 'AdminTask', 'File', 'Help', 'TypedProxy',
18|'__builtin__', '__doc__', '__name__', 'bsf', 'imp', 'main', 'sys']
19|WASX7031I: For help, enter: "print Help.help()"
  |
20|wsadmin>print File
  |
21|Robert.py


표 E. 목록 8 설명
설명 및 주석
1bob.py의 내용을 표시할 운영 체제 명령
2-4bob.py의 내용
5Robert.py의 내용을 표시할 운영 제체 명령
6-8Robert.py의 내용이며, bob.py의 내용(2 - 4행)과 거의 동일하다.
9wsadmin 유틸리티를 시작할 때 사용하는 명령이며, Robert를 지정한다.
10wsadmin에 의해 생성된 잘려진 메시지이며, 배치 관리자에 연결되었다는 것을 나타낸다.
11-14wsadmin.properties 파일에 지정된 bob.py에 의해 생성된 출력이며, wsadmin.properties 파일 프로파일이 처음 실행되었다는 것을 나타낸다.
15-18Robert.py에 의해 생성된 출력이며, Robert.py가 wsadmin.properties에 지정된 후에 명령행 프로파일이 실행되었다는 것을 나타낸다.
19wsadmin 유틸리티에서 생성된, 대화식 세션 메시지
20wsadmin 명령 프롬프트 및 File 변수의 내용을 표시할 print 명령문
21print 명령문에 의해 생성된 출력이며, File 변수의 값을 나타낸다. 이 값은 프로파일 안에서 assignment 명령문으로 네임스페이스 값을 어떻게 수정할 수 있는지를 보여준다.
이러한 스크립트 파일을 실행하면 다음과 같은 내용을 알게 된다.
  • wsadmin.properties 파일에 지정된 프로파일 파일이 먼저 실행된다. 사실상, wsadmin.properties 파일에 지정된 프로파일 파일이, 나열된 순서(즉, 왼쪽에서 오른쪽으로)대로 실행된다는 사실을 추가 테스트를 통해 알 수 있다.
  • 다음에는 wsadmin 명령행에 지정된 프로파일 파일이 실행되며 -profile 명령행 지시문이 여러 개가 지정된 경우에는 프로파일 파일이 지정된 순서대로 실행된다.
  • 모든 프로파일 파일에 있는 명령문은 로컬 네임스페이스에 영향을 주며, 따라서 프로파일 파일에서 정의, 지정, 수정 및 삭제 조작이 수행될 때마다 로컬 네임스페이스에서 오브젝트의 값이 변경된다. boy.py에 의해 초기화된 File 변수의 값이 Robert.py에 있는 assignment 명령문에 의해 겹쳐 쓰여졌다는 사실에 주목한다.
이 마지막 사실에 입각해서 보면 프로파일 파일을 신중하게 자제해서 사용하는 것이 좋다는 것을 알 수 있다. 프로파일 파일을 작성하는 경우에는 이로 인해 최소 네임스페이스 수가 변경되는지 확인하도록 한다.
프로파일을 사용할 시점
프로파일은 결코 사용해서는 안 되는 것은 아니지만, 조심스럽게 사용해야 한다. 프로파일을 사용하여 모든 wsadmin 스크립트의 wsadmin 환경을 변경하는 경우는 합리적이다. 예를 들면, 앞서 언급한 책의 7장에는 프로파일 파일에서 수행할 수 있는 몇 가지 조치가 있는데, 이러한 조치를 이용하면 wsadmin 스크립트 사용자가 훨씬 더 수월하게 작업을 할 수 있다.
이외에도 이 책에는 프로파일을 사용하는 것이 매우 적합한 몇 가지 조치가 있다. 이러한 조치에는 다음과 같은 것들이 있다.
  • 반드시 기억해야 하는 import 명령문 실행 예를 들면, 목록 9의 1행에 있는 import 명령문을 참조한다(이 책의 5장 참조). 원래의 프로파일 스크립트(wsadmin.properties 파일에서 제거한 스크립트)를 모듈로서 가져오려고 할 수도 있다. 이러한 예제는 목록 9의 3행과 4행에 표시되어 있다. 프로파일 스크립트에 삽입하기로 선택할 수 있는 또 다른 유형의 import 명령문은 12행에 표시된 바와 같이 별명으로서 모듈을 가져오는 import 명령문이다.
  • sys.path에 디렉토리 추가 대부분의 개발자들은 재사용하기 쉽도록 루틴과 모듈을 특정 디렉토리에 모은다. 프로파일 스크립트에서 명령문을 사용하여 이 디렉토리의 존재 여부를 확인하여 만일 이 디렉토리가 존재하는 경우에는 이 디렉토리를 sys.path 목록의 원하는 위치에 추가함으로써 이 디렉토리를 sys.path에서 사용 가능하도록 하기 위해 프로파일 스크립트를 사용할 수 있다. 이러한 예제는 목록 9의 6 ~ 9행까지에 표시되어 있다.

목록 9. 가능한 프로파일 예제
1|from __future__ import nested_scopes
 2|
 3|import securityProcs
 4|import LTPA_LDAPSecurityProcs
 5|
 6|import os
 7|if 'wsadminModules' in os.listdir( r'C:\temp' ) :
 8|  sys.path.append( r'C:\temp' + os.sep + 'wsadminModules' )
 9|del( os )                  # Remove os from the namespace to minimize clutter
10|
11|try :
12|  import wsadmin_Jython_utilities as Util
13|except ImportError, e :
14|  print '\n*** WARNING *** Module not found: %s\n' % str( e ).split( ' ' )[ -1 ]
15|  del( e )                 # Remove e from the namespace to minimize clutter

이러한 예제는 네임스페이스를 정리하고 체계화하는 데 도움이 된다. 프로파일 스크립트를 사용하여 환경을 사용자 정의하고 스크립트 파일을 훨씬 더 이해하기 쉽도록 구성하는 방법을 생각해 보자. 모든 securityProcs 오브젝트를 네임스페이스에 추가하는 프로파일 대신, 목록 10에는 프로파일을 모듈로서 가져오는 과정이 표시되어 있다. 이제는 앞에서 살펴본 점(.) 연산자 표기법을 사용하여 모듈 안에 있는 모든 오브젝트를 액세스할 수 있으며, 목록 10의 4행에서 이점을 확인할 수 있다.

목록 10. 모듈로서 가져온 프로파일 사용
1|wsadmin>dir( securityProcs )
 2|['__doc__', '__file__', '__name__', 'checkuserpw', 'securityoff', 'securityon']
 3|wsadmin>
 4|wsadmin>securityProcs.securityoff()
 5|LOCAL OS security is off now but you need to restart the connected server ...

scriptLibraries의 역할
이 기사를 시작할 때 가장 먼저 수행한 것 중 하나는 제품을 설치하는 과정에서 작성된 scriptLibraries 디렉토리의 이름을 바꾸는 작업이었다. 이렇게 하는 과정에서 각 오브젝트의 이름이 네임스페이스에서 제거되었다. 이제까지 스크립트 파일과 모듈 및 패키지를 살펴보았으므로 이러한 스크립트 라이브러리 파일이 사실상 모듈이라는 사실을 바로 파악할 수 있을 것이다. 이점을 확인하려면 scriptLibraries 디렉토리를 복원한 후에 wsadmin 유틸리티를 시작한다. 이 디렉토리를 삭제하는 대신 이 디렉토리의 이름을 변경했으므로 이렇게 할 수가 있다. dir() 명령을 사용하여 로컬 네임스페이스에 어떤 변화가 일어나는지 확인한다. 목록 11에는 이렇게 할 수 있는 한 가지 방법이 표시되어 있다. (생성된 출력을 약간 더 읽기 쉽게 하면서 이 예제가 약간 더 복잡해졌다.) 표 F에는 중요한 세부사항이 설명되어 있다.

목록 11. 최소 wsadmin 네임스페이스 + scriptLibraries
1|C:\IBM\WebSphere\AppServer80\bin>wsadmin
 2|WASX7209I: Connected to process "dmgr" on node ...
 3|WASX7031I: For help, enter: "print Help.help()"
  |
 4|wsadmin>def namesInColumns( names ) :
 5|wsadmin>  x, width = 0, max( [ len( x ) for x in names ] )
 6|wsadmin>  for name in names :
 7|wsadmin>    if name != 'namesInColumns' :
 8|wsadmin>      print '%*s' % ( -width, name ),
 9|wsadmin>      x += 1
10|wsadmin>      if ( x + 1 ) * ( width + 1 ) > 80 :
11|wsadmin>        print
12|wsadmin>        x = 0
13|wsadmin>  print
14|wsadmin>
  |
15|wsadmin>namesInColumns( dir() )
  |
16|AdminApp                 AdminApplication         AdminAuthorizations
17|AdminBLA                 AdminClusterManagement   AdminConfig
18|AdminControl             AdminJ2C                 AdminJDBC
19|AdminJMS                 AdminLibHelp             AdminNodeGroupManagement
20|AdminNodeManagement      AdminResources           AdminServerManagement
21|AdminTask                AdminUtilities           ApplyPerfTuning
22|Help                     TypedProxy               __builtin__
23|__doc__                  __name__                 bsf
24|imp                      main                     osgiApplicationConsole
25|sys
  |
26|wsadmin>namesInColumns( dir( AdminBLA ) )
  |
27|AdminUtilities __doc__        __file__       __name__       addCompUnit
28|bundleName     createEmptyBLA deleteAsset    deleteBLA      deleteCompUnit
29|editAsset      editCompUnit   exportAsset    help           importAsset
30|java           listAssets     listBLAs       listCompUnits  resourceBundle
31|startBLA       stopBLA        sys            viewAsset      viewCompUnit
  |
32|wsadmin>print AdminBLA.__file__
  |
33|C:\IBM\WebSphere\AppServer80\scriptLibraries\application\V70\AdminBLA.py
  |
34|wsadmin>print AdminBLA.__name__
  |
35|AdminBLA


표 F. 목록 11 설명
설명 및 주석
1wsadmin 유틸리티를 시작하는 데 사용된 명령
2-3wsadmin을 초기화하는 과정에서 생성된 출력
4-13지정된 이름을 열에 표시할 함수를 정의하는 명령문
15namesInColumns() 함수를 호출하여 네임스페이스의 내용을 열에 표시한다.
16-25생성된 출력이며, 내장된 dir() 함수를 호출하여 리턴된 값으로 구성된 목록에 있는 28개의 이름이 표시되어 있다.
26namesInColumns() 함수를 호출하여 AdminBLA 모듈의 네임스페이스를 표시한다.
27-31생성된 출력이며, 모듈의 네임스페이스에 있는 25개의 이름이 표시되어 있다.
32AdminBLA 모듈에 있는 __file__ 오브젝트의 값을 표시하는 print 명령문
33생성된 출력이며, 모듈이 로드된 파일에 대한 완전한 경로가 표시되어 있다.
34AdminBLA 모듈에 있는 __name__ 오브젝트의 값을 표시하는 print 명령문
35생성된 출력이며, AdminBLA.__name__의 값이 표시되어 있다.
모듈과 모든 scriptLibraries 모듈 간의 기본적인 차이점은 scriptLibraries 모듈은 명시적으로 "가져오지" 않아도 기본적으로 사용 가능하다는 점이다. 그렇지만, 모듈의 경우에는 import 명령문이 성공적으로 수행되려면 모듈이 있는 디렉토리가 sys.path 목록에 존재해야 한다.
목록 4에서는 대화식 wsadmin 세션이 시작될 때, Jython 파일(즉, 확장자가 .py인 파일)이 있는 scriptLibraries 디렉토리가 있는 디렉토리가 sys.path의 내용에 포함된다는 사실을 확인했다.
scriptLibraries 디렉토리에 있는 *.py 파일의 이름을 다른 확장자(예: *.py.tx)로 변경한 후에 wsadmin을 시작하면 *.py 파일이 있는 디렉토리만 sys.path에 추가된다는 사실을 확인할 수 있다. sys.path의 내용을 표시하면 scriptLibraries 디렉토리는 하나도 표시되지 않는다는 것을 알 수 있다.
scriptLibraries 모듈을 프로파일 스크립트에서 사용할 수 있을까?
둘 이상의 scriptLibraries 모듈에 의존하는 프로파일 코드가 일부 있으면 프로파일 스크립트가 실행되기 전에 이러한 모듈이 사용 가능해야 한다. 이것을 확인하기는 쉬우며, 프로파일을 실행하는 과정에서 로컬 네임스페이스를 표시할 수 있다(목록 12).

목록 12. 프로파일과 scriptLibraries 중 어느 것이 먼저 실행될까?
1|C:\IBM\WebSphere\AppServer80\bin>wsadmin
  |
 2|WASX7209I: Connected to process "dmgr" on node ...
 3|File: bob.py      __name__ = "__main__"
 4|dir():
 5|['AdminApp', 'AdminApplication', 'AdminAuthorizations', 'AdminBLA',
 6|'AdminClusterManagement', 'AdminConfig', 'AdminControl', 'AdminJ2C', 'AdminJDBC',
 7|'AdminJMS', 'AdminLibHelp', 'AdminNodeGroupManagement', 'AdminNodeManagement',
 8|'AdminResources', 'AdminServerManagement', 'AdminTask', 'AdminUtilities',
 9|'ApplyPerfTuning', 'File', 'Help', 'TypedProxy', '__builtin__', '__doc__',
10|'__name__', 'bsf', 'imp', 'main', 'osgiApplicationConsole', 'sys']
11|bob.py executed.
12|WASX7031I: For help, enter: "print Help.help()"
13|wsadmin>

다행히도 목록 12에서는 wsadmin.properties 파일에 지정된 프로파일 파일의 경우에도 프로파일이 실행될 때 scriptLibraries 디렉토리에 있는 모듈이 이미 사용 가능했다. 기억해야 할 점은 wsadmin 명령행 -profile 옵션에 의해 프로파일 파일이 식별되기 전에 wsadmin.properties 파일에서 식별된 프로파일 파일이 실행된다는 사실이다.
불행히도 프로파일 스크립트로 sys.path에 대해 무엇인가를 수행하여 scriptLibraries 모듈이 로드되지 않도록 하기는 어렵다.
기타 스크립트 라이브러리 사용
이 scriptLibraries 디렉토리가 사용 가능한 유일한 스크립트 라이브러리는 아니다. 또 다른 scriptLibraries나 다양한 scriptLibraries 디렉토리를 지정하려면 목록 13의 4행에 있는 구문이 필요하다.

목록 13. 추가 scriptLibraries 지정
1|C:\IBM\WebSphere\AppServer80\bin>type C:\temp\BobLibraries\trivialModule.py
 2|print '\n%s executed.\n' % __file__
 3|
 4|C:\IBM\WebSphere\AppServer80\bin>wsadmin -conntype none -javaoption 
  |"-Dwsadmin.script.libraries=C:\temp\BobLibraries"
  |
 5|WASX7357I: By request, this scripting client is not connected ...
  6|
 7|c:\temp\BobLibraries\trivialModule.py executed.
  7
 9|WASX7031I: For help, enter: "print Help.help()"
  |
10|wsadmin>for d in sys.path : print d
11|wsadmin>
  |
12|.
13|C:\IBM\WebSphere\AppServer80\optionalLibraries\jython\Lib
14|c:/temp/BobLibraries


표 G. 목록 13 설명
설명 및 주석
1scriptLibrary에 있는 *.py 파일의 내용을 표시하는 데 사용되는 명령
2지정된 모듈 파일의 내용
4wsadmin을 호출하는 행이며, 새 명령행 옵션(즉, "-javaoption …")이 추가되었고 이 행이 너무 길어서 목록에는 여러 개의 행으로 표시되었다는 점에 유의한다.
5wsadmin에 의해 생성된 잘려진 메시지
7지정된 scriptLibraries 디렉토리에 있는 trivialModule.py에 의해 생성된 출력
9wsadmin에 의해 생성된 대화식 세션 메시지
10sys.path 변수의 내용을 표시하는 데 사용되는 명령문
12-14wsadmin 명령행에 지정된 디렉토리가 sys.path 변수의 일부가 되었다는 것을 나타내는 생성된 출력
javaoption 사용
이 명령행 옵션을 사용했을 때 어떤 변화가 생기는지 이해하려면 사실상 wsadmin은 명령 파일(쉘 스크립트)이며 따라서 실행되는 wsadmin 파일은 확장자가 .bat 또는 .sh가 되어야 한다는 사실을 인식해야 한다. 이 명령 파일은 명령행 옵션을 처리한 후, JVM(Java Virtual Machine)을 실행하고 해당 옵션과 클래스 이름을 지정하여 wsadmin 유틸리티의 Java 클래스가 실행되도록 한다. 명령행에 -javaoption이 있다는 것은 바로 다음에 있는 매개변수가 wsadmin 유틸리티에 지정된 옵션이 아니라 JVM에 지정된 옵션의 일부라는 것을 나타낸다.
–Dwsadmin.script.libraries 옵션과 관련해서는 다음과 같은 몇 가지 사항을 알아야 한다.
  • 이 옵션은 다음에 오는 것을 JVM 옵션으로 취하라고 wsadmin 명령행 파일에 지시하는 특수 접두부인 -javaoption 바로 다음에 있어야 한다. -javaoption을 지정하지 않으면 해당 값이 사용자 스크립트 파일의 매개변수로 wsadmin 유틸리티에 전달된다.
  • 백슬래시(\)를 사용하는 것과 연관된 일반적인 문제점이 발생하지 않도록 하기 위해 WebSphere Application Server 제품 문서에서는 Windows 환경에서도 슬래시(/)를 디렉토리 구분 기호로 사용할 것을 권장한다.
wsadmin 스크립트 작성 도구 사용에 기술되어 있듯이 등호(=)가 존재하기 때문에 Windows 환경에서는 완전한 -Dwsadmin.script.libraries 값을 큰따옴표로 둘러싸야 하며, 이 문서에는 다음과 같이 기술되어 있다.
"Windows 운영 체제에서는 옵션에 등호(=)나 세미콜론(;)이 포함되어 있으면 다음과 같이 옵션 주위에 큰따옴표(")를 삽입해야 한다.
wsadmin -javaoption "-Da.b.c=3"
Windows 운영 체제에서는 명령행 인수에 있는 등호(=)나 세미콜론(;)을 공백으로 처리한다. wsadmin 도구를 사용하는 경우에는 공백이 있는 인수를 큰따옴표 표시로 둘러싸야 한다."
scriptLibraries의 순서
프로파일 파일에서 살펴본 바와 같이 scriptLibraries가 수행되는 순서를 이해하는 것이 중요하다. 기본 scriptLibraries는 프로파일 스크립트 파일이 실행되기 전에 실행된다고 알고 있지만, 이러한 scriptLibraries가 사용자 지정 스크립트 라이브러리 대신에 실행되어 사용 가능하게 되는지도 모른다. 이점을 확인하기 위해 스크립트 라이브러리가 실행될 때 로컬 네임스페이스 정보가 표시되는 간단한 스크립트 라이브러리를 작성한다. 이왕 하는 김에 sys.path의 내용을 표시하게 할 수도 있다. 목록 14에는 이러한 작업을 수행하는 스크립트 라이브러리가 표시되어 있다.

목록 14. 간단한 사용자 스크립트 라이브러리
1|C:\IBM\WebSphere\AppServer80\bin>type C:\temp\BobLibraries\myModule.py
 2|print "Enter:", __file__
 3|print '-' * 60
 4|print dir()
 5|print '-' * 60
 6|import sys
 7|for d in sys.path : print d
 8|print '-' * 60
 9|print " Exit:", __file__
10|
11|C:\IBM\WebSphere\AppServer80\bin>wsadmin -javaoption 
  |"-Dwsadmin.script.libraries=C:\temp\BobLibraries"

12|WASX7209I: Connected to process "dmgr" on node ...
13|Enter: C:\temp\BobLibraries\myModule.py
14|------------------------------------------------------------
15|['__doc__', '__file__', '__name__']
16|------------------------------------------------------------
17|.
18|C:\IBM\WebSphere\AppServer80\optionalLibraries\jython\Lib
19|C:/temp/BobLibraries
20|C:/IBM/WebSphere/AppServer80/scriptLibraries/application/V70
21|C:/IBM/WebSphere/AppServer80/scriptLibraries/osgi
22|C:/IBM/WebSphere/AppServer80/scriptLibraries/perfTuning/V70
23|C:/IBM/WebSphere/AppServer80/scriptLibraries/resources/J2C/V70
24|C:/IBM/WebSphere/AppServer80/scriptLibraries/resources/JDBC/V70
25|C:/IBM/WebSphere/AppServer80/scriptLibraries/resources/JMS/V70
26|C:/IBM/WebSphere/AppServer80/scriptLibraries/resources/Provider/V70
27|C:/IBM/WebSphere/AppServer80/scriptLibraries/security/V70
28|C:/IBM/WebSphere/AppServer80/scriptLibraries/servers/V70
29|C:/IBM/WebSphere/AppServer80/scriptLibraries/system/V70
30|C:/IBM/WebSphere/AppServer80/scriptLibraries/utilities/V70
31|------------------------------------------------------------
32| Exit: C:\temp\BobLibraries\myModule.py
33|WASX7031I: For help, enter: "print Help.help()"
34|wsadmin>


표 H. 목록 14 설명
설명 및 주석
1간단한 스크립트 라이브러리 파일(myModule.py)의 내용을 표시할 운영 체제 명령
2-9myModule.py의 내용
11스크립트 라이브러리 디렉토리를 지정하는 데 사용되는 wsadmin 명령행 참고: 행의 길이가 짧은 관계로 목록에서는 여러 개의 행으로 나누어 표시함
12wsadmin에 의해 생성된 잘려진 메시지이며, 배치 관리자 서버에 연결되었다는 것을 나타낸다.
13라이브러리 모듈에서 생성된 출력이며, 모듈의 이름이 처리 중이라는 것을 나타낸다.
14-16라이브러리 모듈에서 생성된 출력이며, 네임스페이스의 내용이 표시되어 있다. wsadmin 스크립팅 오브젝트(예: AdminApp, AdminConfig 등)가 없다는 점에 유의한다.
17-30라이브러리 모듈에서 생성된 출력이며, sys.path의 내용이 표시되어 있다.
32라이브러리 모듈에서 생성된 출력이며, 실행이 완료되었다는 것을 나타낸다.
33wsadmin에 의해 생성된 대화식 세션 메시지이며, wsadmin 환경에 대한 도움말을 얻을 수 있는 방법이 표시되어 있다.
scriptLibraries로 할 수 있는 것
사용자 scriptLibraries는 기본 scriptLibraries보다 먼저 실행되므로 사용자 스크립트 라이브러리 모듈이 있는지 궁금할 수 있다. sys.path 목록에서 기본 scriptLibraries 디렉토리를 제거하여, 기본 scriptLibraries가 처리되어 네임스페이스에 추가되지 않도록 한다. 이렇게 하는 것도 기본 scriptLibraries를 무시할 수 있는 또 다른 방법이다. 목록 15에는 이것을 나타내는 대화식 세션이 표시되어 있다.

목록 15. 처리 중인 기본 scriptLibraries를 사용하지 않게 설정
1|C:\IBM\WebSphere\AppServer80\bin>type C:\temp\BobLibraries\*.py
 2|
 3|C:\temp\BobLibraries\noDefaultScriptLibraries.py
 4|
 5|
 6|import sys
 7|sys.path = [ x for x in sys.path if x.find( 'scriptLibraries' ) < 0 ]
 8|
 9|C:\IBM\WebSphere\AppServer80\bin>wsadmin -javaoption \
10|"-Dwsadmin.script.libraries=C:\temp\BobLibraries"
  |
11|WASX7209I: Connected to process "dmgr" on node ...
12|WASX7031I: For help, enter: "print Help.help()"
  |
13|wsadmin>dir()
  |
14|['AdminApp', 'AdminConfig', 'AdminControl', 'AdminTask', 'Help', 'TypedProxy',
15|'__builtin__', '__doc__', '__name__', 'bsf', 'imp', 'main',
16|'noDefaultScriptLibraries', 'sys']
  |
17|wsadmin>for d in sys.path : print d
18|wsadmin>
  |
19|.
20|C:\IBM\WebSphere\AppServer80\optionalLibraries\jython\Lib
21|C:/temp/BobLibraries
22|wsadmin>


표 I. 목록 15 설명
설명 및 주석
1scriptLibraries 디렉토리에 있는 모든 *.py 파일의 내용을 표시할 운영 체제 명령
3발견된 *.py 파일의 이름
6-7noDefaultScriptLibraries.py 파일의 내용
9-10scriptLibraries 디렉토리를 지정하는 wsadmin 명령
11-12wsadmin에 의해 생성된 출력과 대화식 세션의 메시지이며, 배치 관리자에 연결되었다는 것을 나타낸다.
13명령 프롬프트와 현재 네임스페이스의 내용을 표시할 명령문
14-16현재 네임스페이스의 내용
17sys.path 목록에 있는 현재 값을 표시하는 데 사용되는 명령문
19-21sys.path의 내용이며, 기본 scriptLibraries 항목이 더 이상 존재하지 않는다는 것을 나타낸다.
스크립트 라이브러리 제거
스크립트 라이브러리 항목을 제거하면 문제점이 생길까? 이점은 문제점에 따라 다르다. scriptLibraries 모듈의 sys.path에서 기본 scriptLibraries 값을 동적으로 제거하고 wsadmin 추적을 사용하면(wsadmin.properties의 com.ibm.ws.scripting.traceString 지시문 참조), traceFile(wsadmin.properties의 com.ibm.ws.scripting.traceFile 지시문 참조)에 각 scriptLibraries 모듈의 ImportError가 삽입된다. 이렇게 하면 사용자 scriptLibraries 모듈을 실행하기 전에 처리되는 기본 scriptLibraries 파일의 목록이 wsadmin을 통해 빌드된다. 그리고 생각해 보면 이렇게 하는 것이 합당하다. scriptLibraries 디렉토리를 처리하는 과정에서 디렉토리 계층 구조를 순회하여 sys.path에 추가할 디렉토리를 결정하고, 디렉토리에 확장자가 .py인 파일이 있을 때만 sys.path에 항목을 추가한다. 나중에는 이러한 각 모듈을 대상으로 import 명령문을 실행한다. 분명히 사용자 지정 scriptLibraries 모듈은 이러한 두 단계 사이에서 실행된다.
그러나 기본 scriptLibraries에 관해 알아야 할 내용이 이것만 있는 것은 아니다. 자체 스크립트 라이브러리를 작성하여 사용하려고 하는 경우에는 "-Dwsadmin.script.libraries 옵션이 기능하도록 하려면 scriptLibraries 디렉토리가 WebSphere Application Server 설치 디렉토리 아래에 존재해야 한다"는 경고에 유의해야 한다.
이점이 무엇을 의미하는지 이해하기 위해 목록 16에 있는 대화식 세션을 살펴보도록 하자.

목록 16. scriptLibraries 디렉토리가 누락되는 시점
1|C:\IBM\WebSphere\AppServer80\bin>type \temp\BobLibraries\trivialModule.py
 2|print __file__, 'executed.'
 3|
 4|C:\IBM\WebSphere\AppServer80\bin>wsadmin -javaoption 
  |"-Dwsadmin.script.libraries=C:\temp\BobLibraries"
  |
 5|WASX7209I: Connected to process "dmgr" on node ...
 6|C:\temp\BobLibraries\trivialModule.py executed.
 7|WASX7031I: For help, enter: "print Help.help()"
  |
 8|wsadmin>quit
 9|
10|C:\IBM\WebSphere\AppServer80\bin>ren ..\scriptLibraries scriptLibraries.old
11|
12|C:\IBM\WebSphere\AppServer80\bin>wsadmin -javaoption \
  |"-Dwsadmin.script.libraries=C:\temp\BobLibraries"
  |
13|WASX7209I: Connected to process "dmgr" on node ...
14|WASX7031I: For help, enter: "print Help.help()"
  |
15|wsadmin>dir()
  |
16|['AdminApp', 'AdminConfig', 'AdminControl', 'AdminTask', 'Help', 'TypedProxy',
17|'__builtin__', '__doc__', '__name__', 'bsf', 'imp', 'main', 'sys']
18|wsadmin>quit


표 J. 목록 16 설명
설명 및 주석
1사소한 scriptLibraries 모듈을 표시할 운영 체제 명령
2trivialModule.py의 내용
4scriptLibraries 디렉토리를 지정하는 wsadmin 호출
5wsadmin에 의해 생성된 잘려진 출력이며, 배치 관리자가에 연결되었다는 것을 나타낸다.
6trivialModule.py 스크립트에 의해 생성된 메시지이며, 이 스크립트가 실행되었다는 것을 나타낸다.
7wsadmin에 의해 생성된 대화식 세션 메시지
8wsadmin 프롬프트와, 대화식 세션을 종료하는 데 사용되는 명령
10scriptLibraries 디렉토리의 이름을 바꾸는 데 사용되는 운영 체제 명령
12동일한 scriptLibraries 디렉토리를 지정하는 wsadmin 호출
13-14wsadmin에 의해 생성된 메시지이며, 자체 scriptLibraries 모듈에서는 어떻게 메시지가 생성되지 않았는지 주목한다.
15wsadmin 프롬프트와, 네임스페이스의 내용을 표시하는 데 사용되는 명령
16-17네임스페이스의 내용을 표시하는 출력. 참고: 자체 scriptLibrary 모듈은 표시되지 않았다.
18wsadmin 프롬프트와, 대화식 세션을 종료하는 데 사용되는 명령
scriptLibraries를 사용할 경우에는 같은 이름의 디렉토리(아마도 비어 있는)가 <WAS_HOME> 디렉토리 안에 있어야 한다.
scriptLibraries의 장단점
IBM에서 제공하는 것과 작성하기를 원하는 것 중 어떤 scriptLibraries를 사용할지를 결정하려면 이러한 재사용 기술의 장단점을 알아야 한다.
장점
  • import 명령문을 명시적으로 사용하지 않아도 모든 scriptLibraries 모듈이 자동으로 사용 가능하게 된다.)
  • sys.path 변수에 scriptLibraries 디렉토리를 추가하지 않아도 된다. scriptLibraries 디렉토리가 식별되면, wsadmin 초기화 코드나 시작 코드가 디렉토리 구조를 자동으로 순회하여 확장자가 .py인 파일이 있는 각 디렉토리를 sys.path 변수에 추가한다.
  • 각 modeluName을 자동으로 가져오므로 개발자는 코드를 분리할 수 있고 wsadmin 네임스페이스의 충돌을 최소화할 수 있다.
단점
  • scriptLibraries 디렉토리 구조에 있는 모든 모듈은 실제 사용 여부와 관계없이 네임스페이스에 자동으로 추가된다.
  • scriptLibraries 디렉토리에 있는 모듈 파일을 실행하려면 추가적인 처리가 필요하고 이로 인해 wsadmin 초기화 시간이 느려진다.
  • –javaoption “-Dwsadmin.script.libraries=…" 명령행 옵션을 추가하면 명령행이 상당히 길어지고 이로 인해 읽고 이해하기가 더 어려워진다.
  • scriptLibraries 디렉토리의 구조를 제거하거나 이름을 바꾸면 제품을 업데이트하는 과정이 복잡해지거나 문제점이 발생할 수 있다. (scriptLibraries 디렉토리의 이름을 바꾸는 경우에는 "*$py.class" 파일을 삭제해야 하며, 이렇게 하지 않으면 이 디렉토리를 다시 컴파일할 수 없게 되고 포함된 __file__ 변수의 값이 올바르지 않게 된다.
  • scriptLibrary 모듈을 로드한 파일의 위치를 결정하려면 __file__ 변수의 값을 표시해야 한다.
결국, wsadmin scriptLibraries가 해당 환경에 적합한지 결정해야 한다.
기타 javaoption 값
앞에 목록 9에서는 Jython 명령문을 사용하여 sys.path 변수에 디렉토리를 추가하는 방법을 살펴보았다. wsadmin 명령행에서 이러한 작업을 수행할 수 있게 해주는 또 다른 javaoption이 존재한다. 목록 17의 대화식 wsadmin 세션에는 이러한 옵션이 표시되어 있다.

목록 17. -Dpython.path javaoption
1|C:\IBM\WebSphere\AppServer80\bin>wsadmin -javaoption 
  |"-Dpython.path=C:/temp/BobLibraries;C:/temp/myModules"
 2|WASX7209I: Connected to process "dmgr" on node ...
 3|WASX7031I: For help, enter: "print Help.help()"
  |
 4|wsadmin>for d in sys.path : print d
 5|wsadmin>
 6|.
 7|C:\IBM\WebSphere\AppServer80\optionalLibraries\jython\Lib
 8|C:/temp/BobLibraries
 9|C:/temp/myModules
10|
11|wsadmin>


표 K. 목록 17 설명
설명 및 주석
1–Dpython.path javaoption을 사용하는 방법이 표시된 wsadmin 명령 호출
2-3wsadmin에 의해 생성된 대화식 세션 메시지
4-5sys.path의 값을 표시하는 데 사용되는 명령문
6-9sys.path의 현재 값으로, 여기에는 –Dpython.path javaoption에서 지정한 디렉토리 두 개는 존재하지 않는다.
새로운 wsadmin.properties 지시문
python.path와 wsadmin.script.libraries를 대상으로 -javaoption을 사용할 때 어려운 점 중에 하나는 이 옵션이 너무 길어서 wsadmin 명령행을 읽기가 어렵다는 사실이다. 이러한 지시문을 일부 특성 파일에 삽입하고 싶은 경우에는 이러한 지시문을 해당 wsadmin.properties 파일에 추가할 수 있다. 목록 18에는 이러한 내용이 적용되어 있다.

목록 18. 새로운 지시문 예제
1|C:\IBM\WebSphere\AppServer80\bin>type ..\profiles\Dmgr01\properties\wsadmin.properties
 2|#-------------------------------------------------------------------------
 3|# Properties file for scripting client
 4|#   Cell Manager version
 5|#-------------------------------------------------------------------------
 6|#
 7|...
 8|wsadmin.script.libraries=C:/temp/BobLibraries
 9|python.path=C:/temp
10|
11|C:\IBM\WebSphere\AppServer80\bin>wsadmin
  |
12|WASX7209I: Connected to process "dmgr" on node ...
13|
14|c:\temp\BobLibraries\trivialModule.py executed.
15|
16|WASX7031I: For help, enter: "print Help.help()"
  |
17|wsadmin>for d in sys.path : print d
18|wsadmin>
  |
19|.
20|C:\IBM\WebSphere\AppServer80\optionalLibraries\jython\Lib
21|C:/temp
22|C:/temp/BobLibraries
23|wsadmin>


표 L. 목록 18 설명
설명 및 주석
1wsadmin.properties 파일을 표시할 운영 체제 명령
2-10wsadmin.properties 파일의 첫 번째 행과 마지막 몇 행이 표시되어 있는 잘려진 출력 새 지시문은 이 파일의 마지막 부분에 있다.
11일반적인 wsdamin 명령행
12wsadmin에 의해 생성된 출력이며, wsadmin이 배치 관리자에 연결되었다는 것을 나타내고 있다.
13-15일반적인 scriptLibraries 모듈에 의해 생성된 출력
16wsadmin에 의해 생성된 대화식 세션 메시지
17sys.path의 내용을 표시하는 데 사용되는 명령문
19-22sys.path의 내용. 참고: 이 예제에서는 scriptLibraries 디렉토리가 존재하지만 비어 있다.
결정은 독자의 몫
해당 환경에서 Jython 코드를 어떻게 재사용해야 하는지에 대해 최상의 선택을 하려면 스스로 다음과 질문을 해보아야 한다.
  • 문제점이 있는 오브젝트나 루틴을 얼마나 자주 사용하게 될까? 필요성이 거의 없는 "매우 전문화된" 코드가 일부 있는 경우에는 이 코드를 필요에 따라 스크립트로 가져올 수 있는 모듈에 삽입하는 것이 좋다. 다른 옵션 대신에 모듈을 사용하는 기본적인 이유는 스크립트 작성자에게 import 변종 중 하나를 삽입하게 하면 어디에서 코드가 액세스되고 있는지 더 분명하게 알 수 있기 때문이다.
  • 스크립트에서 코드를 복제해야 할 때가 있나? 그렇지 않다. 스크립트에 오브젝트와 루틴을 복사하여 붙여 넣는 것이 합리적인 경우는 사용 중인 코드가 사소한 것이어서 프로그래밍 기술을 입증할 수 있을 때뿐이다. 이렇게 하지 않으면 불일치되기 쉬운 코드가 여러 위치에 중복되는 결과를 초래하게 된다. 코드가 유용해서 이 코드를 재사용하고 싶은 경우에는 이 코드를 모듈이나 패키지 또는 여기에서 언급한 기사 재사용 기술 중 하나에 삽입한다.
  • 프로파일 스크립트 파일을 사용하는 것이 합당한 때는 언제인가? 앞에서 살펴본 바와 같이 독자와 같은 상황에서는 오브젝트와 루틴이 포함되어 있는 프로파일 스크립트가 커다란 이점이 되지 않으므로 일반적으로 프로파일 파일에 많은 오브젝트를 삽입하는 것은 좋지 않다. 그러나 wsadmin 환경을 사용자 정의하는 프로파일 스크립트가 매우 가치 있게 될 수도 있다. 예를 들어, 모든 Jython 스크립트에서 사용하고 싶은 유틸리티 모듈이 일부 있는 경우에는 wsadmin.properties 파일에서 참조하는 프로파일 스크립트가 앞에서 언급한 import 명령문 변종 중 하나를 배치할 올바른 위치가 될 수도 있다.
  • scriptLibraries가 해당 환경에 적합한가? 이 질문에 정확하게 답변할 수 있을 것이다. 실행되는 모든 스크립트가 모든 스크립트 라이브러리 모듈을 자동으로 가져오기를 원하는가? 이러한 스크립트 라이브러리를 사용 가능하게 하려면 실행되는 모든 스크립트에서 초기화 및 처리 시간이 필요하다. 그러므로 해당 환경에서 이러한 오버헤드를 감수할만한 가치가 있는지를 결정해야 한다. scriptLibrary를 사용하기로 한 경우에는 아마도 wsadmin.script.libraries 지시문을 wsadmin.properties 파일에 추가하고자 할 것이다.
결론
대부분의 개발자들에게는 이러한 기술을 조합하는 것이 유용하다. 필자는 프로파일 스크립트를 사용하여 필자의 환경을 초기화하고 필자의 유틸리티 모듈이 자동으로 가져와지는지 확인한다. 따라서 필자는 자주 사용하는 루틴을 필요할 때면 언제나 사용 할 수 있다.
이 기사를 사용하여 다음과 같은 작업을 수행할 수 있다.
  • wsdamin 환경을 정리하고 더 체계화한다.
  • 초기화 과정에서 처리해야 하는 코드를 제한하여 wsadmin 초기화 시간을 최소화한다.
  • wsadmin 스크립팅 환경에 맞게 작성한 코드를 체계화하고 개선한다. (예를 들면, 코드를 분리하고 더 완전히 문서화한다.)
이 기사에 있는 정보가 독자에게 도움이 되기를 바란다. 또한, 이 기사를 읽는 데 필요한 시간이 유익한 시간이 되었기를 바란다.

참고자료
필자소개
Bob Gibson Bob Gibson은 자문 소프트웨어 엔지니어로, IBM에서 애플리케이션 프로그래머, 아키텍트, 개발자, 지도자, 기술 지원 분석가 및 테스터와 같은 다양한 소프트웨어 관련 역할을 25년 이상 경험했다. 현재는 IBM WebSphere Distributed Application Server를 담당하는 기술 지원 그룹의 팀 리더이다. 그는 버지니아대학교에서 공학 학사학위와 전산학 석사학위를 취득했다.

댓글 없음:

댓글 쓰기