package — 패키지 로딩과 버전 관리

package — 패키지 로딩과 버전 관리

프로그램이 여러 라이브러리(패키지)를 쓰다 보면 "어떤 버전을 골라 로드할까?"를 관리해야 해요. package 명령은 현재 인터프리터가 사용할 수 있는 패키지와 그것을 로드하는 방법의 간단한 데이터베이스를 유지해서, 애플리케이션이 필요로 하는 올바른 버전이 로드되게 해 줍니다.

출처: Tcl Commands — package

본문

package forget ?package package ...?
package ifneeded package version ?script?
package names
package present package ?requirement...?
package present -exact package version
package provide package ?version?
package require package ?requirement...?
package require -exact package version
package unknown ?command?
package vcompare version1 version2
package versions package
package vsatisfies version requirement...?
package prefer ?latest|stable?

이 명령은 현재 인터프리터가 사용할 수 있는 패키지와 그것을 인터프리터에 로드하는 방법의 간단한 데이터베이스를 유지해요. 각 패키지의 여러 버전을 지원하고, 애플리케이션이 필요로 하는 것에 따라 패키지의 올바른 버전이 로드되도록 준비해요. 이 명령은 버전 충돌도 감지하고 보고해요. 보통 일반 Tcl 스크립트에서는 package requirepackage provide 명령만 호출돼요. 나머지 명령들은 패키지 데이터베이스를 유지하는 시스템 스크립트가 주로 사용해요.

package 명령의 동작은 첫 번째 인수로 결정돼요. 허용되는 형식은 다음과 같아요.

package forget ?package package ...? 각 지정된 패키지에 대한 모든 정보를 이 인터프리터에서 제거해요. package ifneededpackage provide 둘 다가 제공한 정보를 포함해요.

package ifneeded package version ?script? 이 명령은 보통 패키지 데이터베이스를 설정하는 시스템 구성 스크립트에만 나타나요. 특정 패키지의 특정 버전이 필요하면 사용 가능하다는 것, 그리고 script를 실행하면 패키지를 인터프리터에 추가할 수 있다는 것을 나타내요. 스크립트는 이후의 package require 명령을 위해 데이터베이스에 저장돼요. 보통 스크립트는 패키지의 명령에 대한 자동 로딩을 설정한 다음(또는 loadsource를 직접 호출하고), 패키지가 있다는 것을 나타내기 위해 package provide를 호출해요. 단일 패키지의 여러 다른 버전에 대한 정보가 데이터베이스에 있을 수 있어요. 데이터베이스에 이미 packageversion에 대한 정보가 있으면, 새 스크립트가 기존 것을 대체해요. script 인수가 생략되면, packageversion 버전에 대한 현재 스크립트를 돌려주거나, 이 패키지·버전에 대해 package ifneeded 명령이 호출된 적이 없다면 빈 문자열을 돌려줘요.

package names package provide로 버전이 제공되었거나 package ifneeded 스크립트가 있는, 인터프리터의 모든 패키지 이름 목록을 돌려줘요. 목록의 요소 순서는 임의예요.

package present ?-exact? package ?requirement...? 이 명령은 package require와 같지만, 패키지가 아직 로드되지 않았다면 로드하려 시도하지 않아요.

package provide package ?version? 이 명령은 packageversion 버전이 이제 인터프리터에 있다는 것을 나타내기 위해 호출돼요. 보통 ifneeded 스크립트의 일부로 한 번, 패키지가 마침내 로드될 때 패키지 자신이 다시 한 번 호출돼요. 이전의 package provide 명령이 package의 다른 버전을 제공했으면 오류가 발생해요. version 인수가 생략되면 현재 제공된 버전 번호를 돌려주고, 이 인터프리터에서 package에 대해 package provide가 호출된 적이 없으면 빈 문자열을 돌려줘요.

package require package ?requirement...? 이 명령은 보통 특정 패키지의 특정 버전을 쓰려는 Tcl 코드가 호출해요. 인수는 원하는 패키지를 나타내고, 명령은 패키지의 적절한 버전이 인터프리터에 로드되도록 보장해요. 명령이 성공하면 로드된 버전 번호를 돌려주고, 아니면 오류를 생성해요.

적절한 패키지 버전은 아래 "요구사항" 섹션에 정의된 요구사항 중 적어도 하나를 만족하는 버전이에요. 여러 버전이 적절하면 가장 높은 버전의 구현이 선택돼요. 이 마지막 부분은 package prefer로 설정한 선택 모드의 추가 영향을 받아요.

