파이썬 패키징 #4 uv: 2026년 표준 워크플로

5 분 소요

여기까지 손으로 해 온 일을 나열해 보면 이렇습니다. venv 만들기, activate, pip install, 버전 기록, 파이썬 버전은 별도 관리. 도구 하나가 이 전부를 맡으면 어떻게 되는지가 이번 글입니다. uv는 2026년 현재 파이썬 프로젝트 관리의 사실상 표준 워크플로가 된 도구입니다. ruff를 만든 Astral이 러스트로 개발했고, 2025년 1.0 릴리스를 거치며 월 다운로드에서 기존 도구들을 추월했습니다. 이 블로그의 테스트·자동화 시리즈, 모던 파이썬 기초 #1이 처음부터 uv를 전제한 이유이기도 합니다. 속도(lock 파일 설치 기준 기존 도구의 수 배〜십수 배)가 유명하지만, 실무 가치는 속도보다 워크플로가 하나로 접히는 것에 있습니다.

설치와 첫 프로젝트: uv init #

uv 자체는 파이썬과 무관한 단일 실행 파일이라 설치가 단순합니다.

설치
# macOS / Linux
curl -LsSf https://astral.sh/uv/install.sh | sh
# 또는
brew install uv

새 프로젝트는 init으로 시작합니다.

프로젝트 생성
uv init invoice-tool
cd invoice-tool

만들어지는 것은 단출합니다. #3에서 본 pyproject.toml, 파이썬 버전을 고정하는 .python-version, 그리고 main.py와 README 정도입니다. .venv는 아직 없습니다. 필요해지는 순간 uv가 알아서 만들기 때문입니다.

add와 sync: 선언과 환경을 항상 일치시킵니다 #

의존성 추가는 add입니다.

의존성 추가
uv add django
uv add --dev pytest ruff

이 한 줄 뒤에서 일어나는 일이 앞 편들의 요약입니다. pyproject.toml의 dependencies(또는 dependency-groups의 dev)에 선언이 기록되고, 전체 의존성이 해석되어 uv.lock에 잠기고, .venv가 없으면 만들어진 뒤 설치까지 끝납니다. 선언(#3), 잠금(#5), 환경(#1)이 명령 하나로 동기화되는 것입니다. 제거는 uv remove django로 대칭입니다.

동료의 저장소를 클론했을 때는 sync 하나입니다.

환경 재현
git clone .../invoice-tool && cd invoice-tool
uv sync

lock 파일 그대로 .venv가 재현됩니다. README에 “파이썬 X.Y를 설치하고, venv를 만들고, activate하고, pip install -r…” 같은 절차 목록이 필요 없어집니다.

run: activate가 필요 없는 실행 #

#1에서 activate의 정체가 PATH 조작일 뿐이라는 것을 봤습니다. uv는 아예 그 단계를 생략하게 해 줍니다.

실행
uv run python main.py
uv run pytest

uv run은 프로젝트의 .venv를 찾아(없으면 만들고, lock과 어긋나 있으면 맞춘 뒤) 그 환경에서 명령을 실행합니다. “activate를 깜빡해서 엉뚱한 환경에 설치했다"는 사고 유형이 구조적으로 사라집니다. 테스트 시리즈에서 uv run pytest를 기본 실행법으로 쓴 배경입니다.

파이썬 버전까지 uv가 관리합니다 #

uv의 관리 범위는 패키지에서 끝나지 않습니다. 파이썬 인터프리터 자체를 내려받아 관리합니다.

파이썬 버전 관리
uv python install 3.13     # 인터프리터 설치
uv python pin 3.13         # 프로젝트에 고정 (.python-version 기록)
uv python list             # 설치·사용 가능 버전 목록

.python-version이 있으면 uv의 모든 명령이 그 버전으로 동작하고, 없는 버전이면 자동으로 받아 옵니다. pyenv가 맡던 자리까지 흡수한 것으로, “파이썬 버전 관리 도구 + 가상 환경 도구 + 패키지 관리자"의 3종 세트가 하나로 줄어듭니다. 시스템 파이썬을 건드리지 않는다는 #1의 원칙도 자연스럽게 지켜집니다.

uvx와 uv tool: 전역 도구의 올바른 설치처 #

#1에서 “시스템 파이썬에 아무것도 설치하지 않는다. 전역 도구는 방법이 따로 있다"고 미뤄 둔 답이 여기입니다.

전역 도구 실행·설치
uvx ruff check .            # 설치 없이 일회성 실행
uv tool install ruff        # 전역 도구로 설치 (격리 환경에)

uvx는 도구를 임시 격리 환경에서 바로 실행하고, uv tool install은 자주 쓰는 도구를 도구별 격리 환경에 설치해 PATH에 노출합니다. 어느 쪽이든 프로젝트 환경도 시스템 파이썬도 오염되지 않습니다. 자동화 #7에서 만든 CLI 같은 자작 도구도 같은 방식으로 설치할 수 있습니다.

기존 프로젝트 마이그레이션 #

requirements.txt로 굴러가던 프로젝트의 이전은 흡수에 가깝습니다.

마이그레이션
uv init --bare              # 기존 코드에 pyproject.toml만 추가
uv add -r requirements.txt  # 목록을 dependencies로 흡수
uv add --dev -r requirements-dev.txt

#2에서 본 freeze형 목록이라면 이 기회에 직접 의존성만 남기고 정리하는 것이 좋습니다. 전이 의존성은 lock이 알아서 관리하므로 선언에 남겨 둘 이유가 없습니다. 반대로 uv를 도입할 수 없는 환경에 맞춰 내보내는 것도 됩니다(uv export --format requirements.txt). 또 pip 명령 체계에 익숙한 손을 위해 uv pip install 같은 저수준 인터페이스도 제공되지만, 프로젝트 관리에서는 add/sync 쪽이 선언·잠금·환경을 함께 맞춰 주는 정식 경로입니다.

정리 #

이번 글에서 다룬 내용입니다.

  • uv는 가상 환경, 패키지 설치, lock, 파이썬 버전 관리를 하나로 묶은 도구이고, 2026년 현재 신규 프로젝트의 사실상 표준입니다
  • uv init으로 시작하고, uv add/uv remove가 선언(pyproject.toml)·잠금(uv.lock)·환경(.venv)을 한 번에 동기화합니다
  • 클론 후에는 uv sync 하나로 환경이 재현되고, uv run은 activate 없이 프로젝트 환경에서 명령을 실행합니다
  • uv python install/pin으로 인터프리터까지 uv가 관리합니다. pyenv 없이 .python-version으로 팀의 파이썬 버전이 고정됩니다
  • 전역 도구는 uvx(일회성)와 uv tool install(상시)로 격리 설치합니다. 시스템 파이썬은 끝까지 건드리지 않습니다
  • 기존 프로젝트는 uv add -r requirements.txt로 흡수하고, freeze형 목록은 직접 의존성만 남기고 정리합니다

다음 글(#5 의존성 잠금)에서는 add 뒤에서 조용히 만들어지던 uv.lock의 내용을 직접 읽습니다. 잠금이 재현성을 보장하는 원리, 업그레이드 전략, 그리고 도구 사이를 잇는 표준 pylock.toml(PEP 751)까지 다룹니다.

X