Skip to content

패키지 인덱스

기본적으로 uv는 의존성 해결과 패키지 설치를 위해 Python Package Index (PyPI)를 사용한다. 하지만 [[tool.uv.index]] 설정 옵션(또는 동일한 커맨드라인 옵션인 --index)을 통해 프라이빗 인덱스를 포함한 다른 패키지 인덱스를 사용하도록 uv를 설정할 수 있다.

인덱스 정의하기

의존성을 해결할 때 추가 인덱스를 포함하려면 pyproject.toml 파일에 [[tool.uv.index]] 항목을 추가한다.

[[tool.uv.index]]
# 인덱스의 선택적 이름
name = "pytorch"
# 인덱스의 필수 URL
url = "https://download.pytorch.org/whl/cpu"

인덱스는 정의된 순서대로 우선순위가 부여된다. 즉, 설정 파일에 나열된 첫 번째 인덱스가 의존성을 해결할 때 가장 먼저 참조된다. 단, 커맨드라인을 통해 제공된 인덱스는 설정 파일의 인덱스보다 우선순위가 높다.

기본적으로 uv는 Python Package Index(PyPI)를 "기본" 인덱스로 포함한다. 이는 다른 인덱스에서 패키지를 찾을 수 없을 때 사용된다. PyPI를 인덱스 목록에서 제외하려면 다른 인덱스 항목에 default = true를 설정하거나 --default-index 커맨드라인 옵션을 사용한다.

[[tool.uv.index]]
name = "pytorch"
url = "https://download.pytorch.org/whl/cpu"
default = true

기본 인덱스는 목록에서의 위치와 상관없이 항상 가장 낮은 우선순위로 간주된다.

인덱스 이름은 알파벳, 숫자, 대시, 언더스코어, 마침표만 포함할 수 있으며 유효한 ASCII 문자여야 한다.

커맨드라인에서 --index 또는 --default-index를 통해 인덱스를 제공하거나 환경 변수(UV_INDEX 또는 UV_DEFAULT_INDEX)를 통해 제공할 때 이름은 선택 사항이지만 <name>=<url> 구문을 사용해 포함할 수 있다.

# 커맨드라인에서
$ uv lock --index pytorch=https://download.pytorch.org/whl/cpu
# 환경 변수를 통해
$ UV_INDEX=pytorch=https://download.pytorch.org/whl/cpu uv lock

패키지를 특정 인덱스에 고정하기

tool.uv.sources 항목에서 인덱스를 지정하면 특정 패키지를 특정 인덱스에 고정할 수 있다. 예를 들어, torch를 항상 pytorch 인덱스에서 설치하도록 하려면 pyproject.toml 파일에 다음과 같이 추가한다:

[tool.uv.sources]
torch = { index = "pytorch" }

[[tool.uv.index]]
name = "pytorch"
url = "https://download.pytorch.org/whl/cpu"

마찬가지로, 플랫폼에 따라 다른 인덱스에서 패키지를 가져오려면 환경 마커를 사용해 소스 목록을 제공할 수 있다:

pyproject.toml
[project]
dependencies = ["torch"]

[tool.uv.sources]
torch = [
  { index = "pytorch-cu118", marker = "sys_platform == 'darwin'"},
  { index = "pytorch-cu124", marker = "sys_platform != 'darwin'"},
]

[[tool.uv.index]]
name = "pytorch-cu118"
url = "https://download.pytorch.org/whl/cu118"

[[tool.uv.index]]
name = "pytorch-cu124"
url = "https://download.pytorch.org/whl/cu124"

인덱스를 explicit = true로 표시하면 해당 인덱스에 명시적으로 고정된 패키지가 아니면 설치되지 않는다. 예를 들어, torchpytorch 인덱스에서 설치하고, 다른 모든 패키지는 PyPI에서 설치하도록 하려면 pyproject.toml 파일에 다음과 같이 추가한다:

[tool.uv.sources]
torch = { index = "pytorch" }

[[tool.uv.index]]
name = "pytorch"
url = "https://download.pytorch.org/whl/cpu"
explicit = true

tool.uv.sources를 통해 참조되는 이름이 지정된 인덱스는 프로젝트의 pyproject.toml 파일 내에서 정의되어야 한다. 커맨드라인, 환경 변수, 사용자 수준 설정을 통해 제공된 인덱스는 인식되지 않는다.

인덱스가 default = trueexplicit = true로 모두 표시된 경우, 해당 인덱스는 명시적 인덱스로 취급되며(즉, tool.uv.sources를 통해서만 사용 가능), 동시에 PyPI를 기본 인덱스에서 제거한다.

여러 인덱스에서 검색하기

