Skip to content

환경 잠금(Locking)

환경 잠금은 ruff와 같은 의존성을 특정 버전으로 고정하고, 그 정확한 버전을 파일에 기록하는 과정이다. 여러 의존성을 다룰 때, 환경을 재현할 수 있도록 정확한 버전을 잠그는 것이 유용하다. 잠금을 사용하지 않으면, 다른 도구를 사용하거나 플랫폼이 달라질 때 의존성 버전이 변경될 수 있다.

의존성 잠금 요구 사항

uv는 requirements.txt 형식으로 의존성을 잠글 수 있다. 일반적으로 pyproject.toml을 사용해 의존성을 정의하는 것을 권장하지만, 다른 의존성 형식도 지원한다. 의존성을 정의하는 방법에 대한 자세한 내용은 의존성 선언 문서를 참고한다.

pyproject.toml에 선언된 의존성을 잠그려면:

$ uv pip compile pyproject.toml -o requirements.txt

기본적으로 uv pip compile의 출력은 화면에 표시되며, 파일에 쓰려면 --output-file 또는 -o 인자가 필요하다.

requirements.in에 선언된 의존성을 잠그려면:

$ uv pip compile requirements.in -o requirements.txt

여러 파일에 선언된 의존성을 잠그려면:

$ uv pip compile pyproject.toml requirements-dev.in -o requirements-dev.txt

uv는 레거시 setup.pysetup.cfg 형식도 지원한다. setup.py에 선언된 의존성을 잠그려면:

$ uv pip compile setup.py -o requirements.txt

stdin에서 의존성을 잠그려면 -를 사용한다:

$ echo "ruff" | uv pip compile -

옵셔널 의존성을 활성화해 잠그려면, 예를 들어 "foo" extra를 사용한다:

$ uv pip compile pyproject.toml --extra foo

모든 옵셔널 의존성을 활성화해 잠그려면:

$ uv pip compile pyproject.toml --all-extras

requirements.in 형식에서는 extras를 지원하지 않는다.

요구사항 업그레이드

출력 파일을 사용할 때, uv는 기존 출력 파일에 고정된 버전을 고려한다. 의존성이 고정된 경우, 이후 컴파일 실행에서 업그레이드되지 않는다. 예를 들어:

$ echo "ruff==0.3.0" > requirements.txt
$ echo "ruff" | uv pip compile - -o requirements.txt
#  파일은 uv에 의해 자동 생성되었으며, 다음 명령어를 사용했습니다:
#    uv pip compile - -o requirements.txt
ruff==0.3.0

의존성을 업그레이드하려면 --upgrade-package 플래그를 사용한다:

$ uv pip compile - -o requirements.txt --upgrade-package ruff

모든 의존성을 업그레이드하려면 --upgrade 플래그를 사용한다.

환경 동기화

의존성은 정의 파일에서 직접 설치하거나 requirements.txt 파일을 컴파일한 후 uv pip install 명령으로 설치할 수 있다. 자세한 내용은 파일에서 패키지 설치 문서를 참고한다.

uv pip install로 설치할 때, 이미 설치된 패키지는 lockfile과 충돌하지 않는 한 제거되지 않는다. 이로 인해 환경에 lockfile에 선언되지 않은 의존성이 존재할 수 있으며, 이는 재현성에 좋지 않다. 환경이 lockfile과 정확히 일치하도록 보장하려면 uv pip sync를 사용한다.

requirements.txt 파일로 환경을 동기화하려면:

$ uv pip sync requirements.txt

pyproject.toml 파일로 환경을 동기화하려면:

$ uv pip sync pyproject.toml

제약 조건 추가하기

제약 조건 파일은 requirements.txt와 유사하지만, 설치되는 패키지의 _버전_만 제어한다. 제약 조건 파일에 패키지를 포함하더라도 해당 패키지가 자동으로 설치되지는 않는다. 제약 조건은 현재 프로젝트의 종속성이 아닌 패키지에 대한 버전 범위를 설정할 때 유용하다.

제약 조건을 정의하려면 패키지에 대한 버전 범위를 지정한다:

constraints.txt
pydantic<2.0

제약 조건 파일을 사용하려면 다음 명령어를 실행한다:

$ uv pip compile requirements.in --constraint constraints.txt

하나의 파일에 여러 제약 조건을 정의할 수 있으며, 여러 파일을 동시에 사용할 수도 있다.

uv는 워크스페이스 루트의 pyproject.toml에서 constraint-dependencies를 읽어 제약 조건 파일에 지정된 내용에 추가한다.

빌드 제약 조건 추가

constraints와 유사하지만, 빌드 시간 의존성을 포함해 런타임 의존성을 빌드할 때 필요한 사항을 특별히 다룬다.

빌드 제약 조건 파일은 requirements.txt와 유사한 파일로, 빌드 시간 요구 사항의 _버전_만을 제어한다. 그러나 빌드 제약 조건 파일에 패키지를 포함하더라도 빌드 시간에 해당 패키지를 설치하지 않는다. 대신, 패키지가 직접적이거나 전이적인 빌드 시간 의존성으로 요구될 때만 제약 조건이 적용된다. 빌드 제약 조건은 현재 프로젝트의 빌드 시간 의존성으로 명시적으로 선언되지 않은 의존성에 대한 범위를 추가하는 데 사용할 수 있다.

예를 들어, 패키지가 빌드 의존성을 다음과 같이 정의한다면:

pyproject.toml
[build-system]
requires = ["setuptools"]
build-backend = "setuptools.build_meta"

빌드 제약 조건을 사용해 작업 공간 내 모든 패키지에 대해 특정 버전의 setuptools를 사용하도록 보장할 수 있다:

build-constraints.txt
setuptools==75.0.0

uv는 작업 공간 루트의 pyproject.toml에서 build-constraint-dependencies를 읽어 빌드 제약 조건 파일에 지정된 내용에 추가한다.

의존성 버전 재정의

오버라이드 파일은 requirements.txt와 유사한 파일로, 특정 의존성의 버전을 강제로 설치하도록 지정한다. 이는 다른 패키지에서 선언한 요구 사항과 상관없이 적용되며, 해결이 불가능한 경우에도 강제로 설치한다.

제약 조건(constraints)이 추가적인 속성을 가진다면, 오버라이드는 절대적인 속성을 가진다. 즉, 다른 패키지의 요구 사항을 완전히 대체한다.

오버라이드는 주로 전이 의존성(transitive dependency)의 상한선을 제거하는 데 사용된다. 예를 들어, ac>=1.0,<2.0을 요구하고 bc>=2.0을 요구할 때, 현재 프로젝트가 ab를 모두 필요로 한다면 의존성 해결이 불가능하다.

문제가 되는 패키지의 새로운 요구 사항을 정의하려면 다음과 같이 오버라이드 파일을 작성한다:

overrides.txt
c>=2.0

오버라이드 파일을 사용하려면 아래 커맨드를 실행한다:

$ uv pip compile requirements.in --override overrides.txt

이제 의존성 해결이 가능해진다. 하지만 ac>=2.0을 지원하지 않는다면, 패키지를 사용할 때 런타임 에러가 발생할 가능성이 있다.

하나의 파일에 여러 오버라이드를 정의할 수 있으며, 여러 파일을 동시에 사용할 수도 있다.