Uv는 환상적이지만, 패키지 관리 UX는 엉망이다

발행: (2026년 5월 22일 AM 05:56 GMT+9)
8 분 소요

Source: Hacker News

Astral의 uv는 파이썬 세계에 큰 반향을 일으켰으며, 그럴 만한 이유가 있습니다. 엄청나게 빠르고, 파이썬 버전을 손쉽게 다루며, 반 다스의 도구를 하나의 바이너리로 대체합니다. 저는 이전에 이에 대해 여러 기사를 작성한 적이 있습니다.

uv를 사용해 새로운 파이썬 프로젝트를 시작하고 첫 번째 의존성을 추가하는 것은 매우 쉽습니다. 하지만 초기 설정을 넘어 프로젝트 유지 관리 단계—구식 패키지를 확인하고 정기적인 업그레이드를 수행하는 단계—에 들어서면, CLI가 pnpm이나 Poetry 같은 동료 도구들에 비해 놀라울 정도로 투박하게 느껴지기 시작합니다.

오래된 패키지 찾기

JavaScript 프로젝트에서 업데이트가 필요한 패키지를 확인하려면 다음 명령을 실행합니다:

pnpm outdated

이 명령은 오래된 패키지, 현재 버전, 최신 버전, 그리고 제약 조건에 의해 허용되는 버전을 깔끔하고 간결하게 보여줍니다.

uv에는 uv outdated가 없습니다. 대신 다음과 같은 복잡한 명령을 기억해야 합니다:

uv tree --outdated --depth 1

출력 역시 문제가 됩니다. 단순히 오래된 항목만 보여주는 것이 아니라, 전체 최상위 의존성 트리를 표시하고 업데이트 가능한 항목 옆에 작은 주석을 달아줍니다. 50개의 의존성이 있고 그 중 두 개만 오래되었더라도 50줄짜리 목록을 모두 살펴봐야 합니다.

poetry show --outdated 명령을 사용하는 Poetry도 크게 나아지지는 않지만, 최소한 실제로 오래된 패키지만 표시합니다.

기본적으로 안전하지 않은 버전 제약

이는 uv가 pnpm 및 Poetry와 가장 크게 철학적으로 차별되는 부분이며, 프로덕션 안정성에 위험을 초래합니다.

pnpm/Poetry는 어떻게 처리하나요

pnpm add 로 패키지를 추가하면 package.json에 캐럿(^1.23.4) 요구사항을 사용해 기록합니다. 캐럿이 앞에 붙어 있다는 것은 1.x.x 버전이면 모두 허용하지만, 2.0.0 으로는 업데이트되지 않음을 의미합니다.

Poetry도 기본적으로 동일하게 동작하며, 다음과 같은 형식을 사용합니다:

>=1.23.4,=2.13.4",
]

상한이 없다는 점에 주목하세요. uv 입장에서는 pydantic 버전 2, 3, 그리고 100 모두 완전히 허용됩니다.

즉, uv 업데이트는 기본적으로 안전하지 않습니다. 대규모 업데이트를 실행하면 버그 수정만 받는 것이 아니라, 의존성 그래프에 있는 모든 유지관리자가 발표한 모든 파괴적 변경을 자동으로 수용하게 되는 것입니다.

업그레이드 명령의 나쁜 UX

uv에서 실제로 업데이트를 수행하는 명령은 인간보다 기계를 위해 설계된 것처럼 느껴집니다.

pnpm이나 Poetry에서 모든 것을 업데이트하고 싶다면, 간단히 pnpm update 또는 poetry update 명령을 사용합니다. uv에서는 다음과 같이 사용합니다:

uv lock --upgrade

위에서 언급한 “상한선 없음” 문제 때문에 uv lock --upgrade는 핵 옵션입니다. 이는 lockfile에 있는 모든 패키지를 최신 버전으로 전부 업그레이드하며, SemVer 안전성을 무시합니다. 그리고 여기에는 여러분이 들어본 적 없는 깊고 중첩된 의존성까지 포함됩니다! 행운을 빕니다. 어디선가 깨지는 변경이 없기를 바랍니다.

이것이 너무 위험하다는 것을 깨달으면, 특정 패키지만 업그레이드하고 싶을 것입니다. uv tree --outdated --depth 1의 형편없는 출력을 뒤져서 원하는 패키지를 찾은 뒤, 구문은 반복적인 작업이 됩니다.

pnpm이 하는 방법:

pnpm update pydantic httpx uvicorn

uv가 하는 방법:

uv lock --upgrade-package pydantic --upgrade-package httpx --upgrade-package uvicorn

업데이트하려는 패키지가 여러 개일 때마다 --upgrade-package 플래그를 반복해서 써야 한다는 것은 큰 번거로움입니다. uv 명령어들의 UX가 이렇게 형편없는 이유를 이해할 수 없습니다.

희망이 있다: bounds 플래그

다행히 uv는 최근 uv add--bounds 옵션을 도입했습니다:

uv add pydantic --bounds major

이 옵션은 우리가 기대하는 보다 안전한 pydantic>=2.13.4,<3.0.0 제약을 생성합니다. 하지만 현재는 선택적 기능이며, 매번 입력해야 하고 아직은 프리뷰 기능으로 간주됩니다.

--bounds major(또는 유사한 설정)이 기본 동작이 되기 전까지, uv 사용자는 본질적으로 두 가지 나쁜 옵션 중 하나를 선택해야 합니다:

  • 모든 의존성에 대해 상한을 추가하려면 pyproject.toml을 수동으로 편집합니다.
  • uv lock --upgrade가 실수로 깨지는 주요 버전 변경을 가져올까 두려워합니다.

내가 보고 싶은 것

I love uv. Its speed is transformative, and the way it manages Python toolchains is second to none. But as a package manager, the developer experience for maintaining a project is currently a step backward from the tools that came before it.

We need a dedicated uv outdated command that filters noise, a more ergonomic update command that doesn’t require repeating flags, and default version constraints that respect the sanity of Semantic Versioning.

Until then, I’ll be double‑checking every single line of my lockfile changes with a healthy dose of suspicion.

0 조회
Back to Blog

관련 글

더 보기 »

Slumber, TUI HTTP 클라이언트

Keyboard shortcuts - Press ← or → to navigate between chapters - Press S or / to search in the book - Press ? to show this help - Press Esc to hide this help I...

dotnet Framework 수명 주기 도구

Introduction Learn how to create a dotnet Global Tool that lists all .NET Core frameworks with release and end‑of‑life information. 💡 For my other article on...