기본적으로 uv는 특정 패키지를 찾을 수 있는 첫 번째 인덱스에서 검색을 멈추고, 해당 인덱스에 있는 버전만을 해결 대상으로 삼는다(first-index).

예를 들어, [[tool.uv.index]]를 통해 내부 인덱스를 지정하면, uv는 해당 내부 인덱스에 패키지가 존재할 경우 항상 그 인덱스에서 패키지를 설치하고 PyPI에서는 절대 설치하지 않는다. 이는 "의존성 혼동" 공격을 방지하기 위한 의도다. 공격자가 내부 패키지와 동일한 이름으로 악성 패키지를 PyPI에 게시하면, 내부 패키지 대신 악성 패키지가 설치될 수 있다. 예를 들어, 2022년 12월 발생한 torchtriton 공격이 대표적이다.

사용자는 --index-strategy 커맨드라인 옵션이나 UV_INDEX_STRATEGY 환경 변수를 통해 다른 인덱스 동작을 선택할 수 있다. 이 옵션은 다음과 같은 값을 지원한다:

  • first-index (기본값): 모든 인덱스에서 각 패키지를 검색하되, 패키지가 포함된 첫 번째 인덱스의 후보 버전만을 고려한다.
  • unsafe-first-match: 모든 인덱스에서 각 패키지를 검색하되, 호환 가능한 버전이 있는 첫 번째 인덱스를 우선한다. 다른 인덱스에 더 새로운 버전이 있어도 무시한다.
  • unsafe-best-match: 모든 인덱스에서 각 패키지를 검색하고, 후보 버전 전체에서 가장 적합한 버전을 선택한다.

unsafe-best-match는 pip의 동작과 가장 유사하지만, "의존성 혼동" 공격의 위험에 노출될 수 있다.

인증 정보 제공

대부분의 프라이빗 레지스트리는 패키지에 접근하기 위해 인증을 요구한다. 일반적으로 사용자 이름과 비밀번호(또는 액세스 토큰)를 통해 인증한다.

인덱스와 인증하려면 환경 변수를 통해 인증 정보를 제공하거나 URL에 직접 포함시킬 수 있다.

예를 들어, 사용자 이름(public)과 비밀번호(koala)가 필요한 internal-proxy라는 인덱스가 있다고 가정하자. 먼저 pyproject.toml 파일에 인증 정보 없이 인덱스를 정의한다:

[[tool.uv.index]]
name = "internal-proxy"
url = "https://example.com/simple"

그런 다음 UV_INDEX_INTERNAL_PROXY_USERNAMEUV_INDEX_INTERNAL_PROXY_PASSWORD 환경 변수를 설정한다. 여기서 INTERNAL_PROXY는 인덱스 이름을 대문자로 변환하고, 영숫자가 아닌 문자를 밑줄(_)로 대체한 것이다:

export UV_INDEX_INTERNAL_PROXY_USERNAME=public
export UV_INDEX_INTERNAL_PROXY_PASSWORD=koala

환경 변수를 통해 인증 정보를 제공하면 pyproject.toml 파일에 민감한 정보를 평문으로 저장하지 않아도 된다.

또는 인덱스 정의에 인증 정보를 직접 포함시킬 수도 있다:

[[tool.uv.index]]
name = "internal"
url = "https://public:koala@pypi-proxy.corp.dev/simple"

보안상의 이유로 인증 정보는 uv.lock 파일에 절대 저장되지 않는다. 따라서 uv는 설치 시 인증된 URL에 반드시 접근할 수 있어야 한다.

--index-url--extra-index-url

[[tool.uv.index]] 설정 옵션 외에도, uv는 호환성을 위해 pip 스타일의 --index-url--extra-index-url 커맨드라인 옵션을 지원한다. 여기서 --index-url는 기본 인덱스를 정의하고, --extra-index-url는 추가 인덱스를 정의한다.

이 옵션들은 [[tool.uv.index]] 설정 옵션과 함께 사용할 수 있으며, 동일한 우선순위 규칙을 따른다:

  • 기본 인덱스는 항상 가장 낮은 우선순위로 처리된다. 이는 레거시 --index-url 인자, 권장되는 --default-index 인자, 또는 default = true로 설정된 [[tool.uv.index]] 항목을 통해 정의되었는지 여부와 무관하다.
  • 인덱스는 정의된 순서대로 참조된다. 이는 레거시 --extra-index-url 인자, 권장되는 --index 인자, 또는 [[tool.uv.index]] 항목을 통해 정의되었는지 여부와 무관하다.

실질적으로, --index-url--extra-index-url는 이름이 없는 [[tool.uv.index]] 항목으로 간주할 수 있다. 여기서 --index-urldefault = true가 활성화된 상태이며, 이 맥락에서 --index-url--default-index에 매핑되고, --extra-index-url--index에 매핑된다.