"stable" 선택 모드에서 명령은 요구사항을 만족하는 가장 높은 안정 버전을 선택해요. 요구사항을 만족하는 안정 버전이 없으면, 요구사항을 만족하는 가장 높은 불안정 버전을 선택해요. "latest" 선택 모드에서 명령은 안정성에 관계없이 모든 요구사항을 만족하는 가장 높은 버전을 받아들여요.

패키지 버전이 이미 제공되었다면(package provide 명령 호출로), 그 버전 번호가 요구사항을 만족해야 하고 명령은 즉시 돌아가요. 그렇지 않으면 이전 package ifneeded 명령이 제공한 정보의 데이터베이스를 검색해 패키지의 수용 가능한 버전이 있는지 확인해요. 있으면 가장 높은 수용 가능한 버전 번호의 스크립트가 전역 네임스페이스에서 평가돼요. 그 스크립트는 패키지에 대해 package provide를 호출하는 것을 포함해 패키지를 로드하는 데 필요한 모든 것을 해야 해요. package ifneeded 데이터베이스에 패키지의 수용 가능한 버전이 없고 인터프리터에 package unknown 명령이 지정되어 있으면, 그 명령이 전역 네임스페이스에서 평가돼요. 완료되면 Tcl은 패키지가 이제 제공되었는지 또는 package ifneeded 스크립트가 있는지 다시 확인해요. 이 모든 단계가 패키지의 수용 가능한 버전을 제공하지 못하면 명령은 오류를 돌려줘요.

package require -exact package version 이 형식은 호출자가 package의 주어진 버전만 수용할 때 사용돼요. 이 명령은 package require package version-version과 같아요.

package unknown ?command? 이 명령은 package ifneeded 데이터베이스에서 패키지의 적절한 버전을 찾을 수 없을 때 package require 중에 호출할 "마지막 수단" 명령을 제공해요. command 인수가 주어지면 명령의 첫 부분을 담아요. package require 중에 명령이 호출되면 Tcl은 원하는 패키지 이름과 요구사항을 주는 추가 인수를 하나 이상 붙여요.

예를 들어 commandfoo bar이고 나중에 package require test 2.4가 호출되면, Tcl은 foo bar test 2.4 명령을 실행해 패키지를 로드해요. package require 명령에 요구사항이 제공되지 않으면 호출된 명령에 이름만 추가돼요. package unknown 명령이 command 인수 없이 호출되면 현재 package unknown 스크립트를 돌려주고, 없으면 빈 문자열을 돌려줘요. command가 빈 문자열로 지정되면 현재 package unknown 스크립트를 제거해요(있으면).

package vcompare version1 version2 version1version2가 주는 두 버전 번호를 비교해요. version1version2보다 이전 버전이면 -1, 같으면 0, version1version2보다 이후 버전이면 1을 돌려줘요.

package versions package package ifneeded 명령이 정보를 제공한 package의 모든 버전 번호 목록을 돌려줘요.

package vsatisfies version requirement... version이 주어진 요구사항 중 적어도 하나를 만족하면 1, 아니면 0을 돌려줘요. 요구사항은 아래 "요구사항" 섹션에 정의돼 있어요.

package prefer ?latest|stable? 인수 없이 호출하면 현재 package require가 쓰는 선택 논리 모드를 설명하는 "latest" 또는 "stable"을 돌려줘요. "latest" 인수를 주면 선택 논리 모드를 "latest"로 설정해요. "stable" 인수를 주면, 모드가 이미 "stable"이면 그 값을 유지하고, 모드가 이미 "latest"이면 "stable"로 되돌리려는 시도는 효과가 없어 모드 값이 "latest"로 유지돼요. 다른 값을 인수로 주면 잘못된 인수 오류를 발생시켜요.

인터프리터가 생성될 때 초기 선택 모드 값은 TCL_PKG_PREFER_LATEST 환경 변수가 (어떤 값이든) 설정되어 있지 않으면 "stable"로 설정돼요. 그렇지 않으면 초기(그리고 영구적인) 선택 모드 값이 "latest"로 설정돼요.

버전 번호

버전 번호는 2, 1.162, 3.1.13.1처럼 점으로 구분된 하나 이상의 십진수로 구성돼요. 첫 번째 숫자를 메이저 버전 번호라고 불러요. 더 큰 숫자는 패키지의 더 이후 버전에 해당하고, 왼쪽 숫자일수록 중요도가 커요. 예를 들어 버전 2.1은 1.3보다 이후이고, 3.4.6은 3.3.5보다 이후예요.

