uv는 Python 생태계에 지난 10년간 등장한 최고의 혁신
(emily.space)- Python 설치와 가상 환경 관리를 획기적으로 단순화한 uv는 Python 생태계의 복잡한 환경 설정 문제를 해결함
- Rust로 작성되어 속도와 안정성을 모두 갖추었으며, Python 버전 설치·패키지 관리·의존성 해결을 하나의 명령어로 처리함
-
pyproject.toml을 자동 인식해 프로젝트 환경을 구성하고,uv sync로 팀 간 완전히 동일한 개발 환경을 재현할 수 있음 -
uv run,uv add,uvx등 명령을 통해 가상환경 활성화 없이도 실행, 패키지 추가 및 일회성 실행이 가능함 - Python 설치와 실행 일관성을 확보함으로써, uv는 개발자 생산성과 협업 효율성을 크게 높이는 전환점으로 평가됨
uv 개요
- uv는 Astral이 개발한 무료 오픈소스 Python 관리 도구로, 복잡한 환경 설정 과정을 간소화하는 것을 목표로 함
- Astral은 Ruff와 같은 Python 개발 도구를 만든 팀
- uv는 Python 버전 설치, 패키지 설치, 가상환경 관리, 의존성 해결을 지원하며, 속도 면에서 기존 도구보다 월등히 빠름
- Rust로 개발되어 성능이 매우 뛰어나며, macOS, Linux, Windows 등 거의 모든 플랫폼에서 작동함
설치 및 기본 사용
- 설치는 매우 간단하며,
curl또는 PowerShell 명령어 한 줄로 실행 가능- Linux/Mac:
curl -LsSf https://astral.sh/uv/install.sh | sh - Windows:
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
- Linux/Mac:
- 기존 Python 설치를 변경하지 않기 때문에 안전하게 시도 가능함
프로젝트 환경 관리
- uv는 Python 프로젝트마다 가상 환경을 자동 관리하며,
pyproject.toml파일을 인식해 환경을 설정함-
pyproject.toml에는 Python 버전, 의존성 목록, 프로젝트 이름과 버전 등을 정의함 - 예시:
[project] name = "my_project" version = "1.0.0" requires-python = ">=3.9,<3.13" dependencies = ["astropy>=5.0.0", "pandas>=1.0.0,<2.0"] - 이 방식은 pip보다 더 명확하고 표준화된 환경 정의를 제공함
-
새 프로젝트 생성
-
uv init명령으로 새 프로젝트를 쉽게 생성할 수 있음- 자동으로
pyproject.toml,README.md등 필수 파일을 만듦 -
--bare,--package등의 옵션으로 다양한 초기화 형태 지원 -
uv init --help로 세부 옵션 확인 가능
- 자동으로
기존 프로젝트 동기화
- 프로젝트에
pyproject.toml이 있으면uv sync명령으로 즉시 사용 가능- 자동으로 Python 버전 설치
-
.venv디렉터리에 가상환경 생성 - 모든 패키지의 정확한 버전 정보를 기록한
uv.lock생성
-
uv run명령을 사용하면 환경을 활성화하지 않아도 Python 스크립트를 실행 가능- 예:
uv run myscript.py,uv run jupyter lab
- 예:
의존성 및 Python 버전 관리
-
uv add numpy>=2.0명령으로 의존성을 자동 추가 및 관리 가능-
pyproject.toml을 직접 수정하지 않아도 됨
-
-
uv python pin 3.12.9명령으로 특정 Python 버전을 고정할 수 있어, 환경 재현성이 보장됨
uvx: 빠른 일회성 실행
-
uvx는 별도의 환경 설정 없이 도구를 바로 실행할 수 있는 명령임- 예:
uvx ruff,uvx jupyter lab,uvx --with pandas,pyarrow ipython - 캐시 기반으로 매우 빠르게 재실행 가능, 실험적 작업에 유용함
- 예:
- 덕분에 개발자는 가상환경에 구애받지 않고 임시 실행 환경을 손쉽게 구성할 수 있음
만약 이게 당신에게 설득력이 없다면: 개인적인 메모
-
The Astrosky Ecosystem 개발 중 다수의 OS에서 Python 환경을 통일하는 데 uv를 도입하였음
- 모든 개발자와 서버가 완전히 동일한 Python 설치 및 의존성 버전을 사용하도록 도와줌
- GitHub Actions와 프로덕션 서버 환경에서도 uv가 Python 환경을 관리함
- uv 덕분에 설치와 테스트 환경 불일치 문제가 사라지고, 개발자 간 협업이 단순해짐
결론
- uv는 Python 설치·관리의 복잡성을 근본적으로 해소하며, 개발자들이 동일한 환경에서 안정적으로 협업할 수 있게 함
- 빠른 속도와 Rust 기반 안정성 덕분에, uv는 “지난 10년간 Python 생태계에 일어난 가장 큰 혁신”으로 평가
Hacker News 의견
-
예전엔 Python의 툴링이 충분하다고 들었지만, 이제 Python 개발자들이 npm이나 cargo, bundler 같은 lockfile 기반 생태계를 경험하고 나서 그 장점을 깨닫는 걸 보니 속이 시원해짐
npm에도 문제는 있지만, 일관된 설치와 잠금 파일은 정말 훌륭한 개념임- 다른 사람의 Python 프로젝트를 실행해야 할 때만큼 두려운 일은 없음
이렇게 오랫동안 환경 관리가 불편했다는 게 놀라움 - 왜 이렇게 오래 걸렸는지 궁금함
수많은 시도가 실패한 이유가 단순히 패키지 관리의 난이도 때문인지, 아니면 VC 자금이 필요했기 때문인지 의문임 - 예전부터
pip freeze > requirements.txt와pip install -r requirements.txt를 써왔음
버전 범위를 쓰지 않으면 사실상 requirements.txt가 lockfile 역할을 함
그래서 요즘의 ‘공식 lockfile’ 열풍이 조금 과장된 것 같음 - npm도 한동안 lockfile이 없었음
yarn이 등장하면서 npm이 개선된 게 크다고 봄 - 1998년부터 웹 개발을 해왔는데, npm보다 PNPM이 훨씬 낫다고 생각함
더 빠르고 효율적이며 결정적임
자세한 내용은 pnpm.io/motivation 참고
- 다른 사람의 Python 프로젝트를 실행해야 할 때만큼 두려운 일은 없음
-
UV 스크립트를 이용해 MCP 클라이언트/서버를 단일 파일로 배포할 수 있었음
관련 글: MCP server in a file -
대부분의 스크립트가 단일 파일이라, 맨 위에 아래 코드를 추가하면 삶이 훨씬 단순해짐
#!/usr/bin/env -S uv run --script
이렇게 하면 스크립트가 독립 실행 파일처럼 동작하고, uv가 필요한 모듈을 자동으로 설치해줌- 보안 관점에서 보면 이런 방식은 조금 위험 요소가 있음
스크립트 작성자가 악성 의존성을 숨길 수도 있기 때문임
화이트리스트 기능이 있으면 좋겠음 - 현재 날짜 기준으로 최대 릴리스 날짜 플래그를 쓰면 lockfile 없이 버전을 고정할 수 있음
다만 일부 패키지는 릴리스 날짜를 감지하지 못함 (예: yaml) - 실행하려면 uv가 설치되어 있어야 하므로 완전한 standalone은 아님
-
/usr/bin/env -S를 지원해야 하고, 의존성 이름은uv pip install명령에서 쓰는 배포 패키지명을 써야 함
이는 PEP 723 표준이며 pipx도 지원함 - 인터넷 연결이 필요하고, 저장소 상태에 따라 다른 버전이 설치될 수도 있음
- 보안 관점에서 보면 이런 방식은 조금 위험 요소가 있음
-
uv를 쓰기 전엔 Rust에 관심이 없었는데, uv 덕분에 성능 민감한 코드는 Rust로 옮기게 됨
conda는 완전히 사라졌으면 좋겠음. ML 클러스터에서 conda 환경이 너무 커지고 재현성도 떨어짐- conda 대안으로 Rust 기반의 pixi를 추천받음. uv의 PyPI 솔버를 재사용함
- conda는 의존성을 고정하면 재현성은 있지만, 빌드가 느림
- ML 클러스터라면 컨테이너화가 되어 있어 conda가 필요 없다고 생각함
- uv로 CUDA 의존성 관리를 어떻게 하는지 궁금함
- 대규모 ML 의존성 관리에 대한 오픈소스 접근법은 Metaflow docs와 Fast Bakery 블로그 참고
-
예전엔 pyenv + venv + pip + pipx 조합으로 충분히 만족했지만, uv는
- 의존성 해석 속도가 매우 빠르고
-
uv run,uv add등으로 사용성이 훨씬 좋아졌음 - 여러 툴을 하나로 통합했고
- Python 설치도 간편해짐
-
환경을 활성화하는 대신 명령 앞에
uv를 붙이는 게 훨씬 편함
Python 버전 관리도 쉬워지고, 프로젝트별로 batteries-included 느낌이 있음
아직 장기적으로 안정성은 모르지만 새 프로젝트엔 기본으로 쓰고 있음- 환경 활성화는 단순히 PATH와 프롬프트를 조정하는 것뿐임
uv가 자동으로 환경을 감지하는 걸 싫어하는 사람도 있음
Python 버전 관리의 가치를 잘 모르겠지만, uv로 환경 재생성은 훨씬 빨라짐 -
uv를 붙이면 stateless하게 명령을 실행할 수 있어 협업 시 편함 - mise와 함께 써서 자동 활성화를 하되,
uv접두사는 여전히 유용함 - uv의 철학은 venv는 일회용이라는 것임. 문제 생기면
.venv를 지우면 됨 - 사실 이런 환경 설정은 그냥 “그냥 작동해야 하는” 문제임
- 환경 활성화는 단순히 PATH와 프롬프트를 조정하는 것뿐임
-
이 블로그 글이 내 경험과 거의 일치함
마찰이 줄고 단순해졌음
Python 커뮤니티가 uv를 기본 도구로 채택했으면 함 -
Rust 기반 툴들이 피드백 속도를 완전히 바꿔놓았음
다만 Astral이 수익을 어떻게 내는지 궁금함. 투자도 받았는데 유료 제품이 없음- Astral의 수익 모델은 오픈소스 도구와 통합된 엔터프라이즈 소프트웨어 판매임
예: 사내용 패키지 레지스트리
관련 인터뷰: Charlie Marsh 인터뷰 - 유료 서비스로 발전할 가능성이 있는 제품은 Pyx
- Conda도 “보안 강화 패키지” 접근권만으로 돈을 벌고 있음
Python 개발자가 1천만 명이라면 uv도 충분히 수익화 가능하다고 봄
- Astral의 수익 모델은 오픈소스 도구와 통합된 엔터프라이즈 소프트웨어 판매임
-
개인적으로는 타입 어노테이션과 GIL 제거가 uv보다 더 중요하다고 생각함
uv는 아직 초기 단계라 불편함도 있음. 결국 또 하나의 패키지 관리자일 뿐임- 사람들이 uv를 칭찬하는 이유 중 일부는 사실 pip과 venv가 이제 표준화된 PEP들 덕분에 개선된 결과임
pip의 새 resolver와 wheel 배포 증가가 큰 역할을 했음
관련 글: Wheels are faster for pure Python - 언어 차원에서는 GIL 제거가 더 큰 변화겠지만, 실제로 효용 있는 사례는 아직 많지 않음
- 타입 힌트는 이미 2015년에 도입된 오래된 기능임
- uv는 단순한 패키지 관리자가 아니라 배포 단순화에 큰 가치를 줌
Rust로 작성된 것도 흥미로움. LLVM처럼 다른 언어를 지원하는 구조임
end-user 입장에선 uv가 훨씬 낫고, 유지보수자에게 불편하다면 피드백을 주면 됨 - 타입 어노테이션은 문서화엔 좋지만 실용성은 낮음
엄격 모드가 생기면 성능 향상도 가능하겠지만 언어 철학과 충돌함
그래도 conda가 사라진다면 uv로 옮길 의향은 있음
- 사람들이 uv를 칭찬하는 이유 중 일부는 사실 pip과 venv가 이제 표준화된 PEP들 덕분에 개선된 결과임
-
나는 uv가 마음에 들지 않음
- 너무 많은 걸 하려 함: pip, pyenv, virtualenv, ruff까지 한 번에 대체하려 함
-
uv pip을 써야 해서 완전한 대체도 아님 - Docker와의 호환성도 떨어짐
- 새로운 환경 변수들이 많아 복잡도 증가가 있음
- pyenv, virtualenv, pip이 따로 있는 게 이상하지 않다고 생각함
하지만 pip과 venv도 자주 깨지고 디버깅이 더 어려움 - 사실 pip, pyenv, virtualenv는 항상 함께 쓰이므로 통합 도구가 합리적임
uv는 ruff를 대체하지 않음
환경 변수는 건드릴 필요도 없음 -
uv pip은 pip을 호출하는 게 아니라 호환 인터페이스를 제공함
실제로는 uv가 pip을 대체함
Docker 호환성 문제는 구체적으로 어떤 건지 궁금함 -
uv add,uv sync,uv run으로 관리하면 훨씬 인체공학적이고 빠름
자세한 문서는 uv dependencies 개념 참고 - 내 경험상 uv는 여러 역할을 잘 수행함. 구체적으로 어떤 문제를 겪었는지 궁금함