공식 문서: uv documentation, Installing uv
uv란?
uv는 Python package와 project를 관리하는 도구이다.
Rust로 작성되어 있고, 기존 Python 개발에서 자주 쓰던 여러 도구의 역할을 하나로 묶는 것을 목표로 한다.
공식 문서에서는 uv가 다음 도구들을 대체할 수 있다고 설명한다.
pip
pip-tools
pipx
poetry
pyenv
twine
virtualenv
즉 uv는 단순히 package를 설치하는 도구만은 아니다.
가상환경 생성, 의존성 추가, lockfile 생성, Python version 설치, command line tool 실행까지 다룰 수 있다.
설치
Ubuntu와 macOS에서는 공식 installer를 사용할 수 있다.
curl -LsSf https://astral.sh/uv/install.sh | sh
curl이 없다면 Ubuntu에서는 먼저 설치한다.
sudo apt update
sudo apt install curl
설치 후 version을 확인한다.
uv --version
macOS에서 Homebrew를 사용한다면 다음처럼 설치할 수도 있다.
brew install uv
Python package로 설치하는 것도 가능하다.
pipx install uv
다만 project별 Python 환경과 섞이지 않게 하려면 standalone installer나 pipx처럼 격리된 방식이 좋다.
uv가 해결하는 문제
기존 Python project에서는 보통 여러 도구를 조합한다.
python -m venv .venv
pip install requests
pip freeze > requirements.txt
pipx install ruff
pyenv install 3.12
poetry add fastapi
각 도구는 역할이 분명하지만, 처음 설정할 때는 무엇을 언제 써야 하는지 헷갈릴 수 있다.
uv는 이 흐름을 하나의 CLI로 정리한다.
예를 들어 project를 만들고 dependency를 추가하고 실행하는 흐름은 다음처럼 쓸 수 있다.
uv init my-app
cd my-app
uv add requests
uv run python main.py
가상환경은 필요할 때 자동으로 만들어진다.
project dependency는 pyproject.toml에 기록되고, 재현 가능한 설치를 위해 uv.lock도 생성된다.
새 project 만들기
새 project를 만들려면 uv init을 사용한다.
uv init my-app
cd my-app
대략 다음과 같은 파일이 만들어진다.
my-app/
.python-version
README.md
main.py
pyproject.toml
pyproject.toml은 project metadata와 dependency를 기록하는 파일이다.
requirements.txt가 package 목록 중심이라면, pyproject.toml은 project 자체의 설정까지 담을 수 있다.
dependency 추가
package를 추가하려면 uv add를 사용한다.
uv add requests
그러면 pyproject.toml에 dependency가 추가된다.
동시에 lockfile도 갱신된다.
pyproject.toml
uv.lock
개발용 dependency는 --dev option을 붙인다.
uv add --dev pytest ruff
이렇게 하면 실행에 필요한 package와 개발에만 필요한 package를 구분할 수 있다.
command 실행
project 안에서 command를 실행할 때는 uv run을 사용한다.
uv run python main.py
가상환경을 직접 activate하지 않아도 uv가 project 환경을 사용한다.
uv run pytest
uv run ruff check
물론 기존 방식처럼 가상환경을 활성화해서 사용할 수도 있다.
source .venv/bin/activate
python main.py
하지만 uv run을 쓰면 어떤 Python 환경에서 실행되는지 더 명확해지고, CI에서도 같은 명령을 쓰기 쉽다.
lock과 sync
uv.lock은 dependency resolution 결과를 고정하는 lockfile이다.
다른 컴퓨터나 CI에서 같은 dependency set을 재현할 때 중요하다.
lockfile을 갱신하려면 다음 명령어를 사용한다.
uv lock
현재 환경을 lockfile에 맞추려면 uv sync를 사용한다.
uv sync
일반적인 협업 흐름은 다음과 같다.
dependency 추가: uv add package
lockfile commit: uv.lock commit
다른 환경에서 설치: uv sync
실행: uv run python main.py
즉 uv.lock은 npm의 package-lock.json이나 Poetry의 poetry.lock과 비슷한 역할을 한다.
기존 requirements.txt와 함께 쓰기
uv는 기존 pip workflow와 비슷하게 사용할 수도 있다.
이때는 uv pip interface를 사용한다.
가상환경을 만든다.
uv venv
활성화한다.
source .venv/bin/activate
requirements.txt를 설치한다.
uv pip install -r requirements.txt
현재 환경을 requirements 형식으로 출력할 수도 있다.
uv pip freeze
즉 기존 project가 requirements.txt 기반이어도 바로 pyproject.toml로 옮길 필요는 없다.
처음에는 pip 대신 uv pip를 사용해보는 방식으로 도입할 수 있다.
uv pip compile과 sync
pip-tools를 사용하던 흐름도 uv로 처리할 수 있다.
예를 들어 사람이 관리하는 입력 파일을 requirements.in으로 둔다.
requests
fastapi
이를 고정된 requirements.txt로 compile한다.
uv pip compile requirements.in -o requirements.txt
그리고 환경을 requirements.txt와 정확히 맞춘다.
uv pip sync requirements.txt
install은 package를 추가 설치하는 느낌에 가깝고,
sync는 환경을 lockfile 또는 requirements 파일과 맞추는 느낌에 가깝다.
uv pip install -r requirements.txt
-> 필요한 package 설치
uv pip sync requirements.txt
-> 환경을 requirements.txt와 동기화
재현성을 중요하게 보면 sync가 더 명확하다.
Python version 관리
uv는 Python version도 설치하고 선택할 수 있다.
Python 3.12를 설치한다.
uv python install 3.12
현재 project에서 사용할 Python version을 고정한다.
uv python pin 3.12
그러면 .python-version 파일이 만들어지거나 갱신된다.
3.12
특정 Python version으로 가상환경을 만들 수도 있다.
uv venv --python 3.12
이 기능은 pyenv를 사용하던 일부 workflow를 대체할 수 있다.
다만 system package와 엮인 Ubuntu 기본 Python을 무리하게 바꾸는 대신, project별 Python version을 분리해서 사용하는 것이 좋다.
tool 실행
uvx는 Python package로 배포되는 command line tool을 임시 환경에서 실행한다.
uvx는 uv tool run의 alias이다.
예를 들어 ruff를 설치하지 않고 바로 실행할 수 있다.
uvx ruff check .
자주 쓰는 tool은 설치할 수도 있다.
uv tool install ruff
ruff --version
이 흐름은 pipx와 비슷하다.
project dependency와 전역 CLI tool을 섞지 않기 때문에 환경을 깨끗하게 유지하기 쉽다.
script 실행
작은 single-file script도 uv로 관리할 수 있다.
예를 들어 example.py가 있다고 하자.
import requests
response = requests.get("https://example.com")
print(response.status_code)
script에 dependency metadata를 추가한다.
uv add --script example.py requests
실행한다.
uv run example.py
이 방식은 작은 자동화 script를 만들 때 편하다. project 전체를 만들지 않아도 script가 어떤 dependency를 필요로 하는지 파일 안에 기록할 수 있다.
Docker에서 사용하기
Docker image에서도 uv를 사용할 수 있다.
Ubuntu base image 기준 예시는 다음과 같다.
FROM ubuntu:24.04
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update \
&& apt-get install -y --no-install-recommends curl ca-certificates \
&& rm -rf /var/lib/apt/lists/*
RUN curl -LsSf https://astral.sh/uv/install.sh | sh
ENV PATH="/root/.local/bin:$PATH"
WORKDIR /app
COPY pyproject.toml uv.lock ./
RUN uv sync --frozen
COPY . .
CMD ["uv", "run", "python", "main.py"]
--frozen은 lockfile을 변경하지 않고 그대로 사용하겠다는 의미이다.
CI나 Docker build에서는 dependency가 몰래 바뀌지 않게 하는 것이 좋다.
requirements.txt 기반 project라면 다음처럼 쓸 수 있다.
COPY requirements.txt .
RUN uv venv && uv pip sync requirements.txt
pip와 uv 비교
pip와 uv는 겹치는 부분이 있지만 같은 범위의 도구는 아니다.
| 항목 | pip | uv |
|---|---|---|
| package 설치 | 가능 | 가능 |
| 가상환경 생성 | python -m venv 필요 | uv venv |
| lockfile | 직접 제공하지 않음 | uv.lock |
| project dependency 관리 | 제한적 | uv add, uv sync |
| Python version 설치 | 불가 | 가능 |
| CLI tool 격리 실행 | 보통 pipx 사용 | uvx, uv tool |
| 속도 | 일반적 | 빠른 편 |
기존 project에서는 uv pip install -r requirements.txt부터 시작하면 부담이 적다.
새 project라면 uv init, uv add, uv run, uv sync 흐름을 쓰는 것이 더 자연스럽다.
자주 쓰는 명령어
| 명령어 | 의미 |
|---|---|
uv init my-app | 새 project 생성 |
uv add requests | dependency 추가 |
uv add --dev pytest | 개발용 dependency 추가 |
uv run python main.py | project 환경에서 command 실행 |
uv lock | lockfile 생성 또는 갱신 |
uv sync | 환경을 lockfile과 동기화 |
uv venv | virtual environment 생성 |
uv pip install -r requirements.txt | requirements 설치 |
uv pip freeze | 설치 package 출력 |
uv python install 3.12 | Python 3.12 설치 |
uv python pin 3.12 | project Python version 고정 |
uvx ruff check . | tool을 임시 환경에서 실행 |
언제 쓰면 좋은가?
uv는 다음 상황에서 특히 편하다.
새 Python project를 빠르게 시작하고 싶을 때
requirements.txt보다 재현성 있는 lockfile을 쓰고 싶을 때
pip, venv, pipx, pyenv를 따로 관리하기 귀찮을 때
CI나 Docker build에서 dependency 설치 시간을 줄이고 싶을 때
여러 Python version을 project별로 관리하고 싶을 때
반대로 아주 단순한 script 하나만 실행하거나, 이미 조직에서 Poetry나 Conda workflow를 강하게 쓰고 있다면 바로 바꾸지 않아도 된다.
이 경우에는 uv pip부터 부분적으로 도입하는 것이 현실적이다.
정리
uv는 빠른 Python package manager이면서 project manager이다.
핵심 흐름은 다음과 같다.
uv init my-app
cd my-app
uv add requests
uv run python main.py
uv sync
기존 requirements.txt project에서는 다음처럼 시작할 수 있다.
uv venv
source .venv/bin/activate
uv pip install -r requirements.txt
새 project에서는 pyproject.toml과 uv.lock을 중심으로 관리하고,
기존 project에서는 uv pip interface로 점진적으로 도입하는 방식이 좋다.