# uv는 훌륭하지만 패키지 관리 UX는 엉망이다

> Clean Markdown view of GeekNews topic #29806. Use the original source for factual precision when an external source URL is present.

## Metadata

- GeekNews HTML: [https://news.hada.io/topic?id=29806](https://news.hada.io/topic?id=29806)
- GeekNews Markdown: [https://news.hada.io/topic/29806.md](https://news.hada.io/topic/29806.md)
- Type: GN+
- Author: [neo](https://news.hada.io/@neo)
- Published: 2026-05-24T03:35:34+09:00
- Updated: 2026-05-24T03:35:34+09:00
- Original source: [loopwerk.io](https://www.loopwerk.io/articles/2026/uv-ux-mess/)
- Points: 2
- Comments: 1

## Topic Body

- **uv**는 빠른 속도, Python 버전 관리, 단일 바이너리 통합이 강점이지만 유지보수 단계의 패키지 관리 UX는 아직 투박함
- 오래된 패키지는 `uv pip list --outdated`로 확인할 수 있지만 **최상위 명령**이 아니라 pip 호환 네임스페이스 아래 있어 발견성이 낮음
- `uv add pydantic`은 기본적으로 `pydantic>=2.13.4`처럼 **상한 없는 제약**을 추가해 메이저 버전 상승까지 허용함
- 전체 업그레이드는 `uv lock --upgrade`로 처리되고, 여러 특정 패키지는 **`--upgrade-package` 반복**이 필요해 명령이 장황해짐
- `add-bounds = "major"` 설정으로 더 안전한 기본 제약을 줄 수 있지만 프리뷰 기능이며, 애플리케이션에는 더 직관적인 업데이트 UX가 필요함

---

### uv의 강점과 유지보수 단계의 불편함
- Astral의 [uv](https://docs.astral.sh/uv/)는 **빠른 속도**, Python 버전 관리, 여러 도구를 단일 바이너리로 대체하는 점에서 강점을 가짐
- 새 Python 프로젝트를 시작하고 첫 의존성을 추가하는 흐름은 쉽지만, 프로젝트가 **유지보수 단계**에 들어가면 오래된 패키지 확인과 정기 업그레이드 UX가 pnpm이나 Poetry보다 투박하게 느껴짐
- 핵심 불편은 오래된 패키지 확인 명령의 발견성, 기본 버전 제약의 상한 부재, 업그레이드 명령의 장황함에 있음

### 오래된 패키지 확인
- JavaScript 프로젝트에서는 `pnpm outdated`로 오래된 패키지, 현재 버전, 최신 버전, 제약 조건상 허용되는 버전을 간결하게 확인할 수 있음
- uv에는 최상위 `uv outdated` 명령이 없고, 처음에는 다음 명령이 대안으로 쓰였음

```bash
$ uv tree --outdated --depth 1
```

- `uv tree --outdated --depth 1`은 오래된 항목만 걸러내지 않고 **최상위 의존성 트리 전체**를 출력한 뒤, 업데이트 가능한 항목 옆에 작은 주석을 붙임
- 의존성이 50개이고 오래된 패키지가 2개뿐이어도 50줄 목록을 훑어야 함
- Poetry의 `poetry show --outdated`도 명령 이름은 덜 직관적이지만, 실제 출력은 **오래된 패키지만** 보여줌

### 기본 버전 제약의 위험성
- ## pnpm과 Poetry의 기본 방식
  - `pnpm add`는 `package.json`에 `^1.23.4` 같은 **캐럿 요구사항**을 기록함
  - `^1.23.4`는 1.x.x 버전을 허용하지만 2.0.0으로는 업데이트하지 않음
  - Poetry도 기본적으로 `>=1.23.4,<2.0.0` 같은 형식을 사용하며, 표기는 덜 읽기 쉽지만 효과는 같음
  - 두 도구에서는 패키지가 SemVer를 지킨다는 전제에서 `pnpm update`나 `poetry update`를 실행해도 **주요 API 변경**으로 빌드가 깨질 가능성을 줄일 수 있음
- ## uv의 기본 방식
  - `uv add pydantic`은 `pyproject.toml`에 다음처럼 상한 없는 제약을 추가함

```toml
dependencies = [
    "pydantic>=2.13.4",
]
```

  - 이 제약에서는 pydantic 2, 3, 100 버전이 모두 허용됨
  - 대량 업데이트를 실행하면 버그 수정만 받는 것이 아니라, 의존성 그래프의 모든 유지관리자가 배포한 **호환성 깨짐 변경**까지 받아들일 수 있음
  - 특히 애플리케이션 유지보수에서는 안정성 위험으로 이어질 수 있음

### 업그레이드 명령의 UX
- pnpm과 Poetry에서 전체 업데이트는 각각 다음처럼 간단함

```bash
$ pnpm update
$ poetry update
```

- uv에서는 전체 업그레이드에 다음 명령을 사용함

```bash
$ uv lock --upgrade
```

- `uv lock --upgrade`는 `uv update`나 `uv upgrade`가 아니라 lock 명령의 옵션으로 동작해, 사람이 쓰는 패키지 관리 명령으로는 덜 직관적임
- 상한 없는 제약과 결합되면 `uv lock --upgrade`는 lockfile의 모든 패키지를 **절대 최신 버전**으로 올리는 선택이 됨
- 이 업데이트에는 직접 알지 못하는 깊은 중첩 의존성도 포함될 수 있음
- 특정 패키지만 업데이트하려면 pnpm은 다음처럼 패키지 이름을 나열하면 됨

```bash
$ pnpm update pydantic httpx uvicorn
```

- uv에서는 각 패키지마다 `--upgrade-package` 플래그를 반복해야 함

```bash
$ uv lock --upgrade-package pydantic --upgrade-package httpx --upgrade-package uvicorn
```

- 여러 패키지를 한 번에 올릴 때 **반복 플래그**가 큰 번거로움으로 작용함

### `--bounds` 플래그와 설정
- uv에는 최근 `uv add`를 위한 `--bounds` 옵션이 추가됨

```bash
$ uv add pydantic --bounds major
```

- 이 명령은 더 안전한 제약인 `pydantic>=2.13.4,<3.0.0`을 생성함
- `--bounds major`는 현재 **프리뷰 기능**이며, 명령마다 직접 입력해야 하는 opt-in 기능임
- 이후 `pyproject.toml`에 기본값을 한 번 설정할 수 있음이 드러남

```toml
[tool.uv]
add-bounds = "major"
```

- 이 설정을 사용하면 매번 `--bounds major`를 입력하지 않아도 이후 `uv add`에서 더 합리적인 기본값을 얻을 수 있음
- 애플리케이션에서는 이 동작이 기본값인 편이 더 낫지만, 실제 사용 편의성은 처음 묘사된 것만큼 나쁘지 않음

### 애플리케이션과 라이브러리의 차이
- Python 패키징의 표준 조언은 PyPI에 배포되는 **라이브러리**가 상한을 고정하지 않는 것이며, 이 조언은 타당함
- 모든 라이브러리가 상한을 고정하면 하위 소비자의 의존성 트리가 해소되지 않을 수 있음
- 반대로 **애플리케이션**은 의존성 그래프의 말단 노드이며 다른 사용자가 그 제약을 기준으로 해소하지 않음
- 애플리케이션에서는 상한을 두는 비용이 없고, 예기치 않은 메이저 버전 상승으로부터 보호받을 수 있음
- 여기서의 범위는 웹사이트, 서비스, 내부 도구 같은 애플리케이션 유지보수이며, 라이브러리 배포에는 상한 없는 기본값이 합리적일 수 있음

### 정정된 부분과 남는 문제
- `uv pip list --outdated`를 사용하면 오래된 패키지만 필터링해서 볼 수 있음

```bash
$ uv pip list --outdated
```

- 이로 인해 `uv tree --outdated --depth 1`의 **시끄러운 출력**에 대한 비판은 약해짐
- 남는 문제는 이 기능이 최상위 명령이 아니라 `pip` 호환 네임스페이스 아래에 있어 **발견성**이 낮다는 점임
- `add-bounds = "major"` 설정으로 기본 bounds를 지정할 수 있어, 상한을 매번 직접 편집하거나 위험을 감수해야 한다는 양자택일 구도는 맞지 않음
- 그래도 해당 기능은 프리뷰이며, 애플리케이션 패키지 관리에서는 더 안전한 기본 제약과 더 직관적인 업데이트 명령이 필요함

### 바라는 개선 방향
- 오래된 패키지만 명확히 보여주는 **전용 `uv outdated`** 명령이 필요함
- 여러 패키지를 업데이트할 때 플래그를 반복하지 않아도 되는 더 인체공학적인 `update` 명령이 필요함
- 기본 버전 제약은 의미적 버전 관리(SemVer)의 안정성 기대를 더 잘 반영해야 함
- 현재 상태에서는 lockfile 변경의 각 줄을 의심하며 확인해야 하는 부담이 남음

## Comments



### Comment 58120

- Author: neo
- Created: 2026-05-24T03:35:35+09:00
- Points: 1

###### [Hacker News 의견들](https://news.ycombinator.com/item?id=48228788) 
- `uv add`의 기본 버전 범위는 **영구 설정**으로 지정할 수 있어서 매번 넘길 필요가 없음  
  참고: [https://docs.astral.sh/uv/reference/settings/#add-bounds](<https://docs.astral.sh/uv/reference/settings/#add-bounds>)  
  기본으로 상한을 넣지 않는 이유는 생태계에 불필요한 충돌을 많이 만들기 때문이고, Poetry를 쓰던 시절 관련 자료도 모아둔 적이 있음: [https://github.com/zanieb/poetry-relax#references](<https://github.com/zanieb/poetry-relax#references>)
  - 라이브러리를 배포할 때 **상한 버전 제거**가 중요하다는 건 이해되지만, 글은 라이브러리가 아니라 웹사이트를 만드는 입장에서 쓴 것임  
    웹 프로젝트에서 의존성을 쓸 때는, 의존성이 SemVer를 지킨다는 전제하에 깨지는 변경을 막기 위해 상한이 있기를 원함
  - Haskell 커뮤니티도 이 문제로 여러 해 씨름했고, 한때 가장 성공적이었던 접근은 **Stackage**였음  
    방어적 상한을 넣지 않도록 장려하고, 생태계의 활발한 큰 부분을 매 릴리스마다 지속적으로 빌드해서 실제 호환성 문제를 찾았으며, 소유자에게 자동 알림을 보내고 다음 "LTS" 릴리스에 남기 위한 명확한 일정을 제공했음  
    지금은 Cabal 해석기만으로도 꽤 안정적인 듯하지만, 넓은 범위의 야간 빌드와 눈에 보이는 실패·차단이 생태계를 계속 해석 가능하게 유지하는 데 도움이 됐을 것 같음
  - `add-bounds` 설정을 이제 알게 됐고, 정확한 의존성 고정이 중요하지만 경험이 적은 개발자가 놓치기 쉬운 프로젝트, 특히 라이브러리가 아닌 **최종 제품**에 유용함
  - `--native-tls` 플래그를 영구적으로 설정하는 방법이 있는지 궁금함  
    직장의 Zscaler 설정 때문에 이 플래그 없이는 UV가 항상 실패함  
    또 특정 아키텍처에 맞는 호환 Python 버전을 지정하는 기능을 지원할 계획이 있는지도 궁금함. 회사에서 유지하는 패키지 하나는 32비트 Python을 써야 해서 늘 `--python /path/to/32bit`를 넘겨야 함
  - 약간 덜 다듬어진 질문일 수 있지만, uv가 `pyproject.toml`의 `exclude-newer`를 존중하게 할 방법이 있는지 궁금함  
    `uv run`을 실행하면 `pyproject.toml`에서 `exclude-newer`가 제거됨  
    매번 `uv run —-frozen`이나 `uv run --exclude-newer`를 실행할 수는 있겠지만 그게 맞는 흐름 같지는 않고, 놓치고 있는 관용적인 방식이 있는지 궁금함

- `uv`는 단일 해석 결과가 필요하므로 **상한이 없는 것**은 의도된 설계임  
  npm은 트리의 서로 다른 부분에 다른 해석 결과를 설치할 수 있지만 Python에서는 그게 선택지가 아님. Rye에서도 같은 결정을 해야 했고, 여기에는 더 나은 해법이 없음  
  상한을 넣으면 실제로는 더 이상 해석할 수 없는 트리가 생길 수 있음. Python의 일부 패키지 생태계는 과거에 잘못된 상한을 가정해 배포된 오래된 패키지에 대한 override까지 배포했음  
  오늘 시점에서는 아직 릴리스되지 않은 패키지와 자신의 패키지가 호환될지 아닐지 알 수 없음
  - 개인적으로는 업데이트할 때 패키지들이 호환되지 않는다는 오류를 `uv`에서 받고, 필요하면 override할 수 있는 편이 더 낫다고 봄  
    런타임에서 추적하기 어려운 버전 비호환 오류를 만나는 것보다 나음
  - `pyproject.toml`에 상한이 없는 게 진짜 문제는 아님  
    진짜 문제는 `uv lock —-upgrade`가 상한이 없는 모든 것을 **일괄 업그레이드**한다는 점임  
    메이저 버전을 올리지 않고 패키지를 업그레이드하는 방법이 있다면 이 명령은 훨씬 안전해질 것임
  - uv가 상황을 많이 개선하긴 했지만, 근본적으로 도구만으로는 해결할 수 없는 부분이 꽤 있을 것 같음  
    uv 이전과 비교하면 엄청나게 나아졌지만, 생태계 전체가 깨지는 변경을 어느 정도 하지 않는 한 완전히 좋아지기는 어려워 보임. Python 2에서 3으로 넘어가던 일을 생각하면 당분간 그런 변화에 대한 욕구도 크지 않을 것 같음
  - 라이브러리 작성자에게는 그 말이 맞지만, 웹사이트를 만들고 여러 패키지에 의존할 때는 업그레이드 시 안전하고 싶어서 **상한**을 원함  
    `—-bound` 플래그는 도움이 되지만, 입력하고 기억해야 할 것이 하나 더 늘어남  
    uv가 해당 프로젝트가 라이브러리가 아니라는 걸 알 수 있다면 기본으로 상한을 넣는 방식도 가능하지 않을까 싶음
  - 사실 uv든 npm이든 제대로 쓰는 방식은 전부 `=`로 바꾸고, 메이저가 아닌 업데이트는 안 깨질 거라고 믿지 말고 **수동으로만 업데이트**하는 것임

- 운영 중인 앱에 **Python 의존성 257개**가 있고, 그중 절반 이상이 직접 의존성임  
  `pyproject.toml`에는 상한을 두지 않고, 2주마다 GitHub Actions로 `uv lock --upgrade`를 실행함  
  테스트 커버리지가 좋아서 깨지면 테스트가 실패하고, AI 보조 검토 흐름도 있음. 업그레이드 PR이 만들어지면 AI 워크플로가 Python 스크립트로 메이저·마이너 버전 업데이트를 나열하고, 변경 로그를 찾아 링크하고 요약하며, 코드베이스에서 해당 패키지를 어떻게 쓰는지 기반으로 각 패키지의 위험도를 분석함  
  대체로 고통이 거의 없고, 패키지를 하나씩 올리거나 오래된 패키지를 확인하거나 방치된 의존성을 처리할 필요가 없음. 의존성 작성자의 수정이 필요해서 코드에서 해결할 수 없는 경우는 매우 드물며, 대략 1년에 한 번 정도임. 지난 3개월 동안은 메이저 버전 상승이 18건 있었고, 그중 코드 변경이 필요했던 건 하나뿐이었음  
  프론트엔드에서도 이렇게 하고 싶지만, 안전하게 돌릴 만큼 테스트가 충분하지 않음. 백엔드 테스트는 작성하기 쉽고 더 중요하므로 모든 코드베이스가 갖춰야 한다고 봄. 테스트가 있다면 그냥 전부 자동 업그레이드할 수 있음
  - 테스트 작성은 **AI 에이전트**가 잘하는 일이기도 함  
    적어도 자연어 지시를 정확한 테스트로 바꾸는 데는 뛰어남  
    한동안 테스트를 직접 손으로 쓰지 않았고, 예전에는 늘 불평하던 일이었는데 이제는 아님

- UV는 Python에 많은 걸 해줬지만, 오늘은 꽤 씨름했음  
  여러 저장소에 흩어져 있고 시간이 지나며 구현이 제각각 달라진 스크립트를 중앙에서 관리하려고 했음  
  생각한 방식은 `uv run --with $package main --help`였고, 자동으로 1) 없으면 설치 후 실행, 2) 최신이면 설치하지 않음, 3) 최신이 아니면 업데이트를 하고 싶었음  
  그런데 세 가지 모두 예상보다 까다로웠음. 기본적으로 `uv run`은 매번 다시 설치했고, 가상환경과 설치에 6초가 걸렸음  
  `uvx`나 `uv tool`도 별로 낫지 않았는데, 사용자가 업그레이드를 받지 못하는 새 문제가 생겼음  
  결국 스크립트가 CodeArtifact에 페이지네이션 GET을 날려 더 새 비개발 버전이 있으면 업데이트하고 다시 실행하게 만들었음. 동작은 하고, 6초보다 200ms 지연이 낫지만 원하던 경험은 아니었음
  - `uv run --with $package main --help`는 말한 동작을 아주 적은 오버헤드로 해야 해서 조금 혼란스러움  
    매번 재설치하지 않고, `--with` 환경은 캐시에 저장되어 유지됨. 환경이 캐시되지 않았더라도 의존성은 캐시되고, 캐시에서 설치하면 매우 빠름. 확실히 200ms 미만이어야 함  
    재현 예제를 자세히 열어주면 살펴볼 수 있음
  - 그 용도라면 `uv tool install`과 `uv tool upgrade`가 맞아 보임  
    다만 이런 종류의 작은 불편은 비교적 쉽게 해결할 수 있을 것 같으니 이슈를 열어주면 좋겠음
  - 파일 맨 위의 문서 블록에 필요한 의존성을 정의한 뒤 `uv run main`만 실행할 수도 있음  
    그러면 필요한 의존성을 자동으로 설치·캐시하고 실행함: [https://docs.astral.sh/uv/guides/scripts/](<https://docs.astral.sh/uv/guides/scripts/>)
  - 사용자가 그냥 `uv tool upgrade`를 실행하면 되지 않나 싶음
  - [https://copier.readthedocs.io/en/stable/](<https://copier.readthedocs.io/en/stable/>)도 확인해볼 만함  
    정확히 같은 사용 사례인지는 모르겠지만, polyrepo 마이크로서비스 생태계를 동기화하는 데는 아주 좋았음

- 오래된 의존성 목록을 보려고 `"uv tree --outdated --depth 1"`을 추천한 게 꽤 놀라웠음  
  개인적으로는 도입된 이후 `"uv pip list --outdated"`를 써왔음  
  다만 이 정도로 중요한 명령은 별도의 **최상위 하위 명령**을 가질 만하다는 데 동의함
  - 글쓴이 입장에서는 추천이라기보다 자신이 아는 유일한 방법이었음  
    `"uv pip list --outdated"`가 훨씬 나은 출력을 주는 건 맞고, 고마움  
    그런데 오래된 패키지를 보는 방법이 2개나 있고 출력이 크게 다르다는 점 때문에 UX가 엉망이라는 생각도 듦
  - `"uv tree -od1"`도 아마 동작할 것 같음  
    다만 pacman 같은 패키지 관리자에 대한 비판도, apt처럼 자주 쓰는 명령에는 사람이 이해하기 쉬운 명령을 제공해야 한다는 점이었음

- 제목의 “엉망”이라는 표현에 비해, 예시는 인자를 몇 개 더 써야 하는 정도임  
  더 나은 제목은 **UV에 있었으면 하는 삶의 질 개선** 정도가 맞아 보임
  - 그 표현과 “누가 이 명령줄 인터페이스를 설계했나” 같은 문구는 관심과 클릭을 위한 것으로 보임  
    피드백 자체는 유용하고 대부분 동의하지만, 그런 문구는 피드백의 가치를 낮추고 방어적인 반응을 부름  
    uv의 명령줄 인터페이스가 개인적으로도 번거롭지만, 왜 이렇게 작성됐는지는 이해됨

- `uv`는 훌륭하지만, 현재 Python 패키징의 가장 큰 문제는 여전히 **과학·머신러닝 패키징**을 제대로 처리하는 것임  
  PyTorch를 설치하고 싶다면 어떤 버전인지, CUDA인지부터 따져야 함. CUDA라면 CUDA 버전별로 6가지 버전이 있고 휠도 PyPI에 올리기엔 너무 커서 직접 받아야 함  
  Conda는 이 문제를 부분적으로만 해결함. Spack은 극도로 구성 가능하고 필요한 C/C++/Fortran 의존성과 컴파일러 도구체인을 갖출 수 있어 최고 성능을 뽑아내기 좋지만, uv 등과 잘 통합되지 않음. 그래서 연구자가 만든 실험적 머신러닝 프로젝트를 프로덕션까지 가져가기가 어렵다
  - 예전에는 Anaconda로 우회했지만, 따라오는 잡다한 것들이 너무 많고 개발 환경이 운영 환경과 전혀 달라져서 그것도 별로였음  
    결국 다시 앞에서 말한 상황으로 돌아오게 됨

- 유용한 피드백이 많지만 클릭베이트식 표현이 섞여 있음  
  `pnpm outdated`에 대해서는 그동안 별로 자주 나오지 않았지만 합리적인 요구로 보임. Python과 JavaScript 문화 차이에서 온 듯함. Python 의존성이 취약하거나 깨지지 않는 한 오래됐는지 신경 쓴 적은 거의 없지만, JavaScript 생태계에서는 기회가 될 때 업그레이드하는 일이 꽤 흔한 듯함. 이게 나쁘다는 뜻은 아니고, 큰 프로그래밍 커뮤니티 사이에서 명령줄 인터페이스에 무엇을 드러낼지에 대한 직관이 얼마나 다를 수 있는지 보여줌  
  Armin이 말했듯 uv의 상한 동작은 의도적이고, Python 해석 방식상 기능적으로 필요한 부분임. 이는 Python이 다른 언어와 비교해 선택한 절충이지만, 의존성 트리에 각 의존성이 하나씩만 있고 서로 얽힌 모든 요구사항이 거기에 맞춰 해석된다는 점에서 좋은 절충이라고 봄  
  `uv lock --upgrade`가 그렇게 되어 있는 이유는 사용자 자신의 요구사항이 아니라 **잠금 파일**을 업그레이드하기 때문임. 반면 `pnpm update`는 `package.json`의 사용자 요구사항을 업데이트하는 것으로 보임. 혼란스러울 수는 있지만, `uv lock` 아래에 두는 편이 더 정확함. 그렇지 않으면 `uv upgrade`가 각자 생각하는 업그레이드를 하지 않는다고 혼란스러워하는 사용자가 생길 것임. 그래도 더 깔끔하게 드러낼 여지는 있고, 요구사항 자체도 직접 업그레이드하는 uv 하위 명령에 대한 사용자 요구가 분명히 있었음  
  [https://news.ycombinator.com/item?id=48230048](<https://news.ycombinator.com/item?id=48230048>)
  - 오래된 패키지와 상한에 대해서는 동의하지만, 사용자가 인터페이스가 어렵다고 불평한다면 분명 무언가 있는 것임  
    `uv lock` 명령이 잠금 파일만 다루는 건 말이 되지만, 사용자는 직접·전이 의존성을 업그레이드해야 하는 실제 요구가 있음. 전이 의존성은 `uv lock --upgrade-package`로 가능하지만 조금 장황함. 직접 의존성에도 동작하지만 `pyproject.toml`은 건드리지 않고, 이 파일이 개발자에게 훨씬 더 눈에 잘 띔  
    `uv.lock`의 패키지 버전이 `pyproject.toml`보다 앞서가면, `pyproject.toml`은 의존성 표면적을 파악하는 안내서로서 덜 믿을 만해짐. 친절한 `uv upgrade` 명령이 있으면 좋겠음  
    지금까지 본 uv UX의 가장 큰 함정은 `uv pip`임. 많은 프로젝트가 개발에는 `pyproject.toml`과 `uv.lock`으로 uv를 올바르게 쓰면서, 배포 Dockerfile이나 CI 도구에서는 `uv pip install -r pyproject.toml`을 써서 `uv.lock`을 우회함  
    코딩 에이전트가 학습 데이터에 `pip`가 너무 많아 나쁜 `uv pip` 패턴을 추천하는 것도 문제지만, uv도 사용자를 보호할 장치를 제공해야 함  
    uv는 훌륭한 도구이고 더 많이 쓰여야 한다고 봄: [https://aleyan.com/blog/2026-why-arent-we-uv-yet](<https://aleyan.com/blog/2026-why-arent-we-uv-yet>)
  - 글쓴이 입장에서는 “클릭베이트식”으로 보였다면 유감이지만, 실제로는 **네덜란드식 직설과 솔직함**일 뿐임  
    `poetry update`도 잠금 파일을 업데이트함. uv CLI 구성 방식은 작업하기 꽤 성가시다고 생각함. 정확성과 기계를 위해 설계됐지, 사용자 친화성을 위해 설계된 느낌은 아님
  - pip에서 uv로 넘어온 입장에서는 그 정보가 필요할 때 `uv pip list --outdated`로 돌아가게 됨
  - `uv upgrade`는 로드맵에 있음  
    아직 하지 않은 이유는 훌륭한 경험으로 만들기 어렵고, 사람들이 예상하는 것보다 뉘앙스가 훨씬 많으며, 팀은 작고 우선순위는 많기 때문임
  - `pnpm outdated`류 기능의 용도 중 하나는 `"uv sync --update"`나 `"uv lock --update"`를 실행하면 무엇이 업데이트될지 보는 것임  
    다만 그 명령들에 확인 프롬프트를 두는 편이 더 나을 수도 있음

- Pixi는 uv를 백엔드로 쓰고, 오래된 패키지를 보기 좋게 나열하는 작업 별칭을 쉽게 추가할 수 있어서 UI가 마음에 들었음  
  특히 **Pixi-diff-to-markdown**은 자동 CI 패키지 업데이트를 훑어보기 쉽게 해줌  
  오래된 패키지 중 업데이트될 항목을 보고 싶다면 프로젝트에 이런 작업 별칭을 만들 수 있음  
  `pixi task add outdated "pixi update --dry-run --json | pixi exec pixi-diff-to-markdown"`  
  그리고 프로젝트에서 `pixi run outdated`를 실행하면 됨  
  출력은 업데이트될 패키지, 기존 버전, `pixi update` 명령으로 설치될 새 버전을 담은 읽기 쉬운 Markdown 표임. 물론 취향과 상황에 따라 다를 수 있음

- 최근 `env` 스크립트가 경로에 나타나서 평범한 UNIX `env` 명령 사용을 방해했음  
  알고 보니 uv 설치 프로그램이 아래 명령을 실행할 때 이걸 만듦  
  `curl -LsSf [https://astral.sh/uv/install.sh](<https://astral.sh/uv/install.sh>) | sh`  
  `$HOME/.cargo/bin/`에 설치하고, `$HOME/.cargo/env`에 셸 스크립트를 만들어 `$HOME/.cargo/bin/`이 `PATH`에 없으면 앞에 붙이는 식임  
  기본 UNIX 명령을 이런 식으로 덮어쓰는 코드를 어떤 프로그래머들이 작성하는 건지 이해하기 어려움