빠진 필드는 0과 같아요: 버전 1.3은 1.3.0과 1.3.0.0과 같으므로 1.3.1이나 1.3.0.2보다 이전이에요. 게다가 문자 "a"(알파)와/또는 "b"(베타)는 구분을 위해 점을 대체해 정확히 한 번 나타날 수 있어요. 이 문자들은 의미상 버전에 음수 지정자를 추가하는데, "a"는 -2, "b"는 -1이에요. 각각 한 번만 지정될 수 있고, 지정자에서 "a""b"는 상호 배타적이에요. 따라서 1.3a1은 (의미상) 1.3.-2.1, 1.3b1은 1.3.-1.1이 돼요. 음수는 버전 지정자에서 직접 허용되지 않아요.

위에서 지정한 대로 문자 "a""b"를 포함하지 않는 버전 번호를 안정(stable) 버전이라고 부르고, 문자가 있으면 그 버전을 불안정하(unstable)다고 부르요. 두 버전이 같은 메이저 버전 번호를 가지면, 더 이후의 버전 번호는 더 이전 버전 번호와 위쪽 호환(upwards compatible)된다고 가정돼요. 예를 들어 패키지 버전 2.3용으로 작성된 Tcl 스크립트는 버전 2.3.2, 2.4, 2.5.1에서 변경 없이 동작해야 해요. 메이저 버전 번호의 변경은 호환되지 않는 변경을 뜻해요: 코드가 패키지 버전 2.1을 쓰도록 작성되었다면, 버전 1.7.3이나 3.1에서 수정 없이 동작한다는 보장이 없어요.

패키지 인덱스

Tcl에서 패키지를 쓰는 권장 방법은 스크립트에서 package requirepackage provide 명령을 호출하고, pkg_mkIndex 프로시저로 패키지 인덱스 파일을 만드는 거예요. 이것을 하고 나면 패키지는 package require 명령에 응답해 자동으로 로드돼요. 자세한 내용은 pkg_mkIndex 문서를 참고해요.

요구사항

요구사항 문자열은 패키지의 호환 가능한 버전 번호가 있는지 확인해요. 대부분의 명령은 가장 높은 적절한 버전이 일치되는 요구사항 문자열 목록을 받아들여요.

각 요구사항은 다음 형식 중 어떤 것도 가질 수 있어요:

  • min — 이 형식을 "min-bounded"라고 불러요.
  • min- — 이 형식을 "min-unbound"라고 불러요.
  • min-max — 이 형식을 "bounded"라고 불러요.

여기서 "min""max"는 유효한 버전 번호예요. 옛 문법은 확장 문법의 특수한 경우로, 하위 호환성을 유지해요. 만족에 관한 규칙은:

  • 버전은 만족스러우려면 나열된 요구사항 중 적어도 하나를 통과해야 한다.
  • 버전은 다음 경우에 "bounded" 요구사항을 만족한다: min이 max와 같으면 버전이 min과 같을 때만. 그렇지 않으면 버전이 min보다 크거나 같고 max보다 작을 때만. 여기서 min과 max 둘 다 내부적으로 "a0"으로 패딩된다. min과의 비교는 포함적이지만(max와의 비교는 배타적)이라는 점을 기억하라.
  • "min-bounded" 요구사항은 위장된 "bounded" 요구사항으로, max 부분이 min 부분의 다음으로 높은 메이저 버전 번호로 암시적으로 지정된다. 버전은 위 규칙에 따라 그것을 만족한다.
  • 버전은 min보다 크거나 같을 때만 "min-unbound" 요구사항을 만족하고, 여기서 min은 내부적으로 "a0"으로 패딩된다. 최대값 제약은 없다.

예제

Tcl 스크립트가 Tk와 http 패키지를 요구한다고 나타내려면, 스크립트 맨 위에 이것을 둬요:

package require Tk
package require http

Snack 패키지를 쓸 수 있는지 확인하고 있으면 로드하려면(기능 손실이 치명적이지 않은 선택적 향상에 유용) 이렇게 해요:

if {[catch {package require Snack}]} {
    # Error thrown - package not found.
    # Set up a dummy interface to work around the absence
} else {
    # We have the package, configure the app to use it
}

더 알아보기

  • msgcat, packagens, pkgMkIndex — 패키지·메시지 카탈로그 관련 명령