🔥 uv 완전 가이드 (1): 설치부터 스크립트 실행까지
강의 목차

pip install을 치고 나서 터미널을 멍하니 바라본 적이 있다. 패키지 몇 개 설치하는 데 왜 이렇게 오래 걸리는 걸까. 의존성 해석이 빙글빙글 돌고, 가상환경 만들겠다고 python -m venv를 치면 또 몇 초를 기다려야 한다. 그러다 uv를 처음 써본 날, 진심으로 놀랐다. 같은 작업이 체감상 눈 깜짝할 사이에 끝났다.
이 글은 uv를 처음 접하는 사람을 위한 시작 가이드다. 설치부터 Python 버전 관리, 그리고 의존성을 스크립트 안에 직접 선언하는 방법까지 다룬다.
uv가 뭔가
uv는 Astral이 만든 Python 패키지 및 프로젝트 매니저다. Rust로 작성되었고, pip 대비 10~100배 빠르다. 같은 팀이 만든 Python 린터 Ruff를 써본 적 있다면, 그 속도감을 떠올리면 된다.
단순히 빠르기만 한 게 아니다. uv 하나로 이런 것들을 전부 처리할 수 있다:
- Python 버전 설치 및 관리 (
pyenv대체) - 패키지 설치 (
pip대체) - 프로젝트 의존성 관리 (
poetry,pdm대체) - CLI 도구 실행 (
pipx대체) - 스크립트 실행 및 인라인 의존성
- 패키지 빌드와 배포
2026년 4월 현재 최신 버전은 0.11.7이고, GitHub 스타는 83,000개를 넘겼다. 이미 프로덕션에서 널리 쓰이고 있다.
벤치마크
Astral의 공식 벤치마크에 따르면, 캐시가 없는 상태에서 pip보다 8~10배, 웜 캐시 상태에서는 80~115배 빠르다. 가상환경 생성은 python -m venv 대비 최대 80배, virtualenv 대비 7배 빠르다.
숫자를 외울 필요는 없다. 직접 써보면 체감된다. pip으로 수십 초 걸리던 설치가 1~2초 만에 끝나는 경험을 하면 돌아가기 어렵다.
설치
설치는 한 줄이다.
macOS / Linux:
curl -LsSf https://astral.sh/uv/install.sh | shcurl -LsSf https://astral.sh/uv/install.sh | shWindows (PowerShell):
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"Homebrew를 쓴다면:
brew install uvbrew install uv설치 후 버전을 확인해 보자:
uv --version
# uv 0.11.7uv --version
# uv 0.11.7pip로도 설치할 수 있지만, 독립 설치를 권장한다. uv 자체가 Python에 의존하지 않는 단일 바이너리라서, 시스템 Python이 꼬여도 uv는 멀쩡하게 동작한다.
Python 버전 관리
uv의 가장 편리한 기능 중 하나가 Python 버전 관리다. pyenv를 따로 설치할 필요가 없다.
최신 버전 설치
uv python installuv python install이 한 줄이면 최신 안정 버전의 Python이 설치된다. uv는 Astral의 python-build-standalone 프로젝트에서 배포판을 가져온다. 공식 Python에서는 바이너리를 직접 배포하지 않기 때문이다.
설치 후 버전 지정 실행 파일이 PATH에 추가된다:
python3.13 # 이렇게 바로 실행 가능python3.13 # 이렇게 바로 실행 가능python과 python3 명령도 쓰고 싶다면 --default 옵션을 붙인다:
uv python install --defaultuv python install --default특정 버전 설치
# 특정 마이너 버전
uv python install 3.12
# 여러 버전 한 번에
uv python install 3.11 3.12
# PyPy도 된다
uv python install pypy@3.10# 특정 마이너 버전
uv python install 3.12
# 여러 버전 한 번에
uv python install 3.11 3.12
# PyPy도 된다
uv python install pypy@3.10설치된 버전 확인
uv python listuv python list사용 가능한 버전과 이미 설치된 버전을 한눈에 볼 수 있다.
버전 업그레이드
패치 버전 업그레이드도 지원한다 (현재 프리뷰 기능):
# 특정 버전 업그레이드
uv python upgrade 3.12
# 전체 업그레이드
uv python upgrade# 특정 버전 업그레이드
uv python upgrade 3.12
# 전체 업그레이드
uv python upgrade자동 다운로드
사실 Python을 미리 설치하지 않아도 된다. uv는 필요할 때 알아서 Python을 다운로드한다.
# Python 3.12가 없어도 바로 실행된다
uvx python@3.12 -c "print('hello world')"
# 가상환경 생성 시에도 자동 다운로드
uv venv# Python 3.12가 없어도 바로 실행된다
uvx python@3.12 -c "print('hello world')"
# 가상환경 생성 시에도 자동 다운로드
uv venv시스템에 이미 Python이 깔려 있다면 uv가 자동으로 감지해서 사용한다. 별도 설정은 필요 없다. 만약 시스템 Python만 쓰고 싶으면 --no-managed-python 플래그를 넘기면 된다.
스크립트 실행
여기서부터가 진짜 재미있는 부분이다.
기본 실행
간단한 스크립트를 하나 만들어 보자:
# hello.py
print("Hello from uv!")# hello.py
print("Hello from uv!")uv run hello.py
# Hello from uv!uv run hello.py
# Hello from uv!표준 라이브러리만 쓰는 스크립트라면 이게 전부다. 인자도 그대로 넘길 수 있다:
uv run hello.py arg1 arg2uv run hello.py arg1 arg2stdin에서 직접 읽는 것도 가능하다:
echo 'print("hello")' | uv run -echo 'print("hello")' | uv run -외부 패키지가 필요할 때
스크립트에서 외부 패키지를 쓴다면 --with 옵션으로 지정한다:
# progress.py
import time
from rich.progress import track
for i in track(range(20), description="작업 중:"):
time.sleep(0.05)# progress.py
import time
from rich.progress import track
for i in track(range(20), description="작업 중:"):
time.sleep(0.05)uv run --with rich progress.pyuv run --with rich progress.pyuv가 임시 환경을 만들고, rich를 설치하고, 스크립트를 실행한 뒤, 환경을 정리한다. 전부 순식간에 일어난다.
버전 제약도 걸 수 있다:
uv run --with 'rich>12,<13' progress.pyuv run --with 'rich>12,<13' progress.pyPEP 723: 인라인 스크립트 메타데이터
여기가 핵심이다. PEP 723은 Python 스크립트 파일 안에 의존성을 직접 선언하는 표준이다. 매번 --with를 붙이는 대신, 스크립트 자체에 어떤 패키지가 필요한지 적어둘 수 있다.
먼저 스크립트를 초기화한다:
uv init --script example.py --python 3.12uv init --script example.py --python 3.12의존성을 추가한다:
uv add --script example.py 'requests<3' 'rich'uv add --script example.py 'requests<3' 'rich'그러면 스크립트 상단에 이런 메타데이터 블록이 생긴다:
# /// script
# dependencies = [
# "requests<3",
# "rich",
# ]
# ///
import requests
from rich.pretty import pprint
resp = requests.get("https://peps.python.org/api/peps.json")
data = resp.json()
pprint([(k, v["title"]) for k, v in data.items()][:10])# /// script
# dependencies = [
# "requests<3",
# "rich",
# ]
# ///
import requests
from rich.pretty import pprint
resp = requests.get("https://peps.python.org/api/peps.json")
data = resp.json()
pprint([(k, v["title"]) for k, v in data.items()][:10])이제 uv run example.py만 치면 된다. uv가 메타데이터를 읽고, 의존성을 설치하고, 실행까지 알아서 한다. --with를 매번 붙일 필요가 없다.
Python 버전 요구사항도 지정할 수 있다:
# /// script
# requires-python = ">=3.12"
# dependencies = []
# ///
type Point = tuple[float, float]
print(Point)# /// script
# requires-python = ">=3.12"
# dependencies = []
# ///
type Point = tuple[float, float]
print(Point)uv에서는 dependencies 필드가 비어 있더라도 반드시 포함되어야 한다.
의존성 잠금
스크립트 의존성도 잠글 수 있다:
uv lock --script example.pyuv lock --script example.pyexample.py.lock 파일이 생기고, 이후 실행할 때 잠긴 버전을 사용한다. 재현성이 중요한 스크립트라면 꼭 쓰자.
더 엄격하게 재현성을 보장하고 싶다면 exclude-newer 설정을 쓸 수 있다:
# /// script
# dependencies = [
# "requests",
# ]
# [tool.uv]
# exclude-newer = "2023-10-16T00:00:00Z"
# ///
import requests
print(requests.__version__)# /// script
# dependencies = [
# "requests",
# ]
# [tool.uv]
# exclude-newer = "2023-10-16T00:00:00Z"
# ///
import requests
print(requests.__version__)이렇게 하면 uv가 2023년 10월 16일 이전에 릴리스된 패키지만 고려한다. 시간이 지나도 같은 결과를 보장할 수 있다.
실행 가능한 스크립트 만들기
shebang을 추가하면 uv run 없이도 바로 실행할 수 있다:
#!/usr/bin/env -S uv run --script
# /// script
# requires-python = ">=3.12"
# dependencies = ["httpx"]
# ///
import httpx
print(httpx.get("https://example.com"))#!/usr/bin/env -S uv run --script
# /// script
# requires-python = ">=3.12"
# dependencies = ["httpx"]
# ///
import httpx
print(httpx.get("https://example.com"))chmod +x myscript
./myscriptchmod +x myscript
./myscript스크립트를 다른 사람에게 전달할 때, "이 파일 하나만 실행하면 돼"라고 말할 수 있다는 뜻이다. uv가 설치되어 있기만 하면 Python 버전이든 패키지든 알아서 처리된다.
Python 버전 바꿔가며 실행
같은 스크립트를 다른 Python 버전으로 실행하는 것도 간단하다:
uv run example.py # 기본 버전
uv run --python 3.10 example.py # 3.10으로 실행
uv run --python 3.12 example.py # 3.12로 실행uv run example.py # 기본 버전
uv run --python 3.10 example.py # 3.10으로 실행
uv run --python 3.12 example.py # 3.12로 실행필요한 버전이 없으면 uv가 알아서 다운로드한다.
다음 글에서는
여기까지가 uv의 기본기다. Python 설치, 버전 관리, 스크립트 실행까지 — 이전에 pyenv + pip + venv로 따로따로 하던 일을 uv 하나로 끝낼 수 있다.
다음 글에서는 uv로 본격적인 프로젝트를 관리하는 방법을 다룬다. uv init으로 프로젝트를 만들고, 의존성을 관리하고, uvx로 CLI 도구를 실행하는 것까지. 프로젝트 단위로 uv를 쓰면 생산성이 확 달라진다.
시리즈: uv 완전 가이드
참고 자료
- uv 공식 문서 — uv의 전체 기능을 다루는 공식 레퍼런스
- uv GitHub 저장소 — 소스 코드, 이슈 트래커, 릴리스 노트
- PEP 723 – Inline script metadata — 스크립트 내 인라인 의존성 선언 표준
- python-build-standalone — uv가 사용하는 Python 배포판 프로젝트
- Astral 공식 블로그: uv 소개 — Astral이 uv를 처음 발표한 블로그 포스트








